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
29 # error "`TREE' not defined or bungled constant setting"
30 #elif TREE == XYLA_AVL
33 # define WANT_HEIGHT 1
34 # define tree__name(name) xyla_avl_##name
38 # define WANT_HEIGHT 1
39 # define tree__name(name) xyla_rb_##name
40 #elif TREE == XYLA_SPLAY
43 # define tree__name(name) xyla_splay_##name
44 #elif TREE == XYLA_TREAP
47 # define tree__name(name) xyla_treap_##name
48 #elif TREE == QPTRIE_QP
54 #elif TREE == QPTRIE_FN
60 #elif TREE == SGT_TREE234
62 #elif TREE == LIBAVL_AVL
65 # define tree__name(name) avl_##name
66 #elif TREE == LIBAVL_BST
69 # define tree__name(name) bst_##name
70 #elif TREE == LIBAVL_RB
73 # define tree__name(name) rb_##name
74 #elif TREE == LIBAVL_PAVL
77 # define tree__name(name) pavl_##name
78 #elif TREE == LIBAVL_PBST
81 # define tree__name(name) pbst_##name
82 #elif TREE == LIBAVL_PRB
85 # define tree__name(name) prb_##name
86 #elif TREE == LIBAVL_RTAVL
89 # define tree__name(name) rtavl_##name
90 #elif TREE == LIBAVL_RTBST
93 # define tree__name(name) rtbst_##name
94 #elif TREE == LIBAVL_RTRB
97 # define tree__name(name) rtrb_##name
98 #elif TREE == LIBAVL_TAVL
100 # define USE_LIBAVL 1
101 # define tree__name(name) tavl_##name
102 #elif TREE == LIBAVL_BST
104 # define USE_LIBAVL 1
105 # define tree__name(name) tbst_##name
106 #elif TREE == LIBAVL_TRB
108 # define USE_LIBAVL 1
109 # define tree__name(name) trb_##name
110 #elif TREE == MLIB_SYM
111 # include <mLib/sym.h>
113 # error "unknown `TREE' value"
117 # define NODE tree__name(node)
118 # define PATH tree__name(path)
119 # define ITER tree__name(iter)
120 # define TREE_CHECK tree__name(check)
121 # define TREE_LOOKUP tree__name(lookup)
122 # define TREE_PROBE tree__name(probe)
123 # define TREE_INITITER tree__name(inititer)
124 # define TREE_NEXT tree__name(next)
125 # define TREE_INSERT tree__name(insert)
134 # define TABLE tree__name(table)
135 # define TRAVERSER tree__name(traverser)
136 # define TREE_CREATE tree__name(create)
137 # define TREE_DESTROY tree__name(destroy)
138 # define TREE_PROBE tree__name(probe)
139 # define TREE_FIND tree__name(find)
140 # define TREE_T_INIT tree__name(t_init)
141 # define TREE_T_NEXT tree__name(t_next)
144 struct word { const char *p; size_t n; } word;
149 #elif TREE == MLIB_SYM
155 struct node *down, *right, *up;
161 static void bail(const char *msg, ...)
166 va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap);
168 if (pos >= 0) fprintf(stderr, " (input pos = %ld)", pos);
173 #if USE_XYLA || TREE == SGT_TREE234 || USE_LIBAVL
175 static int compare_words(const struct word *a, const struct word *b)
177 size_t alen = a->n, blen = b->n;
180 ord = memcmp(a->p, b->p, alen <= blen ? alen : blen);
181 if (!ord) ord = alen < blen ? -1 : alen > blen ? +1 : 0;
189 static int word_nav(struct xyla_bst_nodecls *cls,
190 const struct xyla_bst_node *nn, void *arg)
192 const struct word *k = arg;
193 const struct node *node = (struct node *)nn;
195 return (compare_words(k, &node->w));
199 struct xyla_bst_node *root = 0; \
203 # define INIT do ; while (0)
205 # if TREE == XYLA_TREAP
206 # define EXTRA_NODE_SETUP do { node->_n.wt = rand(); } while (0)
208 # ifndef EXTRA_NODE_SETUP
209 # define EXTRA_NODE_SETUP do ; while (0)
211 # define INSERT do { \
212 if (TREE_PROBE(0, &root, word_nav, &word, &path)) { \
213 printf(";; duplicate `%s'\n", buf); \
214 free(node); node = 0; \
217 TREE_INSERT(0, &path, &node->_n); \
222 for (TREE_INITITER(&root, &it); node = TREE_NEXT(&it), node; )
224 # if TREE == XYLA_SPLAY
225 # define FOCUS do { xyla_splay_splay(0, &path); } while (0)
227 # define FOCUS do ; while (0)
230 # define LOOKUP TREE_LOOKUP(0, &root, word_nav, &word)
233 while (node = xyla_bst_severfirst(&root), node) free(node); \
237 # define CHECK do ; while (0)
240 static const void *word_key(struct xyla_bst_nodecls *cls,
241 const struct xyla_bst_node *nn)
242 { struct node *node = (struct node *)nn; return (&node->w); }
244 static void word_ident(struct xyla_bst_nodecls *cls,
245 const struct xyla_bst_node *nn, FILE *fp)
246 { struct node *node = (struct node *)nn; fprintf(fp, "`%s'", node->w.p); }
248 static const struct xyla_bst_ordnodeops word_ops = {
249 { 0, xyla_bst_chkorder, sizeof(struct xyla_bst_ordinfo), word_ident },
250 { word_nav, word_key }
252 struct xyla_bst_nodecls word_cls = { &word_ops.node };
254 # define CHECK do { \
255 if (TREE_CHECK(&word_cls, &root HARG(-1), 0)) \
256 bail("check failed"); \
261 # ifdef USE_RECURSIVE_TNEXTL
262 # define my_Tnextl Tnextl
263 # elif TREE == QPTRIE_QP
265 static bool my_Tnextl(Tbl *tbl, const char **k_inout, size_t *sz_inout,
268 const char *k = *k_inout;
269 size_t sz = *sz_inout;
280 while (isbranch(t)) {
281 __builtin_prefetch(t->branch.twigs);
282 b = twigbit(t, k, sz);
283 TWIGOFFMAX(off, max, t, b);
284 if (!hastwig(t, b)) return (false);
286 if (off + 1 < max) resume = t + 1;
288 if (strcmp(k, t->leaf.key) != 0) return (false);
289 t = resume; if (!t) return (false);
292 while (isbranch(t)) t = twig(t, 0);
293 *k_inout = k = t->leaf.key; *sz_inout = strlen(k); *val_out = t->leaf.val;
297 # elif TREE == QPTRIE_FN
299 static bool my_Tnextl(Tbl *t, const char **k_inout, size_t *sz_inout,
302 const char *k = *k_inout;
303 size_t sz = *sz_inout;
313 while (isbranch(t)) {
314 __builtin_prefetch(t->ptr);
315 i = t->index; b = twigbit(i, k, sz);
316 TWIGOFFMAX(off, max, i, b);
317 if (!hastwig(i, b)) return (false);
318 t = Tbranch_twigs(t) + off;
319 if (off + 1 < max) resume = t + 1;
321 if (strcmp(k, Tleaf_key(t)) != 0) return (false);
322 t = resume; if (!t) return (false);
324 while (isbranch(t)) t = Tbranch_twigs(t);
325 *k_inout = k = Tleaf_key(t); *sz_inout = strlen(k);
326 *val_out = Tleaf_val(t);
337 # define INIT do ; while (0)
339 # define INSERT do { \
340 tbl = Tsetl(tbl, node->w.p, node->w.n, node); \
344 for (cur.p = 0, cur.n = 0; \
345 my_Tnextl(tbl, &cur.p, &cur.n, &v) ? node = v, 1 : 0; )
347 # define FOCUS do ; while (0)
349 # define GETPREFIX do { \
350 word.n = node->w.n - 1; assert(word.n < WORDMAX); \
351 memcpy(buf, node->w.p, word.n); buf[word.n] = 0; \
354 # define LOOKUP Tgetl(tbl, buf, word.n)
358 cur.p = 0; cur.n = 0; my_Tnextl(tbl, &cur.p, &cur.n, &v); \
359 tbl = Tsetl(tbl, cur.p, cur.n, 0); free(v); \
363 # define CHECK do ; while (0)
365 #elif TREE == SGT_TREE234
367 static int node_cmp(void *a, void *b)
368 { const struct word *wa = a, *wb = b; return (compare_words(wa, wb)); }
374 # define INIT do { root = newtree234(node_cmp); } while (0)
376 # define INSERT do { \
377 if (add234(root, node) != node) { \
378 printf(";; duplicate `%s'\n", buf); \
379 free(node); node = 0; \
383 # define ITERATE for (i = 0; node = index234(root, i), node; i++)
385 # define FOCUS do ; while (0)
387 # define LOOKUP find234(root, &word, 0)
390 while (node = delpos234(root, 0), node) free(node); \
394 # define CHECK do ; while (0)
398 static int node_cmp(const void *a, const void *b, void *arg)
399 { const struct word *wa = a, *wb = b; return (compare_words(wa, wb)); }
401 static void free_node(void *n, void *arg) { free(n); }
405 struct TRAVERSER it; \
409 tab = TREE_CREATE(node_cmp, 0, 0); \
410 if (!tab) bail("out of memory"); \
413 # define INSERT do { \
414 p = TREE_PROBE(tab, node); if (!p) bail("out of memory"); \
416 printf(";; duplicate `%s'\n", buf); \
417 free(node); node = 0; \
422 for (TREE_T_INIT(&it, tab); node = TREE_T_NEXT(&it), node; )
424 # define FOCUS do ; while (0)
426 # define LOOKUP TREE_FIND(tab, &word)
428 # define FREE do { TREE_DESTROY(tab, free_node); } while (0)
430 # define CHECK do ; while (0)
432 #elif TREE == MLIB_SYM
439 # define INIT do { sym_create(&tab); } while (0)
441 # define PREPNODE do ; while (0)
443 # define INSERT do { \
444 node = sym_find(&tab, buf, word.n, sizeof(*node), &foundp); \
445 if (foundp) { bail(";; duplicate `%s'\n", buf); node = 0; } \
448 # define ITERATE for (sym_mkiter(&it, &tab); node = sym_next(&it), node; )
450 # define FOCUS do ; while (0)
452 # define WORDPTR(node) (SYM_NAME(node))
453 # define WORDLEN(node) (SYM_LEN(node))
455 # define LOOKUP sym_find(&tab, word.p, word.n, 0, 0)
457 # define FREE do { sym_destroy(&tab); } while (0)
459 # define CHECK do ; while (0)
464 # define PREPNODE do { \
465 node = malloc(sizeof(*node) + word.n + 1); \
466 if (!node) bail("out of memory"); \
467 node->w.p = (char *)(node + 1); \
468 memcpy(node + 1, buf, word.n + 1); node->w.n = word.n; \
473 # define WORDPTR(node) ((node)->w.p)
477 # define WORDLEN(node) ((node)->w.n)
481 # define GETPREFIX do { \
482 word.p = WORDPTR(node); word.n = WORDLEN(node) - 1; \
487 static void print_chain(struct node *node)
490 fputs(WORDPTR(node), stdout);
491 if (node->down) { putchar(' '); print_chain(node->down); }
495 fputs(WORDPTR(node), stdout);
496 if (node->down) { putchar(' '); print_chain(node->down); }
497 node = node->right; if (!node) break;
498 fputs(" | ", stdout);
507 struct node *node, *parent;
515 if (!fgets(buf, WORDMAX, stdin)) break;
516 word.n = strlen(buf); assert(word.n);
517 if (buf[word.n - 1] == '\n') buf[--word.n] = 0;
518 else if (word.n == WORDMAX - 1) bail("word too long");
519 else if (ch = getchar(), ch != EOF) bail("short read, found `%c'", ch);
522 if (node) { node->up = node->down = node->right = 0; node->len = 1; }
531 /* fprintf(stderr, ";; ponder `%.*s'\n", WORDLEN(node), WORDPTR(node)); */
532 if (WORDLEN(node) <= 1)
536 /* fprintf(stderr, ";; search `%.*s'\n", word.n, word.p); */
541 if (parent->len > node->len + 1) break;
542 if (parent->len < node->len + 1) parent->down = 0;
543 if (parent->down != node)
544 { node->right = parent->down; parent->down = node; }
545 parent->len = node->len + 1;
546 if (parent->len > max) max = parent->len;
547 node = parent; parent = node->up;
551 ITERATE if (node->len == max) { print_chain(node); putchar('\n'); }