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
42 # define WANT_HEIGHT 1
43 # define tree__name(name) xyla_rb_##name
44 #elif TREE == XYLA_SPLAY
47 # define tree__name(name) xyla_splay_##name
48 #elif TREE == XYLA_TREAP
51 # define tree__name(name) xyla_treap_##name
52 #elif TREE == QPTRIE_QP
58 #elif TREE == QPTRIE_FN
64 #elif TREE == SGT_TREE234
66 #elif TREE == LIBAVL_AVL
69 # define tree__name(name) avl_##name
70 #elif TREE == LIBAVL_BST
73 # define tree__name(name) bst_##name
74 #elif TREE == LIBAVL_RB
77 # define tree__name(name) rb_##name
78 #elif TREE == LIBAVL_PAVL
81 # define tree__name(name) pavl_##name
82 #elif TREE == LIBAVL_PBST
85 # define tree__name(name) pbst_##name
86 #elif TREE == LIBAVL_PRB
89 # define tree__name(name) prb_##name
90 #elif TREE == LIBAVL_RTAVL
93 # define tree__name(name) rtavl_##name
94 #elif TREE == LIBAVL_RTBST
97 # define tree__name(name) rtbst_##name
98 #elif TREE == LIBAVL_RTRB
100 # define USE_LIBAVL 1
101 # define tree__name(name) rtrb_##name
102 #elif TREE == LIBAVL_TAVL
104 # define USE_LIBAVL 1
105 # define tree__name(name) tavl_##name
106 #elif TREE == LIBAVL_BST
108 # define USE_LIBAVL 1
109 # define tree__name(name) tbst_##name
110 #elif TREE == LIBAVL_TRB
112 # define USE_LIBAVL 1
113 # define tree__name(name) trb_##name
114 #elif TREE == MLIB_SYM
116 # include <mLib/sym.h>
117 # include <mLib/unihash.h>
119 # error "unknown `TREE' value"
123 # define NODE tree__name(node)
124 # define PATH tree__name(path)
125 # define ITER tree__name(iter)
126 # define TREE_CHECK tree__name(check)
127 # define TREE_LOOKUP tree__name(lookup)
128 # define TREE_PROBE tree__name(probe)
129 # define TREE_INITITER tree__name(inititer)
130 # define TREE_NEXT tree__name(next)
131 # define TREE_INSERT tree__name(insert)
140 # define TABLE tree__name(table)
141 # define TRAVERSER tree__name(traverser)
142 # define TREE_CREATE tree__name(create)
143 # define TREE_DESTROY tree__name(destroy)
144 # define TREE_PROBE tree__name(probe)
145 # define TREE_FIND tree__name(find)
146 # define TREE_T_INIT tree__name(t_init)
147 # define TREE_T_NEXT tree__name(t_next)
152 # error "`QPTRIE_ITER' not defined or bungled constant setting"
153 # elif QPTRIE_ITER == QPITER_FANF
154 # elif QPTRIE_ITER == QPITER_MDW
155 # elif QPTRIE_ITER == QPITER_LIST
157 # error "unknown `QPTRIE_ITER' value"
161 struct word { const char *p; size_t n; } word;
166 #elif TREE == MLIB_SYM
169 #if TREE == MLIB_SYM || (USE_QPTRIE && QPTRIE_ITER == QPITER_LIST)
175 struct node *down, *right, *up;
181 static void bail(const char *msg, ...)
186 va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap);
188 if (pos >= 0) fprintf(stderr, " (input pos = %ld)", pos);
193 #if USE_XYLA || TREE == SGT_TREE234 || USE_LIBAVL
195 static int compare_words(const struct word *a, const struct word *b)
197 size_t alen = a->n, blen = b->n;
200 ord = memcmp(a->p, b->p, alen <= blen ? alen : blen);
201 if (!ord) ord = alen < blen ? -1 : alen > blen ? +1 : 0;
209 static int word_nav(struct xyla_bst_nodecls *cls,
210 const struct xyla_bst_node *nn, void *arg)
212 const struct word *k = arg;
213 const struct node *node = (struct node *)nn;
215 return (compare_words(k, &node->w));
219 struct xyla_bst_node *root = 0; \
223 # define INIT do ; while (0)
225 # if TREE == XYLA_TREAP
226 # define EXTRA_NODE_SETUP do { node->_n.wt = rand(); } while (0)
228 # ifndef EXTRA_NODE_SETUP
229 # define EXTRA_NODE_SETUP do ; while (0)
231 # define INSERT do { \
232 if (TREE_PROBE(0, &root, word_nav, &word, &path)) { \
233 fprintf(stderr, ";; duplicate `%s'\n", buf); \
234 free(node); node = 0; \
237 TREE_INSERT(0, &path, &node->_n); \
242 for (TREE_INITITER(&root, &it); node = TREE_NEXT(&it), node; )
244 # if TREE == XYLA_SPLAY
245 # define FOCUS do { xyla_splay_splay(0, &path); } while (0)
247 # define FOCUS do ; while (0)
250 # define LOOKUP TREE_LOOKUP(0, &root, word_nav, &word)
253 while (node = xyla_bst_severfirst(&root), node) free(node); \
257 # define CHECK do ; while (0)
260 static const void *word_key(struct xyla_bst_nodecls *cls,
261 const struct xyla_bst_node *nn)
262 { struct node *node = (struct node *)nn; return (&node->w); }
264 static void word_ident(struct xyla_bst_nodecls *cls,
265 const struct xyla_bst_node *nn, FILE *fp)
266 { struct node *node = (struct node *)nn; fprintf(fp, "`%s'", node->w.p); }
268 static const struct xyla_bst_ordnodeops word_ops = {
269 { 0, xyla_bst_chkorder, sizeof(struct xyla_bst_ordinfo), word_ident },
270 { word_nav, word_key }
272 struct xyla_bst_nodecls word_cls = { &word_ops.node };
274 # define CHECK do { \
275 if (TREE_CHECK(&word_cls, &root HARG(-1), 0)) \
276 bail("check failed"); \
282 # if QPTRIE_ITER == QPITER_FANF
283 # define my_Tnextl Tnextl
287 # define INSERT_LIST do ; while (0)
288 # elif QPTRIE_ITER == QPITER_MDW
292 # define INSERT_LIST do ; while (0)
294 # if TREE == QPTRIE_QP
296 static bool my_Tnextl(Tbl *tbl, const char **k_inout, size_t *sz_inout,
299 const char *k = *k_inout;
300 size_t sz = *sz_inout;
311 while (isbranch(t)) {
312 __builtin_prefetch(t->branch.twigs);
313 b = twigbit(t, k, sz);
314 TWIGOFFMAX(off, max, t, b);
315 if (!hastwig(t, b)) return (false);
317 if (off + 1 < max) resume = t + 1;
319 /* if (strcmp(k, t->leaf.key) != 0) return (false); */
320 t = resume; if (!t) return (false);
323 while (isbranch(t)) t = twig(t, 0);
324 *k_inout = k = t->leaf.key; *sz_inout = strlen(k); *val_out = t->leaf.val;
328 # elif TREE == QPTRIE_FN
330 static bool my_Tnextl(Tbl *t, const char **k_inout, size_t *sz_inout,
333 const char *k = *k_inout;
334 size_t sz = *sz_inout;
344 while (isbranch(t)) {
345 __builtin_prefetch(t->ptr);
346 i = t->index; b = twigbit(i, k, sz);
347 TWIGOFFMAX(off, max, i, b);
348 if (!hastwig(i, b)) return (false);
349 t = Tbranch_twigs(t) + off;
350 if (off + 1 < max) resume = t + 1;
352 /* if (strcmp(k, Tleaf_key(t)) != 0) return (false); */
353 t = resume; if (!t) return (false);
355 while (isbranch(t)) t = Tbranch_twigs(t);
356 *k_inout = k = Tleaf_key(t); *sz_inout = strlen(k);
357 *val_out = Tleaf_val(t);
362 # error "no mdw `Tnextl' for this QP trie variant"
364 # elif QPTRIE_ITER == QPITER_LIST
366 struct node *all = 0, **all_tail = &all
367 # define INSERT_LIST do { \
368 node->next = 0; *all_tail = node; all_tail = &node->next; \
376 # define INIT do ; while (0)
378 # define INSERT do { \
379 tbl = Tsetl(tbl, node->w.p, node->w.n, node); \
383 # if QPTRIE_ITER == QPITER_LIST
385 for (next = all; node = next, node; next = next->next)
388 for (cur.p = 0, cur.n = 0; \
389 my_Tnextl(tbl, &cur.p, &cur.n, &v) ? node = v, 1 : 0; )
392 # define FOCUS do ; while (0)
394 # define GETPREFIX do { \
395 word.n = node->w.n - 1; assert(word.n < WORDMAX); \
396 memcpy(buf, node->w.p, word.n); buf[word.n] = 0; \
399 # define LOOKUP Tgetl(tbl, buf, word.n)
401 # if QPTRIE_ITER == QPITER_LIST
403 for (node = all; node; node = next) { \
404 tbl = Tsetl(tbl, node->w.p, node->w.n, 0); \
405 next = node->next; free(node); \
412 cur.p = 0; cur.n = 0; my_Tnextl(tbl, &cur.p, &cur.n, &v); \
413 tbl = Tsetl(tbl, cur.p, cur.n, 0); free(v); \
418 # define CHECK do ; while (0)
420 #elif TREE == SGT_TREE234
422 static int node_cmp(void *a, void *b)
423 { const struct word *wa = a, *wb = b; return (compare_words(wa, wb)); }
429 # define INIT do { root = newtree234(node_cmp); } while (0)
431 # define INSERT do { \
432 if (add234(root, node) != node) { \
433 fprintf(stderr, ";; duplicate `%s'\n", buf); \
434 free(node); node = 0; \
438 # define ITERATE for (i = 0; node = index234(root, i), node; i++)
440 # define FOCUS do ; while (0)
442 # define LOOKUP find234(root, &word, 0)
445 while (node = delpos234(root, 0), node) free(node); \
449 # define CHECK do ; while (0)
453 static int node_cmp(const void *a, const void *b, void *arg)
454 { const struct word *wa = a, *wb = b; return (compare_words(wa, wb)); }
456 static void free_node(void *n, void *arg) { free(n); }
460 struct TRAVERSER it; \
464 tab = TREE_CREATE(node_cmp, 0, 0); \
465 if (!tab) bail("out of memory"); \
468 # define INSERT do { \
469 p = TREE_PROBE(tab, node); if (!p) bail("out of memory"); \
471 fprintf(stderr, ";; duplicate `%s'\n", buf); \
472 free(node); node = 0; \
477 for (TREE_T_INIT(&it, tab); node = TREE_T_NEXT(&it), node; )
479 # define FOCUS do ; while (0)
481 # define LOOKUP TREE_FIND(tab, &word)
483 # define FREE do { TREE_DESTROY(tab, free_node); } while (0)
485 # define CHECK do ; while (0)
487 #elif TREE == MLIB_SYM
491 struct node *all = 0, **all_tail = &all; \
495 unihash_setkey(&unihash_global, getpid()); \
499 # define PREPNODE do ; while (0)
501 # define INSERT do { \
502 node = sym_find(&tab, buf, word.n, sizeof(*node), &foundp); \
504 node->next = 0; *all_tail = node; all_tail = &node->next; \
506 fprintf(stderr, ";; duplicate `%s'\n", buf); \
507 free(node); node = 0; \
511 # define ITERATE for (next = all; node = next, node; next = next->next)
513 # define FOCUS do ; while (0)
515 # define WORDPTR(node) (SYM_NAME(node))
516 # define WORDLEN(node) (SYM_LEN(node))
518 # define LOOKUP sym_find(&tab, word.p, word.n, 0, 0)
520 # define FREE do { sym_destroy(&tab); } while (0)
522 # define CHECK do ; while (0)
527 # define PREPNODE do { \
528 node = malloc(sizeof(*node) + word.n + 1); \
529 if (!node) bail("out of memory"); \
530 node->w.p = (char *)(node + 1); \
531 memcpy(node + 1, buf, word.n + 1); node->w.n = word.n; \
536 # define WORDPTR(node) ((node)->w.p)
540 # define WORDLEN(node) ((node)->w.n)
544 # define GETPREFIX do { \
545 word.p = WORDPTR(node); word.n = WORDLEN(node) - 1; \
550 static void print_chain(struct node *node)
553 fputs(WORDPTR(node), stdout);
554 if (node->down) { putchar(' '); print_chain(node->down); }
558 fputs(WORDPTR(node), stdout);
559 if (node->down) { putchar(' '); print_chain(node->down); }
560 node = node->right; if (!node) break;
561 fputs(" | ", stdout);
570 struct node *node, *parent, *winners, **winners_tail, *next;
573 int ch, max, nlen, plen;
578 if (!fgets(buf, WORDMAX, stdin)) break;
579 word.n = strlen(buf); assert(word.n);
580 if (buf[word.n - 1] == '\n') buf[--word.n] = 0;
581 else if (word.n == WORDMAX - 1) bail("word too long");
582 else if (ch = getchar(), ch != EOF) bail("short read, found `%c'", ch);
585 if (node) { node->up = node->down = node->right = 0; node->len = 1; }
590 max = 0; winners_tail = &winners;
594 /* fprintf(stderr, ";; ponder `%.*s'\n", WORDLEN(node), WORDPTR(node)); */
595 if (WORDLEN(node) <= 1)
599 /* fprintf(stderr, ";; search `%.*s'\n", word.n, word.p); */
600 parent = LOOKUP; if (!parent) continue;
602 node->up = parent; nlen = node->len;
607 { max = nlen; *winners_tail = 0; winners_tail = &winners; }
608 *winners_tail = node; winners_tail = &node->right;
612 plen = parent->len; nlen++;
615 else if (plen == nlen) {
616 node->right = parent->down; parent->down = node;
619 parent->down = node; node->right = 0;
621 node = parent; parent = node->up;
626 for (*winners_tail = 0, node = winners; node; node = next) {
627 next = node->right; node->right = 0;
628 print_chain(node); putchar('\n');