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 d905320..8a079b5 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 0000000..8a94ab8 --- /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 0000000..154f87c --- /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 0000000..7b297db --- /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 793619e..3602a4d 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