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"
173 struct word { const char *p; size_t n; } word;
178 #elif TREE == MLIB_SYM
181 #if TREE == MLIB_SYM || (USE_QPTRIE && QPTRIE_ITER == QPITER_LIST)
187 struct node *down, *right, *up;
193 static void bail(const char *msg, ...)
198 va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap);
200 if (pos >= 0) fprintf(stderr, " (input pos = %ld)", pos);
205 #if USE_XYLA || TREE == SGT_TREE234 || USE_LIBAVL
207 static int compare_words(const struct word *a, const struct word *b)
209 size_t alen = a->n, blen = b->n;
212 ord = memcmp(a->p, b->p, alen <= blen ? alen : blen);
213 if (!ord) ord = alen < blen ? -1 : alen > blen ? +1 : 0;
221 union nodeu { struct node node; TREE_NODEUSFX; };
223 static int word_nav(struct xyla_bt_nodecls *cls,
224 const struct xyla_bt_node *nn, void *arg)
226 const struct word *k = arg;
227 const struct node *node = (struct node *)nn;
229 return (compare_words(k, &node->w));
233 struct xyla_bt_node *root = 0; \
234 union nodeu *nodeu; \
238 # define INIT do ; while (0)
240 # if TREE == XYLA_TREAP
241 # define EXTRA_NODE_SETUP do { node->trp.wt = rand(); } while (0)
243 # ifndef EXTRA_NODE_SETUP
244 # define EXTRA_NODE_SETUP do ; while (0)
246 # define INSERT do { \
247 if (TREE_PROBE(0, &root, word_nav, &word, &path)) { \
248 fprintf(stderr, ";; duplicate `%s'\n", buf); \
249 free(node); node = 0; \
252 nodeu = (union nodeu *)node; \
253 TREE_INSERT(0, &path, &nodeu->T); \
258 for (TREE_INITITER(root, &it); node = TREE_NEXT(&it), node; )
260 # if TREE == XYLA_SPLAY
261 # define FOCUS do { xyla_splay_splay(0, &path); } while (0)
263 # define FOCUS do ; while (0)
266 # define LOOKUP TREE_LOOKUP(0, &root, word_nav, &word)
269 while (node = xyla_bt_severfirst(&root), node) free(node); \
273 # define CHECK do ; while (0)
276 static const void *word_key(struct xyla_bt_nodecls *cls,
277 const struct xyla_bt_node *nn)
278 { struct node *node = (struct node *)nn; return (&node->w); }
280 static void word_ident(struct xyla_bt_nodecls *cls,
281 const struct xyla_bt_node *nn, FILE *fp)
282 { struct node *node = (struct node *)nn; fprintf(fp, "`%s'", node->w.p); }
284 static const struct xyla_bt_chkops word_ops = {
285 { sizeof(word_ops), 0 },
286 { word_nav, word_key },
287 { xyla_bt_chkorder, sizeof(struct xyla_bt_ordinfo), word_ident }
289 struct xyla_bt_nodecls word_cls = { &word_ops.node };
291 # define CHECK do { \
292 if (TREE_CHECK(&word_cls, &root, stderr, 0 HARG(-1), 0)) \
293 bail("check failed"); \
299 # if QPTRIE_ITER == QPITER_FANF
300 # define my_Tnextl Tnextl
304 # define INSERT_LIST do ; while (0)
305 # elif QPTRIE_ITER == QPITER_MDW
309 # define INSERT_LIST do ; while (0)
311 # if TREE == QPTRIE_QP
313 static bool my_Tnextl(Tbl *tbl, const char **k_inout, size_t *sz_inout,
316 const char *k = *k_inout;
317 size_t sz = *sz_inout;
328 while (isbranch(t)) {
329 __builtin_prefetch(t->branch.twigs);
330 b = twigbit(t, k, sz);
331 TWIGOFFMAX(off, max, t, b);
332 if (!hastwig(t, b)) return (false);
334 if (off + 1 < max) resume = t + 1;
336 /* if (strcmp(k, t->leaf.key) != 0) return (false); */
337 t = resume; if (!t) return (false);
340 while (isbranch(t)) t = twig(t, 0);
341 *k_inout = k = t->leaf.key; *sz_inout = strlen(k); *val_out = t->leaf.val;
345 # elif TREE == QPTRIE_FN
347 static bool my_Tnextl(Tbl *t, const char **k_inout, size_t *sz_inout,
350 const char *k = *k_inout;
351 size_t sz = *sz_inout;
361 while (isbranch(t)) {
362 __builtin_prefetch(t->ptr);
363 i = t->index; b = twigbit(i, k, sz);
364 TWIGOFFMAX(off, max, i, b);
365 if (!hastwig(i, b)) return (false);
366 t = Tbranch_twigs(t) + off;
367 if (off + 1 < max) resume = t + 1;
369 /* if (strcmp(k, Tleaf_key(t)) != 0) return (false); */
370 t = resume; if (!t) return (false);
372 while (isbranch(t)) t = Tbranch_twigs(t);
373 *k_inout = k = Tleaf_key(t); *sz_inout = strlen(k);
374 *val_out = Tleaf_val(t);
379 # error "no mdw `Tnextl' for this QP trie variant"
381 # elif QPTRIE_ITER == QPITER_LIST
383 struct node *all = 0, **all_tail = &all
384 # define INSERT_LIST do { \
385 node->next = 0; *all_tail = node; all_tail = &node->next; \
393 # define INIT do ; while (0)
395 # define INSERT do { \
396 tbl = Tsetl(tbl, node->w.p, node->w.n, node); \
400 # if QPTRIE_ITER == QPITER_LIST
402 for (next = all; node = next, node; next = next->next)
405 for (cur.p = 0, cur.n = 0; \
406 my_Tnextl(tbl, &cur.p, &cur.n, &v) ? node = v, 1 : 0; )
409 # define FOCUS do ; while (0)
411 # define GETPREFIX do { \
412 word.n = node->w.n - 1; assert(word.n < WORDMAX); \
413 memcpy(buf, node->w.p, word.n); buf[word.n] = 0; \
416 # define LOOKUP Tgetl(tbl, buf, word.n)
418 # if QPTRIE_ITER == QPITER_LIST
420 for (node = all; node; node = next) { \
421 tbl = Tsetl(tbl, node->w.p, node->w.n, 0); \
422 next = node->next; free(node); \
429 cur.p = 0; cur.n = 0; my_Tnextl(tbl, &cur.p, &cur.n, &v); \
430 tbl = Tsetl(tbl, cur.p, cur.n, 0); free(v); \
435 # define CHECK do ; while (0)
437 #elif TREE == SGT_TREE234
439 static int node_cmp(void *a, void *b)
440 { const struct word *wa = a, *wb = b; return (compare_words(wa, wb)); }
446 # define INIT do { root = newtree234(node_cmp); } while (0)
448 # define INSERT do { \
449 if (add234(root, node) != node) { \
450 fprintf(stderr, ";; duplicate `%s'\n", buf); \
451 free(node); node = 0; \
455 # define ITERATE for (i = 0; node = index234(root, i), node; i++)
457 # define FOCUS do ; while (0)
459 # define LOOKUP find234(root, &word, 0)
462 while (node = delpos234(root, 0), node) free(node); \
466 # define CHECK do ; while (0)
470 static int node_cmp(const void *a, const void *b, void *arg)
471 { const struct word *wa = a, *wb = b; return (compare_words(wa, wb)); }
473 static void free_node(void *n, void *arg) { free(n); }
477 struct TRAVERSER it; \
481 tab = TREE_CREATE(node_cmp, 0, 0); \
482 if (!tab) bail("out of memory"); \
485 # define INSERT do { \
486 p = TREE_PROBE(tab, node); if (!p) bail("out of memory"); \
488 fprintf(stderr, ";; duplicate `%s'\n", buf); \
489 free(node); node = 0; \
494 for (TREE_T_INIT(&it, tab); node = TREE_T_NEXT(&it), node; )
496 # define FOCUS do ; while (0)
498 # define LOOKUP TREE_FIND(tab, &word)
500 # define FREE do { TREE_DESTROY(tab, free_node); } while (0)
502 # define CHECK do ; while (0)
504 #elif TREE == MLIB_SYM
508 struct node *all = 0, **all_tail = &all; \
512 unihash_setkey(&unihash_global, getpid()); \
516 # define PREPNODE do ; while (0)
518 # define INSERT do { \
519 node = sym_find(&tab, buf, word.n, sizeof(*node), &foundp); \
521 node->next = 0; *all_tail = node; all_tail = &node->next; \
523 fprintf(stderr, ";; duplicate `%s'\n", buf); \
524 free(node); node = 0; \
528 # define ITERATE for (next = all; node = next, node; next = next->next)
530 # define FOCUS do ; while (0)
532 # define WORDPTR(node) (SYM_NAME(node))
533 # define WORDLEN(node) (SYM_LEN(node))
535 # define LOOKUP sym_find(&tab, word.p, word.n, 0, 0)
537 # define FREE do { sym_destroy(&tab); } while (0)
539 # define CHECK do ; while (0)
544 # define PREPNODE do { \
545 node = malloc(sizeof(*node) + word.n + 1); \
546 if (!node) bail("out of memory"); \
547 node->w.p = (char *)(node + 1); \
548 memcpy(node + 1, buf, word.n + 1); node->w.n = word.n; \
553 # define WORDPTR(node) ((node)->w.p)
557 # define WORDLEN(node) ((node)->w.n)
561 # define GETPREFIX do { \
562 word.p = WORDPTR(node); word.n = WORDLEN(node) - 1; \
567 static void print_chain(struct node *node)
570 fputs(WORDPTR(node), stdout);
571 if (node->down) { putchar(' '); print_chain(node->down); }
575 fputs(WORDPTR(node), stdout);
576 if (node->down) { putchar(' '); print_chain(node->down); }
577 node = node->right; if (!node) break;
578 fputs(" | ", stdout);
587 struct node *node, *parent, *winners, **winners_tail, *next;
590 int ch, max, nlen, plen;
595 if (!fgets(buf, WORDMAX, stdin)) break;
596 word.n = strlen(buf); assert(word.n);
597 if (buf[word.n - 1] == '\n') buf[--word.n] = 0;
598 else if (word.n == WORDMAX - 1) bail("word too long");
599 else if (ch = getchar(), ch != EOF) bail("short read, found `%c'", ch);
602 if (node) { node->up = node->down = node->right = 0; node->len = 1; }
607 max = 0; winners_tail = &winners;
611 /* fprintf(stderr, ";; ponder `%.*s'\n", WORDLEN(node), WORDPTR(node)); */
612 if (WORDLEN(node) <= 1)
616 /* fprintf(stderr, ";; search `%.*s'\n", word.n, word.p); */
617 parent = LOOKUP; if (!parent) continue;
619 node->up = parent; nlen = node->len;
624 { max = nlen; *winners_tail = 0; winners_tail = &winners; }
625 *winners_tail = node; winners_tail = &node->right;
629 plen = parent->len; nlen++;
632 else if (plen == nlen) {
633 node->right = parent->down; parent->down = node;
636 parent->down = node; node->right = 0;
638 node = parent; parent = node->up;
643 for (*winners_tail = 0, node = winners; node; node = next) {
644 next = node->right; node->right = 0;
645 print_chain(node); putchar('\n');