+#elif TREE == POSIX_HSEARCH
+
+# define DECLS \
+ ENTRY *e, ee; \
+ size_t hmax = HSEARCH_INITSZ, hcap = 3*(hmax/4), hused = 0; \
+ struct node *all = 0, **all_tail = &all \
+
+# define INIT do { \
+ if (!hcreate(hmax)) \
+ bail("hcreate (initial) failed: %s", strerror(errno)); \
+ } while (0)
+
+# define INSERT do { \
+ if (hused >= hcap) { \
+ hdestroy(); \
+ hmax *= 2; hcap *= 2; \
+ if (!hcreate(hmax)) \
+ bail("hcreate (grow) failed: %s", strerror(errno)); \
+ for (next = all; next; next = next->next) { \
+ ee.key = (/*unconst*/ char *)WORDPTR(next); ee.data = next; \
+ if (!hsearch(ee, ENTER)) \
+ bail("hsearch (grow) failed: table full"); \
+ } \
+ } \
+ ee.key = (char *)(node + 1); ee.data = 0; \
+ e = hsearch(ee, ENTER); \
+ if (!e) \
+ bail("hsearch (insert) failed: table full"); \
+ else if (!e->data) { \
+ e->data = node; \
+ node->next = 0; *all_tail = node; all_tail = &node->next; \
+ hused++; \
+ } else { \
+ fprintf(stderr, ";; duplicate `%s'\n", buf); \
+ free(node); node = 0; \
+ } \
+ } while (0)
+
+# define ITERATE for (next = all; node = next, node; next = next->next)
+
+# define FOCUS do ; while (0)
+
+# define GETPREFIX do { \
+ word.n = WORDLEN(node) - 1; assert(word.n < WORDMAX); \
+ memcpy(buf, WORDPTR(node), word.n); buf[word.n] = 0; \
+ } while (0)
+
+# define LOOKUP \
+ (ee.key = (/*unconst*/ char *)word.p, \
+ e = hsearch(ee, FIND), e ? e->data : 0)
+
+# define FREE do { \
+ node = all; \
+ while (node) { next = node->next; free(node); node = next; } \
+ hdestroy(); \
+ } while (0)
+
+# define CHECK do ; while (0)
+
+#elif TREE == POSIX_TSEARCH
+
+typedef struct { struct node *node; } TNODE;
+
+static int word_cmp(const void *x, const void *y)
+{
+ const struct word *nx = x, *ny = y;
+
+ return (compare_words(nx->p, nx->n, ny->p, ny->n));
+}
+
+# define DECLS \
+ void *root = 0; \
+ struct node *all = 0, **all_tail = &all; \
+ TNODE *tn
+
+# define INIT do ; while (0)
+
+# define PREPNODE do { \
+ node = malloc(sizeof(*node) + word.n + 1); \
+ if (!node) bail("out of memory"); \
+ memcpy(node + 1, buf, word.n + 1); \
+ node->u.w.p = (const char *)(node + 1); node->u.w.n = word.n; \
+ } while (0)
+
+# define INSERT do { \
+ tn = tsearch(node, &root, word_cmp); \
+ if (tn->node == node) { \
+ node->next = 0; *all_tail = node; all_tail = &node->next; \
+ } else { \
+ fprintf(stderr, ";; duplicate `%s'\n", buf); \
+ free(node); node = 0; \
+ } \
+ } while (0)
+
+# define ITERATE for (next = all; node = next, node; next = next->next)
+
+# define FOCUS do ; while (0)
+
+# define LOOKUP (tn = tfind(&word, &root, word_cmp), tn ? tn->node : 0)
+
+# ifdef __GLIBC__
+# define FREE do tdestroy(root, free); while (0)
+# else
+# define FREE do { \
+ for (next = all; node = next, node; next = next->next) \
+ { tdelete(node, &root, word_cmp); free(node); } \
+ } while (0)
+# endif
+
+# define CHECK do ; while (0)
+