17 #define LIBAVL_PAVL 11
18 #define LIBAVL_PBST 12
20 #define LIBAVL_RTAVL 14
21 #define LIBAVL_RTBST 15
22 #define LIBAVL_RTRB 16
23 #define LIBAVL_TAVL 17
24 #define LIBAVL_TBST 18
33 # error "`TREE' not defined or bungled constant setting"
34 #elif TREE == XYLA_AVL
37 # define WANT_HEIGHT 1
38 # define TREE__NAME(name) XYLA_AVL_##name
39 # define tree__name(name) xyla_avl_##name
44 # define WANT_HEIGHT 1
45 # define TREE__NAME(name) XYLA_RB_##name
46 # define tree__name(name) xyla_rb_##name
48 #elif TREE == XYLA_SPLAY
52 # define TREE__NAME(name) XYLA_SPLAY_##name
53 # define tree__name(name) xyla_splay_##name
55 #elif TREE == XYLA_TREAP
59 # define TREE__NAME(name) XYLA_TREAP_##name
60 # define tree__name(name) xyla_treap_##name
62 #elif TREE == QPTRIE_QP
68 #elif TREE == QPTRIE_FN
74 #elif TREE == SGT_TREE234
76 #elif TREE == LIBAVL_AVL
79 # define tree__name(name) avl_##name
80 #elif TREE == LIBAVL_BST
83 # define tree__name(name) bst_##name
84 #elif TREE == LIBAVL_RB
87 # define tree__name(name) rb_##name
88 #elif TREE == LIBAVL_PAVL
91 # define tree__name(name) pavl_##name
92 #elif TREE == LIBAVL_PBST
95 # define tree__name(name) pbst_##name
96 #elif TREE == LIBAVL_PRB
99 # define tree__name(name) prb_##name
100 #elif TREE == LIBAVL_RTAVL
102 # define USE_LIBAVL 1
103 # define tree__name(name) rtavl_##name
104 #elif TREE == LIBAVL_RTBST
106 # define USE_LIBAVL 1
107 # define tree__name(name) rtbst_##name
108 #elif TREE == LIBAVL_RTRB
110 # define USE_LIBAVL 1
111 # define tree__name(name) rtrb_##name
112 #elif TREE == LIBAVL_TAVL
114 # define USE_LIBAVL 1
115 # define tree__name(name) tavl_##name
116 #elif TREE == LIBAVL_BST
118 # define USE_LIBAVL 1
119 # define tree__name(name) tbst_##name
120 #elif TREE == LIBAVL_TRB
122 # define USE_LIBAVL 1
123 # define tree__name(name) trb_##name
124 #elif TREE == MLIB_SYM
126 # include <mLib/sym.h>
127 # include <mLib/unihash.h>
129 # error "unknown `TREE' value"
133 # define NODE tree__name(node)
134 # define PATH tree__name(path)
135 # define ITER tree__name(iter)
136 # define TREE_NODEPFX TREE__NAME(NODEPFX)
137 # define TREE_NODEUSFX TREE__NAME(NODEUSFX)
138 # define TREE_CHECK tree__name(check)
139 # define TREE_LOOKUP tree__name(lookup)
140 # define TREE_PROBE tree__name(probe)
141 # define TREE_INITITER tree__name(inititer)
142 # define TREE_NEXT tree__name(next)
143 # define TREE_INSERT tree__name(insert)
152 # define TABLE tree__name(table)
153 # define TRAVERSER tree__name(traverser)
154 # define TREE_CREATE tree__name(create)
155 # define TREE_DESTROY tree__name(destroy)
156 # define TREE_PROBE tree__name(probe)
157 # define TREE_FIND tree__name(find)
158 # define TREE_T_INIT tree__name(t_init)
159 # define TREE_T_NEXT tree__name(t_next)
164 # error "`QPTRIE_ITER' not defined or bungled constant setting"
165 # elif QPTRIE_ITER == QPITER_FANF
166 # elif QPTRIE_ITER == QPITER_MDW
167 # elif QPTRIE_ITER == QPITER_LIST
169 # error "unknown `QPTRIE_ITER' value"
185 #elif TREE == MLIB_SYM
187 # define WORDPTR(node) (SYM_NAME(node))
188 # define WORDLEN(node) (SYM_LEN(node))
190 #if TREE == MLIB_SYM || (USE_QPTRIE && QPTRIE_ITER == QPITER_LIST)
195 # define WORDPTR(node) ((node)->w.p)
196 # define WORDLEN(node) ((node)->w.n)
198 struct node *down, *right, *up;
200 # define CHLEN(node) ((node)->chlen)
205 static void bail(const char *msg, ...)
210 va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap);
212 if (pos >= 0) fprintf(stderr, " (input pos = %ld)", pos);
217 #if USE_XYLA || TREE == SGT_TREE234 || USE_LIBAVL
219 static int compare_words(const char *a, size_t alen,
220 const char *b, size_t blen)
224 ord = memcmp(a, b, alen <= blen ? alen : blen);
225 if (!ord) ord = alen < blen ? -1 : alen > blen ? +1 : 0;
233 union nodeu { struct node node; TREE_NODEUSFX; };
235 static int word_nav(struct xyla_bt_nodecls *cls,
236 const struct xyla_bt_node *nn, void *arg)
238 const struct word *k = arg;
239 const struct node *node = (struct node *)nn;
241 return (compare_words(k->p, k->n, WORDPTR(node), WORDLEN(node)));
245 struct xyla_bt_node *root = 0; \
246 union nodeu *nodeu; \
250 # define INIT do ; while (0)
252 # if TREE == XYLA_TREAP
253 # define EXTRA_NODE_SETUP do { node->trp.wt = rand(); } while (0)
255 # ifndef EXTRA_NODE_SETUP
256 # define EXTRA_NODE_SETUP do ; while (0)
258 # define INSERT do { \
259 if (TREE_PROBE(0, &root, word_nav, &word, &path)) { \
260 fprintf(stderr, ";; duplicate `%s'\n", buf); \
261 free(node); node = 0; \
264 nodeu = (union nodeu *)node; \
265 TREE_INSERT(0, &path, &nodeu->T); \
270 for (TREE_INITITER(root, &it); node = TREE_NEXT(&it), node; )
272 # if TREE == XYLA_SPLAY
273 # define FOCUS do { xyla_splay_splay(0, &path); } while (0)
275 # define FOCUS do ; while (0)
278 # define LOOKUP TREE_LOOKUP(0, &root, word_nav, &word)
281 while (node = xyla_bt_severfirst(&root), node) free(node); \
285 # define CHECK do ; while (0)
288 static const void *word_key(struct xyla_bt_nodecls *cls,
289 const struct xyla_bt_node *nn)
290 { struct node *node = (struct node *)nn; return (&node->w); }
292 static void word_ident(struct xyla_bt_nodecls *cls,
293 const struct xyla_bt_node *nn, FILE *fp)
294 { struct node *node = (struct node *)nn; fprintf(fp, "`%s'", node->w.p); }
296 static const struct xyla_bt_chkops word_ops = {
297 { sizeof(word_ops), 0 },
298 { word_nav, word_key },
299 { xyla_bt_chkorder, sizeof(struct xyla_bt_ordinfo), word_ident }
301 struct xyla_bt_nodecls word_cls = { &word_ops.node };
303 # define CHECK do { \
304 if (TREE_CHECK(&word_cls, &root, stderr, 0 HARG(-1), 0)) \
305 bail("check failed"); \
311 # if QPTRIE_ITER == QPITER_FANF
312 # define my_Tnextl Tnextl
316 # define INSERT_LIST do ; while (0)
317 # elif QPTRIE_ITER == QPITER_MDW
321 # define INSERT_LIST do ; while (0)
323 # if TREE == QPTRIE_QP
325 static bool my_Tnextl(Tbl *tbl, const char **k_inout, size_t *sz_inout,
328 const char *k = *k_inout;
329 size_t sz = *sz_inout;
340 while (isbranch(t)) {
341 __builtin_prefetch(t->branch.twigs);
342 b = twigbit(t, k, sz);
343 TWIGOFFMAX(off, max, t, b);
344 if (!hastwig(t, b)) return (false);
346 if (off + 1 < max) resume = t + 1;
348 /* if (strcmp(k, t->leaf.key) != 0) return (false); */
349 t = resume; if (!t) return (false);
352 while (isbranch(t)) t = twig(t, 0);
353 *k_inout = k = t->leaf.key; *sz_inout = strlen(k); *val_out = t->leaf.val;
357 # elif TREE == QPTRIE_FN
359 static bool my_Tnextl(Tbl *t, const char **k_inout, size_t *sz_inout,
362 const char *k = *k_inout;
363 size_t sz = *sz_inout;
373 while (isbranch(t)) {
374 __builtin_prefetch(t->ptr);
375 i = t->index; b = twigbit(i, k, sz);
376 TWIGOFFMAX(off, max, i, b);
377 if (!hastwig(i, b)) return (false);
378 t = Tbranch_twigs(t) + off;
379 if (off + 1 < max) resume = t + 1;
381 /* if (strcmp(k, Tleaf_key(t)) != 0) return (false); */
382 t = resume; if (!t) return (false);
384 while (isbranch(t)) t = Tbranch_twigs(t);
385 *k_inout = k = Tleaf_key(t); *sz_inout = strlen(k);
386 *val_out = Tleaf_val(t);
391 # error "no mdw `Tnextl' for this QP trie variant"
393 # elif QPTRIE_ITER == QPITER_LIST
395 struct node *all = 0, **all_tail = &all
396 # define INSERT_LIST do { \
397 node->next = 0; *all_tail = node; all_tail = &node->next; \
405 # define INIT do ; while (0)
407 # define INSERT do { \
408 tbl = Tsetl(tbl, node->w.p, node->w.n, node); \
412 # if QPTRIE_ITER == QPITER_LIST
414 for (next = all; node = next, node; next = next->next)
417 for (cur.p = 0, cur.n = 0; \
418 my_Tnextl(tbl, &cur.p, &cur.n, &v) ? node = v, 1 : 0; )
421 # define FOCUS do ; while (0)
423 # define GETPREFIX do { \
424 word.n = node->w.n - 1; assert(word.n < WORDMAX); \
425 memcpy(buf, node->w.p, word.n); buf[word.n] = 0; \
428 # define LOOKUP Tgetl(tbl, buf, word.n)
430 # if QPTRIE_ITER == QPITER_LIST
432 for (node = all; node; node = next) { \
433 tbl = Tsetl(tbl, node->w.p, node->w.n, 0); \
434 next = node->next; free(node); \
441 cur.p = 0; cur.n = 0; my_Tnextl(tbl, &cur.p, &cur.n, &v); \
442 tbl = Tsetl(tbl, cur.p, cur.n, 0); free(v); \
447 # define CHECK do ; while (0)
449 #elif TREE == SGT_TREE234
451 static int node_cmp(void *a, void *b)
453 const struct node *na = a, *nb = b;
455 return (compare_words(WORDPTR(na), WORDLEN(na),
456 WORDPTR(nb), WORDLEN(nb)));
459 static int word_cmp(void *k, void *n)
461 const struct word *word = k;
462 const struct node *node = n;
464 return (compare_words(word->p, word->n, WORDPTR(node), WORDLEN(node)));
471 # define INIT do { root = newtree234(node_cmp); } while (0)
473 # define INSERT do { \
474 if (add234(root, node) != node) { \
475 fprintf(stderr, ";; duplicate `%s'\n", buf); \
476 free(node); node = 0; \
480 # define ITERATE for (i = 0; node = index234(root, i), node; i++)
482 # define FOCUS do ; while (0)
484 # define LOOKUP find234(root, &word, word_cmp)
487 while (node = delpos234(root, 0), node) free(node); \
491 # define CHECK do ; while (0)
495 static int node_cmp(const void *a, const void *b, void *arg)
497 const struct word *wa = a, *wb = b;
499 return (compare_words(wa->p, wa->n, wb->p, wb->n));
502 static void free_node(void *n, void *arg) { free(n); }
506 struct TRAVERSER it; \
510 tab = TREE_CREATE(node_cmp, 0, 0); \
511 if (!tab) bail("out of memory"); \
514 # define INSERT do { \
515 p = TREE_PROBE(tab, node); if (!p) bail("out of memory"); \
517 fprintf(stderr, ";; duplicate `%s'\n", buf); \
518 free(node); node = 0; \
523 for (TREE_T_INIT(&it, tab); node = TREE_T_NEXT(&it), node; )
525 # define FOCUS do ; while (0)
527 # define LOOKUP TREE_FIND(tab, &word)
529 # define FREE do { TREE_DESTROY(tab, free_node); } while (0)
531 # define CHECK do ; while (0)
533 #elif TREE == MLIB_SYM
537 struct node *all = 0, **all_tail = &all; \
541 unihash_setkey(&unihash_global, getpid()); \
545 # define PREPNODE do ; while (0)
547 # define INSERT do { \
548 node = sym_find(&tab, buf, word.n, sizeof(*node), &foundp); \
550 node->next = 0; *all_tail = node; all_tail = &node->next; \
552 fprintf(stderr, ";; duplicate `%s'\n", buf); \
553 free(node); node = 0; \
557 # define ITERATE for (next = all; node = next, node; next = next->next)
559 # define FOCUS do ; while (0)
561 # define LOOKUP sym_find(&tab, word.p, word.n, 0, 0)
563 # define FREE do { sym_destroy(&tab); } while (0)
565 # define CHECK do ; while (0)
570 # define PREPNODE do { \
571 node = malloc(sizeof(*node) + word.n + 1); \
572 if (!node) bail("out of memory"); \
573 node->w.p = (char *)(node + 1); \
574 memcpy(node + 1, buf, word.n + 1); node->w.n = word.n; \
579 # define GETPREFIX do { \
580 word.p = WORDPTR(node); word.n = WORDLEN(node) - 1; \
585 static void print_chain(struct node *node)
588 fputs(WORDPTR(node), stdout);
589 if (node->down) { putchar(' '); print_chain(node->down); }
593 fputs(WORDPTR(node), stdout);
594 if (node->down) { putchar(' '); print_chain(node->down); }
595 node = node->right; if (!node) break;
596 fputs(" | ", stdout);
605 struct node *node, *parent, *winners, **winners_tail, *next;
608 int ch, max, nlen, plen;
613 if (!fgets(buf, WORDMAX, stdin)) break;
614 word.n = strlen(buf); assert(word.n);
615 if (buf[word.n - 1] == '\n') buf[--word.n] = 0;
616 else if (word.n == WORDMAX - 1) bail("word too long");
617 else if (ch = getchar(), ch != EOF) bail("short read, found `%c'", ch);
620 if (node) { node->up = node->down = node->right = 0; CHLEN(node) = 1; }
625 max = 0; winners_tail = &winners;
629 /* fprintf(stderr, ";; ponder `%.*s'\n", WORDLEN(node), WORDPTR(node)); */
630 if (WORDLEN(node) <= 1)
634 /* fprintf(stderr, ";; search `%.*s'\n", word.n, word.p); */
635 parent = LOOKUP; if (!parent) continue;
637 node->up = parent; nlen = CHLEN(node);
642 { max = nlen; *winners_tail = 0; winners_tail = &winners; }
643 *winners_tail = node; winners_tail = &node->right;
647 plen = CHLEN(parent); nlen++;
650 else if (plen == nlen) {
651 node->right = parent->down; parent->down = node;
654 parent->down = node; node->right = 0;
655 CHLEN(parent) = nlen;
656 node = parent; parent = node->up;
661 for (*winners_tail = 0, node = winners; node; node = next) {
662 next = node->right; node->right = 0;
663 print_chain(node); putchar('\n');