From 9a7752b9a63b5c54086fa0b457fb907869a00186 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= <nicolas@uucidl.com>
Date: Sun, 31 Jan 2016 17:27:19 +0100
Subject: [PATCH] Finish porting hammer's library to windows

We port registry by importing the (public domain) openbsd implementation
of the tfind/tsearch POSIX binary tree search functions.

These are only necessary when building on non-posix platforms
---
 src/registry.c                    |  10 ++-
 src/search.h                      |  15 ++++
 src/tsearch.c                     | 141 ++++++++++++++++++++++++++++++
 src/tsearch.h                     |  26 ++++++
 tools/windows/hammer_lib_src_list |   2 +
 5 files changed, 192 insertions(+), 2 deletions(-)
 create mode 100644 src/search.h
 create mode 100644 src/tsearch.c
 create mode 100644 src/tsearch.h

diff --git a/src/registry.c b/src/registry.c
index d905320b..8a079b52 100644
--- a/src/registry.c
+++ b/src/registry.c
@@ -15,10 +15,16 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#include <search.h>
 #include <stdlib.h>
 #include "hammer.h"
 #include "internal.h"
+#include "tsearch.h"
+
+#if defined(_MSC_VER)
+#define h_strdup _strdup
+#else
+#define h_strdup strdup
+#endif
 
 typedef struct Entry_ {
   const char* name;
@@ -58,7 +64,7 @@ HTokenType h_allocate_token_type(const char* name) {
     return probe->value;
   } else {
     // new value
-    probe->name = strdup(probe->name); // drop ownership of name
+    probe->name = h_strdup(probe->name); // drop ownership of name
     probe->value = tt_next++;
     if ((probe->value - TT_START) >= tt_by_id_sz) {
       if (tt_by_id_sz == 0) {
diff --git a/src/search.h b/src/search.h
new file mode 100644
index 00000000..8a94ab83
--- /dev/null
+++ b/src/search.h
@@ -0,0 +1,15 @@
+#if defined(_MSC_VER)
+/* find or insert datum into search tree */
+void *tsearch(const void *vkey, void **vrootp,
+              int (*compar)(const void *, const void *));
+
+/* delete node with given key */
+void * tdelete(const void *vkey, void **vrootp,
+               int (*compar)(const void *, const void *));
+
+/* Walk the nodes of a tree */
+void twalk(const void *vroot, void (*action)(const void *, VISIT, int));
+
+#else
+#include <search.h>
+#endif
diff --git a/src/tsearch.c b/src/tsearch.c
new file mode 100644
index 00000000..154f87c4
--- /dev/null
+++ b/src/tsearch.c
@@ -0,0 +1,141 @@
+/*	$OpenBSD: tsearch.c,v 1.9 2015/08/20 21:49:29 deraadt Exp $	*/
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+
+#include <stdlib.h>
+#include "tsearch.h"
+
+typedef struct node_t {
+    char	  *key;
+    struct node_t *left, *right;
+} node;
+
+/* find or insert datum into search tree */
+void *
+tsearch(const void *vkey, void **vrootp,
+    int (*compar)(const void *, const void *))
+{
+    node *q;
+    char *key = (char *)vkey;
+    node **rootp = (node **)vrootp;
+
+    if (rootp == (struct node_t **)0)
+	return ((void *)0);
+    while (*rootp != (struct node_t *)0) {	/* Knuth's T1: */
+	int r;
+
+	if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
+	    return ((void *)*rootp);		/* we found it! */
+	rootp = (r < 0) ?
+	    &(*rootp)->left :		/* T3: follow left branch */
+	    &(*rootp)->right;		/* T4: follow right branch */
+    }
+    q = malloc(sizeof(node));	/* T5: key not found */
+    if (q != (struct node_t *)0) {	/* make new node */
+	*rootp = q;			/* link new node to old */
+	q->key = key;			/* initialize new node */
+	q->left = q->right = (struct node_t *)0;
+    }
+    return ((void *)q);
+}
+
+/* delete node with given key */
+void *
+tdelete(const void *vkey, void **vrootp,
+    int (*compar)(const void *, const void *))
+{
+    node **rootp = (node **)vrootp;
+    char *key = (char *)vkey;
+    node *p = (node *)1;
+    node *q;
+    node *r;
+    int cmp;
+
+    if (rootp == (struct node_t **)0 || *rootp == (struct node_t *)0)
+	return ((struct node_t *)0);
+    while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
+	p = *rootp;
+	rootp = (cmp < 0) ?
+	    &(*rootp)->left :		/* follow left branch */
+	    &(*rootp)->right;		/* follow right branch */
+	if (*rootp == (struct node_t *)0)
+	    return ((void *)0);		/* key not found */
+    }
+    r = (*rootp)->right;			/* D1: */
+    if ((q = (*rootp)->left) == (struct node_t *)0)	/* Left (struct node_t *)0? */
+	q = r;
+    else if (r != (struct node_t *)0) {		/* Right link is null? */
+	if (r->left == (struct node_t *)0) {	/* D2: Find successor */
+	    r->left = q;
+	    q = r;
+	} else {			/* D3: Find (struct node_t *)0 link */
+	    for (q = r->left; q->left != (struct node_t *)0; q = r->left)
+		r = q;
+	    r->left = q->right;
+	    q->left = (*rootp)->left;
+	    q->right = (*rootp)->right;
+	}
+    }
+    free((struct node_t *) *rootp);	/* D4: Free node */
+    *rootp = q;				/* link parent to new node */
+    return(p);
+}
+
+/* Walk the nodes of a tree */
+static void
+trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
+{
+    if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
+	(*action)(root, leaf, level);
+    else {
+	(*action)(root, preorder, level);
+	if (root->left != (struct node_t *)0)
+	    trecurse(root->left, action, level + 1);
+	(*action)(root, postorder, level);
+	if (root->right != (struct node_t *)0)
+	    trecurse(root->right, action, level + 1);
+	(*action)(root, endorder, level);
+    }
+}
+
+/* Walk the nodes of a tree */
+void
+twalk(const void *vroot, void (*action)(const void *, VISIT, int))
+{
+    node *root = (node *)vroot;
+
+    if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
+	trecurse(root, action, 0);
+}
+
+/*	$OpenBSD: tfind.c,v 1.6 2014/03/16 18:38:30 guenther Exp $	*/
+
+/* find a node, or return 0 */
+void *
+tfind(const void *vkey, void * const *vrootp,
+    int (*compar)(const void *, const void *))
+{
+    char *key = (char *)vkey;
+    node **rootp = (node **)vrootp;
+
+    if (rootp == (struct node_t **)0)
+	return ((struct node_t *)0);
+    while (*rootp != (struct node_t *)0) {	/* T1: */
+	int r;
+	if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
+	    return (*rootp);		/* key found */
+	rootp = (r < 0) ?
+	    &(*rootp)->left :		/* T3: follow left branch */
+	    &(*rootp)->right;		/* T4: follow right branch */
+    }
+    return (node *)0;
+}
diff --git a/src/tsearch.h b/src/tsearch.h
new file mode 100644
index 00000000..7b297db7
--- /dev/null
+++ b/src/tsearch.h
@@ -0,0 +1,26 @@
+#ifndef HAMMER_TSEARCH__H
+#define HAMMER_TSEARCH__H
+
+#if defined(_MSC_VER)
+typedef enum { preorder, postorder, endorder, leaf } VISIT;
+
+/* find or insert datum into search tree */
+void *tsearch(const void *vkey, void **vrootp,
+              int (*compar)(const void *, const void *));
+
+/* delete node with given key */
+void * tdelete(const void *vkey, void **vrootp,
+               int (*compar)(const void *, const void *));
+
+/* Walk the nodes of a tree */
+void twalk(const void *vroot, void (*action)(const void *, VISIT, int));
+
+/* find a node, or return 0 */
+void *tfind(const void *vkey, void * const *vrootp,
+            int (*compar)(const void *, const void *));
+
+#else
+#include <search.h>
+#endif
+
+#endif /* HAMMER_TSEARCH__H */
diff --git a/tools/windows/hammer_lib_src_list b/tools/windows/hammer_lib_src_list
index 793619ef..3602a4d5 100644
--- a/tools/windows/hammer_lib_src_list
+++ b/tools/windows/hammer_lib_src_list
@@ -9,7 +9,9 @@ desugar.c
 glue.c 
 hammer.c 
 pprint.c
+registry.c
 system_allocator.c
+tsearch.c
 parsers/action.c 
 parsers/and.c 
 parsers/attr_bool.c 
-- 
GitLab