diff --git a/.travis.yml b/.travis.yml index b533da3191e75912e6d34f8c0bdd4a1212e684f9..a7b78e3780c699cfe601bc92665139917a882cac 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 diff --git a/appveyor.yml b/appveyor.yml index 2aef9c9423e10b6671bbddb86c4f159335b69f26..b0d87a79e5da3885c61d060c2a615cf3092ee22e 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 7638fe99558149d9e2d47e5d1dc7f0299da189c1..a768060b3dd2ed1c751076427c8bd6459918f914 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; } } diff --git a/src/datastructures.c b/src/datastructures.c index af8477be36123a53506871827d4dae13d8c9002b..451afb94ec39932dfe1f8c58aa82c0777f73b011 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/src/parsers/choice.c b/src/parsers/choice.c index dd3908ce93168f468ba6e1ff531a59476e404411..90c3662b515babe4a69b0e24dc146ebe1d0a647d 100644 --- a/src/parsers/choice.c +++ b/src/parsers/choice.c @@ -1,6 +1,20 @@ #include <stdarg.h> #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 <malloc.h> // 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; i<s->len; ++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)); } diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c index 0a60108bcc2c0fe69a656fb1cfb4f067ff290922..398432ef460897e7cbd254e9f4f28a86ccecd9d3 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; } diff --git a/src/registry.c b/src/registry.c index d905320bbdf6131e5ab449c525086e4b1205a28b..8a079b5200f7415f878fa7f74fdaa181ee313669 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 0000000000000000000000000000000000000000..8a94ab83d556944a0d0f022bac3d0c3f1f80c884 --- /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 0000000000000000000000000000000000000000..154f87c43e0371ef9f8b623c757e39389c1d7829 --- /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 0000000000000000000000000000000000000000..7b297db7c7ea425f350f0d2c3350d55a630fb97b --- /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/clvars.bat b/tools/windows/clvars.bat index 6e338b78f33a3b7c03538511c6af9005bca42133..23772f6b9547a6131d762d284e6211351f9bcbc0 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/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 -wd4388 + 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 diff --git a/tools/windows/hammer_lib_src_list b/tools/windows/hammer_lib_src_list index a8a4dc4790e73ed6b64544c196416eaebc1e3db3..3602a4d525efef5a0c8745917f6b57684a971b9e 100644 --- a/tools/windows/hammer_lib_src_list +++ b/tools/windows/hammer_lib_src_list @@ -3,18 +3,24 @@ allocator.c benchmark.c bitreader.c bitwriter.c -cfgrammar.c +cfgrammar.c +datastructures.c 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 +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 +31,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