From b3a8403b8e104835618ec91aff57ebceeb86c2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 13 Dec 2015 14:55:28 +0100 Subject: [PATCH 1/9] Remove more useless MSVC warnings --- tools/windows/clvars.bat | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/windows/clvars.bat b/tools/windows/clvars.bat index 6e338b7..1870ba5 100644 --- a/tools/windows/clvars.bat +++ b/tools/windows/clvars.bat @@ -7,6 +7,16 @@ set WARNINGS=-W4 -Wall -WX REM c4464 (relative include path contains '..') set WARNINGS=%WARNINGS% -wd4464 +REM c4189 (local variable is initialized but not referenced) +set WARNINGS=%WARNINGS% -wd4189 + +REM c4018 (signed/unsigned mismatch) +REM basically useless. Complains about obviously correct code like: +REM uint8_t x = 60; +REM size_t i = 9; +REM i < x/8 +set WARNINGS=%WARNINGS% -wd4018 + REM c4457 (declaration shadowing function parameter) REM FIXME(windows) TODO(uucidl): remove occurence of c4457 and reactivate REM FIXME(windows) TODO(uucidl): remove occurence of c4456 and reactivate From c5ca35c347eecdefa261eeb13d4676f219acc6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 13 Dec 2015 15:19:42 +0100 Subject: [PATCH 2/9] Remove c4388 signed/unsigned mismatch It is the counterpart to c4018 for x64 compilations. --- tools/windows/clvars.bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/windows/clvars.bat b/tools/windows/clvars.bat index 1870ba5..23772f6 100644 --- a/tools/windows/clvars.bat +++ b/tools/windows/clvars.bat @@ -10,12 +10,12 @@ set WARNINGS=%WARNINGS% -wd4464 REM c4189 (local variable is initialized but not referenced) set WARNINGS=%WARNINGS% -wd4189 -REM c4018 (signed/unsigned mismatch) +REM c4018/c4388 (signed/unsigned mismatch) REM basically useless. Complains about obviously correct code like: REM uint8_t x = 60; REM size_t i = 9; REM i < x/8 -set WARNINGS=%WARNINGS% -wd4018 +set WARNINGS=%WARNINGS% -wd4018 -wd4388 REM c4457 (declaration shadowing function parameter) REM FIXME(windows) TODO(uucidl): remove occurence of c4457 and reactivate From c95b2987b15607d29d87d5a78e9bd5809eb28355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 13 Dec 2015 14:57:42 +0100 Subject: [PATCH 3/9] Support variable array length instantiation on MSVC As MSVC doesn't implement C99, variable-length arrays are not supported. We use _alloca instead. --- src/parsers/choice.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/parsers/choice.c b/src/parsers/choice.c index dd3908c..90c3662 100644 --- a/src/parsers/choice.c +++ b/src/parsers/choice.c @@ -1,6 +1,20 @@ #include #include "parser_internal.h" +#if defined(__STDC_VERSION__) && ( \ + (__STDC_VERSION__ >= 201112L && !defined(__STDC_NO_VLA__)) || \ + (__STDC_VERSION__ >= 199901L) \ + ) +# define STACK_VLA(type,name,size) type name[size] +#else +# if defined(_MSC_VER) +# include // for _alloca +# define STACK_VLA(type,name,size) type* name = _alloca(size) +# else +# error "Missing VLA implementation for this compiler" +# endif +#endif + typedef struct { size_t len; HParser **p_array; @@ -53,11 +67,14 @@ static void desugar_choice(HAllocator *mm__, HCFStack *stk__, void *env) { static bool choice_ctrvm(HRVMProg *prog, void* env) { HSequence *s = (HSequence*)env; - uint16_t gotos[s->len]; + // NOTE(uucidl): stack allocation since this backend uses + // setjmp/longjmp for error handling. + STACK_VLA(uint16_t, gotos, s->len); for (size_t i=0; ilen; ++i) { uint16_t insn = h_rvm_insert_insn(prog, RVM_FORK, 0); - if (!h_compile_regex(prog, s->p_array[i])) + if (!h_compile_regex(prog, s->p_array[i])) { return false; + } gotos[i] = h_rvm_insert_insn(prog, RVM_GOTO, 65535); h_rvm_patch_arg(prog, insn, h_rvm_get_ip(prog)); } From 62d793b939045f36cf9abbb08b94ce6c6e9acafb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 13 Dec 2015 14:57:55 +0100 Subject: [PATCH 4/9] Remove warning about parser signature being wrong --- src/parsers/nothing.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c index 0a60108..398432e 100644 --- a/src/parsers/nothing.c +++ b/src/parsers/nothing.c @@ -1,6 +1,8 @@ #include "parser_internal.h" -static HParseResult* parse_nothing() { +static HParseResult* parse_nothing(void* x,HParseState* y) { + (void)(x); + (void)(y); // not a mistake, this parser always fails return NULL; } From 2623d1a5f1daeb08876682c8a05bd203c3fdb3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 13 Dec 2015 14:58:23 +0100 Subject: [PATCH 5/9] Add all remaining parsers that were not compiling on windows The last file to port for the library is registry.c --- tools/windows/hammer_lib_src_list | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/windows/hammer_lib_src_list b/tools/windows/hammer_lib_src_list index a8a4dc4..388f92f 100644 --- a/tools/windows/hammer_lib_src_list +++ b/tools/windows/hammer_lib_src_list @@ -12,9 +12,12 @@ system_allocator.c parsers/action.c parsers/and.c parsers/attr_bool.c +parsers/bind.c +parsers/bits.c parsers/butnot.c parsers/ch.c parsers/charset.c +parsers/choice.c parsers/difference.c parsers/end.c parsers/endianness.c @@ -25,6 +28,7 @@ parsers/indirect.c parsers/int_range.c parsers/many.c parsers/not.c +parsers/nothing.c parsers/optional.c parsers/permutation.c parsers/sequence.c From d6e6911ad1864e2ebd97dfdd647043b937a1eece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 20 Dec 2015 12:43:34 +0100 Subject: [PATCH 6/9] -y for install lcov --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b533da3..a7b78e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -92,12 +92,12 @@ matrix: env: BINDINGS=cpp CC=clang before_install: - sudo apt-get update -qq - - sudo apt-get install lcov + - sudo apt-get install -y lcov - gem install coveralls-lcov - if [ "$BINDINGS" != "none" ]; then sudo apt-get install -qq swig; fi - if [ "$BINDINGS" == "perl" ]; then sudo add-apt-repository ppa:dns/irc -y; sudo apt-get update -qq; sudo apt-get install -qq swig=2.0.8-1irc1~12.04; fi - if [ "$BINDINGS" == "python" ]; then sudo apt-get install -qq python-dev; fi - - if [ "$BINDINGS" == "dotnet" ]; then sudo add-apt-repository ppa:directhex/monoxide -y; sudo apt-get update -qq; sudo apt-get install -qq mono-devel mono-mcs nunit nunit-console; mozroots --import --sync; fi + - if [ "$BINDINGS" == "dotnet" ]; then sudo add-apt-repository ppa:directhex/monoxide -y; sudo apt-get update -qq; sudo apt-get install -y -qq mono-devel mono-mcs nunit nunit-console; mozroots --import --sync; fi install: true before_script: - if [ "$BINDINGS" == "php" ]; then phpenv config-add src/bindings/php/hammer.ini; fi From 206f5044a88fc3acc00fdcd1a1668c2833d44d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 31 Jan 2016 16:55:17 +0100 Subject: [PATCH 7/9] Remove warning about tail "potentially uninitialized" MSVC was complaining that the `tail` variable was potentially uninitialized in the while branch. Since the while loop is actually coupled to the if (head != NULL) that initializes the tail variable, we move them together, which makes the warning disappear. --- src/datastructures.c | 16 ++++++++-------- tools/windows/hammer_lib_src_list | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/datastructures.c b/src/datastructures.c index af8477b..451afb9 100644 --- a/src/datastructures.c +++ b/src/datastructures.c @@ -52,14 +52,14 @@ HSlist* h_slist_copy(HSlist *slist) { h_slist_push(ret, head->elem); tail = ret->head; head = head->next; - } - while (head != NULL) { - // append head item to tail in a new node - HSlistNode *node = h_arena_malloc(slist->arena, sizeof(HSlistNode)); - node->elem = head->elem; - node->next = NULL; - tail = tail->next = node; - head = head->next; + while (head != NULL) { + // append head item to tail in a new node + HSlistNode *node = h_arena_malloc(slist->arena, sizeof(HSlistNode)); + node->elem = head->elem; + node->next = NULL; + tail = tail->next = node; + head = head->next; + } } return ret; } diff --git a/tools/windows/hammer_lib_src_list b/tools/windows/hammer_lib_src_list index 388f92f..793619e 100644 --- a/tools/windows/hammer_lib_src_list +++ b/tools/windows/hammer_lib_src_list @@ -3,7 +3,8 @@ allocator.c benchmark.c bitreader.c bitwriter.c -cfgrammar.c +cfgrammar.c +datastructures.c desugar.c glue.c hammer.c From 9a7752b9a63b5c54086fa0b457fb907869a00186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 31 Jan 2016 17:27:19 +0100 Subject: [PATCH 8/9] 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 #include #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 +#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 +#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 +#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 From f9d8f1df7f34dd93a061fbb49dadefb9a973d35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= Date: Sun, 31 Jan 2016 18:11:27 +0100 Subject: [PATCH 9/9] Reactivate examples that can build on windows This is proof that Hammer can be linked and used in a windows program! --- appveyor.yml | 3 +-- examples/grammar.c | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2aef9c9..b0d87a7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,6 +14,5 @@ build_script: } - call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% - call tools\windows\build.bat -# FIXME(windows) TODO(uucidl): reactivate examples -# - call tools\windows\build_examples.bat +- call tools\windows\build_examples.bat - exit /b 0 diff --git a/examples/grammar.c b/examples/grammar.c index 7638fe9..a768060 100644 --- a/examples/grammar.c +++ b/examples/grammar.c @@ -22,11 +22,12 @@ const char *nonterminal_name(const HCFGrammar *g, const HCFChoice *nt) { // if user_data exists and is printable: if(nt->user_data != NULL && *(char*)(nt->user_data) > ' ' && *(char*)(nt->user_data) < 127) { - if(*(char*)(nt->user_data) != '0') { + char* user_str = (char*)(nt->user_data); + if(*user_str != '\0') { // user_data is a non-empty string - return nt->user_data; + return user_str; } else { - return nt->user_data+1; + return user_str+1; } }