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"
186 #elif TREE == MLIB_SYM
188 # define WORDPTR(node) (SYM_NAME(node))
189 # define WORDLEN(node) (SYM_LEN(node))
195 # define CHLEN(node) ((node)->chlen)
201 struct { const char *p; unsigned short n; short chlen; } pack;
203 # define WORDPTR(node) ((const char *)((node) + 1))
204 # define WORDLEN(node) ((node)->u.w.n)
205 # define CHLEN(node) ((node)->u.pack.chlen)
210 # define WORDPTR(node) ((const char *)((node) + 1))
211 # define WORDLEN(node) ((node)->wlen)
214 # define CHLEN(node) ((node)->chlen)
218 #if TREE == MLIB_SYM || (USE_QPTRIE && QPTRIE_ITER == QPITER_LIST)
222 struct node *down, *right, *up;
227 static void bail(const char *msg, ...)
232 va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap);
234 if (pos >= 0) fprintf(stderr, " (input pos = %ld)", pos);
239 #if USE_XYLA || TREE == SGT_TREE234 || USE_LIBAVL
241 static int compare_words(const char *a, size_t alen,
242 const char *b, size_t blen)
246 ord = memcmp(a, b, alen <= blen ? alen : blen);
247 if (!ord) ord = alen < blen ? -1 : alen > blen ? +1 : 0;
255 union nodeu { struct node node; TREE_NODEUSFX; };
257 static int word_nav(struct xyla_bt_nodecls *cls,
258 const struct xyla_bt_node *nn, void *arg)
260 const struct word *k = arg;
261 const struct node *node = (struct node *)nn;
263 return (compare_words(k->p, k->n, WORDPTR(node), WORDLEN(node)));
267 struct xyla_bt_node *root = 0; \
268 union nodeu *nodeu; \
272 # define INIT do ; while (0)
274 # if TREE == XYLA_TREAP
275 # define EXTRA_NODE_SETUP do { node->trp.wt = rand(); } while (0)
277 # ifndef EXTRA_NODE_SETUP
278 # define EXTRA_NODE_SETUP do ; while (0)
280 # define INSERT do { \
281 if (TREE_PROBE(0, &root, word_nav, &word, &path)) { \
282 fprintf(stderr, ";; duplicate `%s'\n", buf); \
283 free(node); node = 0; \
286 nodeu = (union nodeu *)node; \
287 TREE_INSERT(0, &path, &nodeu->T); \
292 for (TREE_INITITER(root, &it); node = TREE_NEXT(&it), node; )
294 # if TREE == XYLA_SPLAY
295 # define FOCUS do { xyla_splay_splay(0, &path); } while (0)
297 # define FOCUS do ; while (0)
300 # define LOOKUP TREE_LOOKUP(0, &root, word_nav, &word)
303 while (node = xyla_bt_severfirst(&root), node) free(node); \
307 # define CHECK do ; while (0)
310 static const void *node_key(struct xyla_bt_nodecls *cls,
311 const struct xyla_bt_node *nn)
314 static int node_nav(struct xyla_bt_nodecls *cls,
315 const struct xyla_bt_node *nn, void *k)
317 const struct node *na = k, *nb = (const struct node *)nn;
319 return (compare_words(WORDPTR(na), WORDLEN(na), WORDPTR(nb), WORDLEN(nb)));
322 static void word_ident(struct xyla_bt_nodecls *cls,
323 const struct xyla_bt_node *nn, FILE *fp)
325 struct node *node = (struct node *)nn;
327 fprintf(fp, "`%s'", WORDPTR(node));
330 static const struct xyla_bt_chkops word_ops = {
331 { sizeof(word_ops), 0 },
332 { node_nav, node_key },
333 { xyla_bt_chkorder, sizeof(struct xyla_bt_ordinfo), word_ident }
335 struct xyla_bt_nodecls word_cls = { &word_ops.node };
337 # define CHECK do { \
338 if (TREE_CHECK(&word_cls, &root, stderr, 0 HARG(-1), 0)) \
339 bail("check failed"); \
345 # if QPTRIE_ITER == QPITER_FANF
346 # define my_Tnextl Tnextl
350 # define INSERT_LIST do ; while (0)
351 # elif QPTRIE_ITER == QPITER_MDW
355 # define INSERT_LIST do ; while (0)
357 # if TREE == QPTRIE_QP
359 static bool my_Tnextl(Tbl *tbl, const char **k_inout, size_t *sz_inout,
362 const char *k = *k_inout;
363 size_t sz = *sz_inout;
374 while (isbranch(t)) {
375 __builtin_prefetch(t->branch.twigs);
376 b = twigbit(t, k, sz);
377 TWIGOFFMAX(off, max, t, b);
378 if (!hastwig(t, b)) return (false);
380 if (off + 1 < max) resume = t + 1;
382 /* if (strcmp(k, t->leaf.key) != 0) return (false); */
383 t = resume; if (!t) return (false);
386 while (isbranch(t)) t = twig(t, 0);
387 *k_inout = k = t->leaf.key; *sz_inout = strlen(k); *val_out = t->leaf.val;
391 # elif TREE == QPTRIE_FN
393 static bool my_Tnextl(Tbl *t, const char **k_inout, size_t *sz_inout,
396 const char *k = *k_inout;
397 size_t sz = *sz_inout;
407 while (isbranch(t)) {
408 __builtin_prefetch(t->ptr);
409 i = t->index; b = twigbit(i, k, sz);
410 TWIGOFFMAX(off, max, i, b);
411 if (!hastwig(i, b)) return (false);
412 t = Tbranch_twigs(t) + off;
413 if (off + 1 < max) resume = t + 1;
415 /* if (strcmp(k, Tleaf_key(t)) != 0) return (false); */
416 t = resume; if (!t) return (false);
418 while (isbranch(t)) t = Tbranch_twigs(t);
419 *k_inout = k = Tleaf_key(t); *sz_inout = strlen(k);
420 *val_out = Tleaf_val(t);
425 # error "no mdw `Tnextl' for this QP trie variant"
427 # elif QPTRIE_ITER == QPITER_LIST
429 struct node *all = 0, **all_tail = &all
430 # define INSERT_LIST do { \
431 node->next = 0; *all_tail = node; all_tail = &node->next; \
439 # define INIT do ; while (0)
441 # define INSERT do { \
442 tbl = Tsetl(tbl, WORDPTR(node), WORDLEN(node), node); \
446 # if QPTRIE_ITER == QPITER_LIST
448 for (next = all; node = next, node; next = next->next)
451 for (cur.p = 0, cur.n = 0; \
452 my_Tnextl(tbl, &cur.p, &cur.n, &v) ? node = v, 1 : 0; )
455 # define FOCUS do ; while (0)
457 # define GETPREFIX do { \
458 word.n = WORDLEN(node) - 1; assert(word.n < WORDMAX); \
459 memcpy(buf, WORDPTR(node), word.n); buf[word.n] = 0; \
462 # define LOOKUP Tgetl(tbl, buf, word.n)
464 # if QPTRIE_ITER == QPITER_LIST
466 for (node = all; node; node = next) { \
467 tbl = Tsetl(tbl, WORDPTR(node), WORDLEN(node), 0); \
468 next = node->next; free(node); \
475 cur.p = 0; cur.n = 0; my_Tnextl(tbl, &cur.p, &cur.n, &v); \
476 tbl = Tsetl(tbl, cur.p, cur.n, 0); free(v); \
481 # define CHECK do ; while (0)
483 #elif TREE == SGT_TREE234
485 static int node_cmp(void *a, void *b)
487 const struct node *na = a, *nb = b;
489 return (compare_words(WORDPTR(na), WORDLEN(na),
490 WORDPTR(nb), WORDLEN(nb)));
493 static int word_cmp(void *k, void *n)
495 const struct word *word = k;
496 const struct node *node = n;
498 return (compare_words(word->p, word->n, WORDPTR(node), WORDLEN(node)));
505 # define INIT do { root = newtree234(node_cmp); } while (0)
507 # define INSERT do { \
508 if (add234(root, node) != node) { \
509 fprintf(stderr, ";; duplicate `%s'\n", buf); \
510 free(node); node = 0; \
514 # define ITERATE for (i = 0; node = index234(root, i), node; i++)
516 # define FOCUS do ; while (0)
518 # define LOOKUP find234(root, &word, word_cmp)
521 while (node = delpos234(root, 0), node) free(node); \
525 # define CHECK do ; while (0)
529 static int node_cmp(const void *a, const void *b, void *arg)
531 const struct word *wa = a, *wb = b;
533 return (compare_words(wa->p, wa->n, wb->p, wb->n));
536 static void free_node(void *n, void *arg) { free(n); }
540 struct TRAVERSER it; \
544 tab = TREE_CREATE(node_cmp, 0, 0); \
545 if (!tab) bail("out of memory"); \
548 # define PREPNODE do { \
549 node = malloc(sizeof(*node) + word.n + 1); \
550 if (!node) bail("out of memory"); \
551 memcpy(node + 1, buf, word.n + 1); \
552 node->u.w.p = (const char *)(node + 1); node->u.w.n = word.n; \
555 # define INSERT do { \
556 p = TREE_PROBE(tab, node); if (!p) bail("out of memory"); \
558 fprintf(stderr, ";; duplicate `%s'\n", buf); \
559 free(node); node = 0; \
564 for (TREE_T_INIT(&it, tab); node = TREE_T_NEXT(&it), node; )
566 # define FOCUS do ; while (0)
568 # define LOOKUP TREE_FIND(tab, &word)
570 # define FREE do { TREE_DESTROY(tab, free_node); } while (0)
572 # define CHECK do ; while (0)
574 #elif TREE == MLIB_SYM
578 struct node *all = 0, **all_tail = &all; \
582 unihash_setkey(&unihash_global, getpid()); \
586 # define PREPNODE do ; while (0)
588 # define INSERT do { \
589 node = sym_find(&tab, buf, word.n, sizeof(*node), &foundp); \
591 node->next = 0; *all_tail = node; all_tail = &node->next; \
593 fprintf(stderr, ";; duplicate `%s'\n", buf); \
594 free(node); node = 0; \
598 # define ITERATE for (next = all; node = next, node; next = next->next)
600 # define FOCUS do ; while (0)
602 # define LOOKUP sym_find(&tab, word.p, word.n, 0, 0)
604 # define FREE do { sym_destroy(&tab); } while (0)
606 # define CHECK do ; while (0)
611 # define PREPNODE do { \
612 node = malloc(sizeof(*node) + word.n + 1); \
613 if (!node) bail("out of memory"); \
614 memcpy(node + 1, buf, word.n + 1); node->wlen = word.n; \
619 # define GETPREFIX do { \
620 word.p = WORDPTR(node); word.n = WORDLEN(node) - 1; \
625 static void print_chain(struct node *node)
628 fputs(WORDPTR(node), stdout);
629 if (node->down) { putchar(' '); print_chain(node->down); }
633 fputs(WORDPTR(node), stdout);
634 if (node->down) { putchar(' '); print_chain(node->down); }
635 node = node->right; if (!node) break;
636 fputs(" | ", stdout);
645 struct node *node, *parent, *winners, **winners_tail, *next;
648 int ch, max, nlen, plen;
653 if (!fgets(buf, WORDMAX, stdin)) break;
654 word.n = strlen(buf); assert(word.n);
655 if (buf[word.n - 1] == '\n') buf[--word.n] = 0;
656 else if (word.n == WORDMAX - 1) bail("word too long");
657 else if (ch = getchar(), ch != EOF) bail("short read, found `%c'", ch);
660 if (node) { node->up = node->down = node->right = 0; CHLEN(node) = 1; }
665 max = 0; winners_tail = &winners;
669 /* fprintf(stderr, ";; ponder `%.*s'\n", WORDLEN(node), WORDPTR(node)); */
670 if (WORDLEN(node) <= 1)
674 /* fprintf(stderr, ";; search `%.*s'\n", word.n, word.p); */
675 parent = LOOKUP; if (!parent) continue;
677 node->up = parent; nlen = CHLEN(node);
682 { max = nlen; *winners_tail = 0; winners_tail = &winners; }
683 *winners_tail = node; winners_tail = &node->right;
687 plen = CHLEN(parent); nlen++;
690 else if (plen == nlen) {
691 node->right = parent->down; parent->down = node;
694 parent->down = node; node->right = 0;
695 CHLEN(parent) = nlen;
696 node = parent; parent = node->up;
701 for (*winners_tail = 0, node = winners; node; node = next) {
702 next = node->right; node->right = 0;
703 print_chain(node); putchar('\n');