diff --git a/.travis.yml b/.travis.yml index b533da3191e75912e6d34f8c0bdd4a1212e684f9..2bf389e71f1e5274cac8b9de355a5674c41125c1 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; fi install: true before_script: - if [ "$BINDINGS" == "php" ]; then phpenv config-add src/bindings/php/hammer.ini; fi diff --git a/README.md b/README.md index 8880cb627764e56964782a2003b6091ab82182fa..ee62558146424c693adc99a87bfb0f79000e6b8c 100644 --- a/README.md +++ b/README.md @@ -29,19 +29,19 @@ Features Installing ========== ### Prerequisites -* SCons +* [SCons](http://scons.org/) ### Optional Dependencies * pkg-config (for `scons test`) * glib-2.0 (>= 2.29) (for `scons test`) * glib-2.0-dev (for `scons test`) -* swig (for Python/Perl/PHP bindings; Perl requires >= 2.0.8) +* [swig](http://swig.org/) (for Python/Perl/PHP bindings; Perl requires >= 2.0.8) * python2.7-dev (for Python bindings) * a JDK (for Java bindings) * a working [phpenv](https://github.com/CHH/phpenv) configuration (for PHP bindings) -* Ruby >= 1.9.3 and bundler, for the Ruby bindings +* [Ruby](https://www.ruby-lang.org/) >= 1.9.3 and bundler, for the Ruby bindings * mono-devel and mono-mcs (>= 3.0.6) (for .NET bindings) -* nunit (for testing .NET bindings) +* [nunit](http://www.nunit.org/) (for testing .NET bindings) To build, type `scons`. To run the built-in test suite, type `scons test`. For a debug build, add `--variant=debug`. @@ -60,13 +60,16 @@ Just `#include <hammer/hammer.h>` (also `#include <hammer/glue.h>` if you plan t If you've installed Hammer system-wide, you can use `pkg-config` in the usual way. -For documentation, see the [user guide](https://github.com/UpstandingHackers/hammer/wiki/User-guide). +To learn about hammer check +* the [user guide](https://github.com/UpstandingHackers/hammer/wiki/User-guide) +* [Hammer Primer](https://github.com/sergeybratus/HammerPrimer) (outdated in terms of code, but good to get the general thinking) +* [Try Hammer](https://github.com/sboesen/TryHammer) Examples ======== The `examples/` directory contains some simple examples, currently including: -* base64 -* DNS +* [base64](https://en.wikipedia.org/wiki/Base64) +* [DNS](https://en.wikipedia.org/wiki/Domain_Name_System) Known Issues ============ diff --git a/SConstruct b/SConstruct index bb2bb858e51ecf84db7588ba1c212bdf164e2e5d..41b467e976aa29985e80bab4ccf01c6f86236816 100644 --- a/SConstruct +++ b/SConstruct @@ -4,10 +4,13 @@ import os.path import platform import sys +default_install_dir='/usr/local' +if platform.system() == 'Windows': + default_install_dir = 'build' # no obvious place for installation on Windows vars = Variables(None, ARGUMENTS) -vars.Add(PathVariable('DESTDIR', "Root directory to install in (useful for packaging scripts)", None, PathVariable.PathIsDirCreate)) -vars.Add(PathVariable('prefix', "Where to install in the FHS", "/usr/local", PathVariable.PathAccept)) +vars.Add(PathVariable('DESTDIR', 'Root directory to install in (useful for packaging scripts)', None, PathVariable.PathIsDirCreate)) +vars.Add(PathVariable('prefix', 'Where to install in the FHS', default_install_dir, PathVariable.PathAccept)) vars.Add(ListVariable('bindings', 'Language bindings to build', 'none', ['cpp', 'dotnet', 'perl', 'php', 'python', 'ruby'])) tools = ['default', 'scanreplace'] @@ -17,6 +20,9 @@ if 'dotnet' in ARGUMENTS.get('bindings', []): envvars = {'PATH' : os.environ['PATH']} if 'PKG_CONFIG_PATH' in os.environ: envvars['PKG_CONFIG_PATH'] = os.environ['PKG_CONFIG_PATH'] +if platform.system() == 'Windows': + # from the scons FAQ (keywords: LNK1104 TEMPFILE), needed by link.exe + envvars['TMP'] = os.environ['TMP'] env = Environment(ENV = envvars, variables = vars, @@ -29,7 +35,7 @@ if not 'bindings' in env: def calcInstallPath(*elements): path = os.path.abspath(os.path.join(*map(env.subst, elements))) if 'DESTDIR' in env: - path = os.path.join(env['DESTDIR'], os.path.relpath(path, start="/")) + path = os.path.join(env['DESTDIR'], os.path.relpath(path, start='/')) return path rel_prefix = not os.path.isabs(env['prefix']) @@ -37,102 +43,131 @@ env['prefix'] = os.path.abspath(env['prefix']) if 'DESTDIR' in env: env['DESTDIR'] = os.path.abspath(env['DESTDIR']) if rel_prefix: - print >>sys.stderr, "--!!-- You used a relative prefix with a DESTDIR. This is probably not what you" - print >>sys.stderr, "--!!-- you want; files will be installed in" - print >>sys.stderr, "--!!-- %s" % (calcInstallPath("$prefix"),) + print >>sys.stderr, '--!!-- You used a relative prefix with a DESTDIR. This is probably not what you' + print >>sys.stderr, '--!!-- you want; files will be installed in' + print >>sys.stderr, '--!!-- %s' % (calcInstallPath('$prefix'),) -env['libpath'] = calcInstallPath("$prefix", "lib") -env['incpath'] = calcInstallPath("$prefix", "include", "hammer") -env['parsersincpath'] = calcInstallPath("$prefix", "include", "hammer", "parsers") -env['backendsincpath'] = calcInstallPath("$prefix", "include", "hammer", "backends") -env['pkgconfigpath'] = calcInstallPath("$prefix", "lib", "pkgconfig") +env['libpath'] = calcInstallPath('$prefix', 'lib') +env['incpath'] = calcInstallPath('$prefix', 'include', 'hammer') +env['parsersincpath'] = calcInstallPath('$prefix', 'include', 'hammer', 'parsers') +env['backendsincpath'] = calcInstallPath('$prefix', 'include', 'hammer', 'backends') +env['pkgconfigpath'] = calcInstallPath('$prefix', 'lib', 'pkgconfig') env.ScanReplace('libhammer.pc.in') -env.MergeFlags("-std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-attributes -Wno-unused-variable") +AddOption('--variant', + dest='variant', + nargs=1, type='choice', + choices=['debug', 'opt'], + default='opt', + action='store', + help='Build variant (debug or opt)') -if env['PLATFORM'] == 'darwin': - env.Append(SHLINKFLAGS = '-install_name ' + env["libpath"] + '/${TARGET.file}') -elif os.uname()[0] == "OpenBSD": - pass -else: - env.MergeFlags("-lrt") - -AddOption("--variant", - dest="variant", - nargs=1, type="choice", - choices=["debug", "opt"], - default="opt", - action="store", - help="Build variant (debug or opt)") - -AddOption("--coverage", - dest="coverage", +AddOption('--coverage', + dest='coverage', default=False, - action="store_true", - help="Build with coverage instrumentation") + action='store_true', + help='Build with coverage instrumentation') -AddOption("--in-place", - dest="in_place", +AddOption('--in-place', + dest='in_place', default=False, - action="store_true", - help="Build in-place, rather than in the build/<variant> tree") + action='store_true', + help='Build in-place, rather than in the build/<variant> tree') + +AddOption('--tests', + dest='with_tests', + default=env['PLATFORM'] != 'win32', + action='store_true', + help='Build tests') + +env['CC'] = os.getenv('CC') or env['CC'] +env['CXX'] = os.getenv('CXX') or env['CXX'] + +if os.getenv('CC') == 'clang' or env['PLATFORM'] == 'darwin': + env.Replace(CC='clang', + CXX='clang++') + +# Language standard and warnings +if env['CC'] == 'cl': + env.MergeFlags('-W3 -WX') + env.Append( + CPPDEFINES=[ + '_CRT_SECURE_NO_WARNINGS' # allow uses of sprintf + ], + CFLAGS=[ + '-wd4018', # 'expression' : signed/unsigned mismatch + '-wd4244', # 'argument' : conversion from 'type1' to 'type2', possible loss of data + '-wd4267', # 'var' : conversion from 'size_t' to 'type', possible loss of data + ] + ) +else: + env.MergeFlags('-std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-attributes -Wno-unused-variable') + +# Linker options +if env['PLATFORM'] == 'darwin': + env.Append(SHLINKFLAGS = '-install_name ' + env['libpath'] + '/${TARGET.file}') +elif platform.system() == 'OpenBSD': + pass +elif env['PLATFORM'] == 'win32': + # no extra lib needed + pass +else: + env.MergeFlags('-lrt') +if GetOption('coverage'): + env.Append(CFLAGS=['--coverage'], + CXXFLAGS=['--coverage'], + LDFLAGS=['--coverage']) + if env['CC'] == 'gcc': + env.Append(LIBS=['gcov']) + else: + env.ParseConfig('llvm-config --ldflags') dbg = env.Clone(VARIANT='debug') -dbg.Append(CCFLAGS=['-g']) +if env['CC'] == 'cl': + dbg.Append(CCFLAGS=['/Z7']) +else: + dbg.Append(CCFLAGS=['-g']) opt = env.Clone(VARIANT='opt') -opt.Append(CCFLAGS=["-O3"]) +if env['CC'] == 'cl': + opt.Append(CCFLAGS=['/O2']) +else: + opt.Append(CCFLAGS=['-O3']) -if GetOption("variant") == 'debug': +if GetOption('variant') == 'debug': env = dbg else: env = opt -env["CC"] = os.getenv("CC") or env["CC"] -env["CXX"] = os.getenv("CXX") or env["CXX"] - -if GetOption("coverage"): - env.Append(CFLAGS=["--coverage"], - CXXFLAGS=["--coverage"], - LDFLAGS=["--coverage"]) - if env["CC"] == "gcc": - env.Append(LIBS=['gcov']) - else: - env.ParseConfig('llvm-config --ldflags') - -if os.getenv("CC") == "clang" or env['PLATFORM'] == 'darwin': - env.Replace(CC="clang", - CXX="clang++") - -env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_")) +env['ENV'].update(x for x in os.environ.items() if x[0].startswith('CCC_')) #rootpath = env['ROOTPATH'] = os.path.abspath('.') -#env.Append(CPPPATH=os.path.join('#', "hammer")) +#env.Append(CPPPATH=os.path.join('#', 'hammer')) testruns = [] -targets = ["$libpath", - "$incpath", - "$parsersincpath", - "$backendsincpath", - "$pkgconfigpath"] +targets = ['$libpath', + '$incpath', + '$parsersincpath', + '$backendsincpath', + '$pkgconfigpath'] Export('env') Export('testruns') Export('targets') -if not GetOption("in_place"): +if not GetOption('in_place'): env['BUILD_BASE'] = 'build/$VARIANT' - lib = env.SConscript(["src/SConscript"], variant_dir='$BUILD_BASE/src') - env.Alias("examples", env.SConscript(["examples/SConscript"], variant_dir='$BUILD_BASE/examples')) + lib = env.SConscript(['src/SConscript'], variant_dir='$BUILD_BASE/src') + env.Alias('examples', env.SConscript(['examples/SConscript'], variant_dir='$BUILD_BASE/examples')) else: env['BUILD_BASE'] = '.' - lib = env.SConscript(["src/SConscript"]) - env.Alias(env.SConscript(["examples/SConscript"])) + lib = env.SConscript(['src/SConscript']) + env.Alias(env.SConscript(['examples/SConscript'])) for testrun in testruns: - env.Alias("test", testrun) + env.Alias('test', testrun) -env.Alias("install", targets) +env.Alias('install', targets) diff --git a/appveyor.yml b/appveyor.yml index 2aef9c9423e10b6671bbddb86c4f159335b69f26..16aa8e8207c545f987ad6e127a48a399ae5bbe9e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,16 @@ platform: - x86 - x64 +environment: + PYTHON: "C:\\Python27" version: 1.0.{build} os: Visual Studio 2015 +install: + - SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" + - easy_install scons build_script: +- scons --version +- scons install - '@echo off' - setlocal - ps: >- @@ -14,6 +21,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/SConscript b/src/SConscript index 3d2545204b23b1108c1fc2228ca2bef43b0358b5..2e446c62eb05b6f8be255e74faa81f269f3994bf 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,23 +1,24 @@ # -*- python -*- import os.path + Import('env testruns') dist_headers = [ - "hammer.h", - "allocator.h", - "compiler_specifics.h", - "glue.h", - "internal.h", - "platform.h" + 'hammer.h', + 'allocator.h', + 'compiler_specifics.h', + 'glue.h', + 'internal.h', + 'platform.h' ] parsers_headers = [ - "parsers/parser_internal.h" + 'parsers/parser_internal.h' ] backends_headers = [ - "backends/regex.h", - "backends/contextfree.h" + 'backends/regex.h', + 'backends/contextfree.h' ] parsers = ['parsers/%s.c'%s for s in @@ -48,7 +49,7 @@ parsers = ['parsers/%s.c'%s for s in 'unimplemented', 'whitespace', 'xor', - 'value']] + 'value']] backends = ['backends/%s.c' % s for s in ['packrat', 'llk', 'regex', 'glr', 'lalr', 'lr', 'lr0']] @@ -63,12 +64,19 @@ misc_hammer_parts = [ 'desugar.c', 'glue.c', 'hammer.c', - 'platform_bsdlike.c', 'pprint.c', 'registry.c', 'system_allocator.c', 'sloballoc.c'] +if env['PLATFORM'] == 'win32': + misc_hammer_parts += [ + 'platform_win32.c', + 'tsearch.c', + ] +else: + misc_hammer_parts += ['platform_bsdlike.c'] + ctests = ['t_benchmark.c', 't_bitreader.c', 't_bitwriter.c', @@ -78,26 +86,40 @@ ctests = ['t_benchmark.c', 't_mm.c', 't_regression.c'] + +static_library_name = 'hammer' +build_shared_library=True +if env['PLATFORM'] == 'win32': + # FIXME(windows): symbols in hammer are not exported yet, a shared lib would be useless + build_shared_library=False + # prevent collision between .lib from dll and .lib for static lib + static_library_name = 'hammer_s' + libhammer_shared = env.SharedLibrary('hammer', parsers + backends + misc_hammer_parts) -libhammer_static = env.StaticLibrary('hammer', parsers + backends + misc_hammer_parts) -Default(libhammer_shared, libhammer_static) - -env.Install("$libpath", [libhammer_static, libhammer_shared]) -env.Install("$incpath", dist_headers) -env.Install("$parsersincpath", parsers_headers) -env.Install("$backendsincpath", backends_headers) -env.Install("$pkgconfigpath", "../../../libhammer.pc") - -testenv = env.Clone() -testenv.ParseConfig('pkg-config --cflags --libs glib-2.0') -testenv.Append(LIBS=['hammer']) -testenv.Prepend(LIBPATH=['.']) -ctestexec = testenv.Program('test_suite', ctests + ['test_suite.c'], LINKFLAGS="--coverage" if testenv.GetOption("coverage") else None) -ctest = Alias('testc', [ctestexec], "".join(["env LD_LIBRARY_PATH=", os.path.dirname(ctestexec[0].path), " ", ctestexec[0].path])) -AlwaysBuild(ctest) -testruns.append(ctest) - -Export("libhammer_static libhammer_shared") +libhammer_static = env.StaticLibrary(static_library_name, parsers + backends + misc_hammer_parts) +if build_shared_library: + Default(libhammer_shared, libhammer_static) + env.Install('$libpath', [libhammer_static, libhammer_shared]) +else: + Default(libhammer_static) + env.Install('$libpath', [libhammer_static]) + +env.Install('$incpath', dist_headers) +env.Install('$parsersincpath', parsers_headers) +env.Install('$backendsincpath', backends_headers) +env.Install('$pkgconfigpath', '../../../libhammer.pc') + +if GetOption('with_tests'): + testenv = env.Clone() + testenv.ParseConfig('pkg-config --cflags --libs glib-2.0') + testenv.Append(LIBS=['hammer']) + testenv.Prepend(LIBPATH=['.']) + ctestexec = testenv.Program('test_suite', ctests + ['test_suite.c'], LINKFLAGS='--coverage' if testenv.GetOption('coverage') else None) + ctest = Alias('testc', [ctestexec], ''.join(['env LD_LIBRARY_PATH=', os.path.dirname(ctestexec[0].path), ' ', ctestexec[0].path])) + AlwaysBuild(ctest) + testruns.append(ctest) + +Export('libhammer_static libhammer_shared') for b in env['bindings']: - env.SConscript(["bindings/%s/SConscript" % b]) + env.SConscript(['bindings/%s/SConscript' % b]) diff --git a/src/backends/regex.c b/src/backends/regex.c index f7dd98add85844366cca53aa96be31c596b4221c..9646ddd59343cacbd1cc53645161c88d70c15f78 100644 --- a/src/backends/regex.c +++ b/src/backends/regex.c @@ -206,16 +206,43 @@ bool svm_stack_ensure_cap(HAllocator *mm__, HSVMContext *ctx, size_t addl) { return true; } +/* + * GCC produces the following diagnostic on this function: + * + * error: argument 'trace' might be clobbered by 'longjmp' or 'vfork' [-Werror=clobbered] + * + * However, this is spurious; what is happening is that the trace + * argument gets reused to store cur, and GCC doesn't know enough + * about setjmp to know that the second return only returns nonzero + * (and therefore the now-clobbered value of trace is invalid.) + * + * A side effect of disabling this warning is that we need to be + * careful about undefined behaviour involving automatic + * variables. Specifically, any automatic variable in this function + * whose value gets modified after setjmp has an undefined value after + * the second return; here, the only variables that could matter for + * are arena and ctx (because they're referenced in "goto fail"). + */ +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC diagnostic ignored "-Wclobbered" +#endif HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace, const uint8_t *input, int len) { // orig_prog is only used for the action table - HSVMContext ctx; + HSVMContext *ctx = NULL; HArena *arena = h_new_arena(mm__, 0); - ctx.stack_count = 0; - ctx.stack_capacity = 16; - ctx.stack = h_new(HParsedToken*, ctx.stack_capacity); + if (arena == NULL) { + return NULL; + } + ctx = h_new(HSVMContext, 1); + if (!ctx) goto fail; + ctx->stack_count = 0; + ctx->stack_capacity = 16; + ctx->stack = h_new(HParsedToken*, ctx->stack_capacity); // out of memory handling - if(!arena || !ctx.stack) + if(!arena || !ctx->stack) goto fail; jmp_buf except; h_arena_set_except(arena, &except); @@ -227,20 +254,20 @@ HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace, for (cur = trace; cur; cur = cur->next) { switch (cur->opcode) { case SVM_PUSH: - if (!svm_stack_ensure_cap(mm__, &ctx, 1)) { + if (!svm_stack_ensure_cap(mm__, ctx, 1)) { goto fail; } tmp_res = a_new(HParsedToken, 1); tmp_res->token_type = TT_MARK; tmp_res->index = cur->input_pos; tmp_res->bit_offset = 0; - ctx.stack[ctx.stack_count++] = tmp_res; + ctx->stack[ctx->stack_count++] = tmp_res; break; case SVM_NOP: break; case SVM_ACTION: // Action should modify stack appropriately - if (!orig_prog->actions[cur->arg].action(arena, &ctx, orig_prog->actions[cur->arg].env)) { + if (!orig_prog->actions[cur->arg].action(arena, ctx, orig_prog->actions[cur->arg].env)) { // action failed... abort somehow goto fail; @@ -249,9 +276,9 @@ HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace, case SVM_CAPTURE: // Top of stack must be a mark // This replaces said mark in-place with a TT_BYTES. - assert(ctx.stack[ctx.stack_count-1]->token_type == TT_MARK); + assert(ctx->stack[ctx->stack_count-1]->token_type == TT_MARK); - tmp_res = ctx.stack[ctx.stack_count-1]; + tmp_res = ctx->stack[ctx->stack_count-1]; tmp_res->token_type = TT_BYTES; // TODO: Will need to copy if bit_offset is nonzero assert(tmp_res->bit_offset == 0); @@ -260,25 +287,33 @@ HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace, tmp_res->bytes.len = cur->input_pos - tmp_res->index; break; case SVM_ACCEPT: - assert(ctx.stack_count <= 1); + assert(ctx->stack_count <= 1); HParseResult *res = a_new(HParseResult, 1); - if (ctx.stack_count == 1) { - res->ast = ctx.stack[0]; + if (ctx->stack_count == 1) { + res->ast = ctx->stack[0]; } else { res->ast = NULL; } res->bit_length = cur->input_pos * 8; res->arena = arena; h_arena_set_except(arena, NULL); - h_free(ctx.stack); + h_free(ctx->stack); + h_free(ctx); return res; } } fail: if (arena) h_delete_arena(arena); - if (ctx.stack) h_free(ctx.stack); + if (ctx) { + if (ctx->stack) h_free(ctx->stack); + h_free(ctx); + } return NULL; } +// Reenable -Wclobber +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif uint16_t h_rvm_create_action(HRVMProg *prog, HSVMActionFunc action_func, void* env) { for (uint16_t i = 0; i < prog->action_count; i++) { diff --git a/src/bindings/ruby/README.md b/src/bindings/ruby/README.md index ae29459f309a7e8121a199200e50a6572b10c5d6..480f25592323435549c619e2bf2985b499f6de4c 100644 --- a/src/bindings/ruby/README.md +++ b/src/bindings/ruby/README.md @@ -21,12 +21,37 @@ Ruby bindings for [hammer](https://github.com/UpstandingHackers/hammer), a parsi ## Installation -TODO +1. Download the hammer source code, and make it available system wide with the bindings. + + `git clone https://github.com/UpstandingHackers/hammer` + `cd hammer` + + `scons bindings=ruby` + + `sudo scons bindings=ruby install` + +2. On linux, you will have to do + + `sudo ldconfig` + +3. Build the gem + `gem build hammer-parser.gemspec` + +4. Install the gem + `gem install hammer-parser-x.x.x.gem` ## Examples +Add hammer to your Gemfile. + + `gem 'hammer-parser'` + +Use hammer in your project. + + `require 'hammer'` + ### Building a parser ```ruby diff --git a/src/bindings/ruby/hammer-parser.gemspec b/src/bindings/ruby/hammer-parser.gemspec index 18b4db738ad9325526dbdca381d0acf93f112d3c..9a4a616ab8383e0afe2bd5240fd64d2986effcbd 100644 --- a/src/bindings/ruby/hammer-parser.gemspec +++ b/src/bindings/ruby/hammer-parser.gemspec @@ -5,9 +5,9 @@ Gem::Specification.new do |s| s.summary = 'Ruby bindings to the hammer parsing library.' s.description = s.summary # TODO: longer description? s.authors = ['Meredith L. Patterson', 'TQ Hirsch', 'Jakob Rath'] - # TODO: - # s.email = ... - # s.homepage = ... + s.email = 'hammer@upstandinghackers.com' + s.homepage = 'https://github.com/UpstandingHackers/hammer' + s.license = 'GPL-2.0' files = [] files << 'README.md' 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/hammer.h b/src/hammer.h index 6c2bf4977087d019581057f61833b5c2175e022d..ad44fee910fcf42445e57e47ec8c1fe2d18d3724 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -778,10 +778,25 @@ void h_benchmark_report(FILE* stream, HBenchmarkResults* results); //void h_benchmark_dump_optimized_code(FILE* stream, HBenchmarkResults* results); // }}} +// {{{ result_buf printers (used by token type registry) + +struct result_buf; + +bool h_append_buf(struct result_buf *buf, const char* input, int len); +bool h_append_buf_c(struct result_buf *buf, char v); +bool h_append_buf_formatted(struct result_buf *buf, char* format, ...); + +// }}} + // {{{ Token type registry /// Allocate a new, unused (as far as this function knows) token type. HTokenType h_allocate_token_type(const char* name); +/// Allocate a new token type with an unambiguous print function. +HTokenType h_allocate_token_new( + const char* name, + void (*unamb_sub)(const HParsedToken *tok, struct result_buf *buf)); + /// Get the token type associated with name. Returns -1 if name is unkown HTokenType h_get_token_type_number(const char* name); diff --git a/src/internal.h b/src/internal.h index 10db4b20f429283bbf0aa99928487b2754379d91..0e92e99e6facf5d04c6b13ca8de51272ba630a1d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -422,6 +422,18 @@ struct HParserVtable_ { bool higher; // false if primitive }; +// {{{ Token type registry internal + +typedef struct HTTEntry_ { + const char* name; + HTokenType value; + void (*unamb_sub)(const HParsedToken *tok, struct result_buf *buf); +} HTTEntry; + +const HTTEntry* h_get_token_type_entry(HTokenType token_type); + +// }}} + bool h_false(void*); bool h_true(void*); bool h_not_regular(HRVMProg*, void*); 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/pprint.c b/src/pprint.c index 9c7c6522c0a201cf544ffaea3227510fec4bf827..52f42eb6060230a8bb608b8e5ab1eafb6ef1467c 100644 --- a/src/pprint.c +++ b/src/pprint.c @@ -41,10 +41,10 @@ void h_pprint(FILE* stream, const HParsedToken* tok, int indent, int delta) { else { fprintf(stream, "%*s", indent, ""); for (size_t i = 0; i < tok->bytes.len; i++) { - fprintf(stream, - "%c%02hhx", - (i == 0) ? '<' : '.', - tok->bytes.token[i]); + fprintf(stream, + "%c%02hhx", + (i == 0) ? '<' : '.', + tok->bytes.token[i]); } fprintf(stream, ">\n"); } @@ -54,7 +54,7 @@ void h_pprint(FILE* stream, const HParsedToken* tok, int indent, int delta) { fprintf(stream, "%*ss -%#" PRIx64 "\n", indent, "", -tok->sint); else fprintf(stream, "%*ss %#" PRIx64 "\n", indent, "", tok->sint); - + break; case TT_UINT: fprintf(stream, "%*su %#" PRIx64 "\n", indent, "", tok->uint); @@ -96,7 +96,7 @@ static inline bool ensure_capacity(struct result_buf *buf, int amt) { return true; } -static inline bool append_buf(struct result_buf *buf, const char* input, int len) { +bool h_append_buf(struct result_buf *buf, const char* input, int len) { if (ensure_capacity(buf, len)) { memcpy(buf->output + buf->len, input, len); buf->len += len; @@ -106,7 +106,7 @@ static inline bool append_buf(struct result_buf *buf, const char* input, int len } } -static inline bool append_buf_c(struct result_buf *buf, char v) { +bool h_append_buf_c(struct result_buf *buf, char v) { if (ensure_capacity(buf, 1)) { buf->output[buf->len++] = v; return true; @@ -116,7 +116,7 @@ static inline bool append_buf_c(struct result_buf *buf, char v) { } /** append a formatted string to the result buffer */ -static inline bool append_buf_formatted(struct result_buf *buf, char* format, ...) +bool h_append_buf_formatted(struct result_buf *buf, char* format, ...) { char* tmpbuf; int len; @@ -125,7 +125,7 @@ static inline bool append_buf_formatted(struct result_buf *buf, char* format, .. va_start(ap, format); len = h_platform_vasprintf(&tmpbuf, format, ap); - result = append_buf(buf, tmpbuf, len); + result = h_append_buf(buf, tmpbuf, len); free(tmpbuf); va_end(ap); @@ -134,52 +134,59 @@ static inline bool append_buf_formatted(struct result_buf *buf, char* format, .. static void unamb_sub(const HParsedToken* tok, struct result_buf *buf) { if (!tok) { - append_buf(buf, "NULL", 4); + h_append_buf(buf, "NULL", 4); return; } switch (tok->token_type) { case TT_NONE: - append_buf(buf, "null", 4); + h_append_buf(buf, "null", 4); break; case TT_BYTES: if (tok->bytes.len == 0) - append_buf(buf, "<>", 2); + h_append_buf(buf, "<>", 2); else { for (size_t i = 0; i < tok->bytes.len; i++) { - const char *HEX = "0123456789abcdef"; - append_buf_c(buf, (i == 0) ? '<': '.'); - char c = tok->bytes.token[i]; - append_buf_c(buf, HEX[(c >> 4) & 0xf]); - append_buf_c(buf, HEX[(c >> 0) & 0xf]); + const char *HEX = "0123456789abcdef"; + h_append_buf_c(buf, (i == 0) ? '<': '.'); + char c = tok->bytes.token[i]; + h_append_buf_c(buf, HEX[(c >> 4) & 0xf]); + h_append_buf_c(buf, HEX[(c >> 0) & 0xf]); } - append_buf_c(buf, '>'); + h_append_buf_c(buf, '>'); } break; case TT_SINT: if (tok->sint < 0) - append_buf_formatted(buf, "s-%#" PRIx64, -tok->sint); + h_append_buf_formatted(buf, "s-%#" PRIx64, -tok->sint); else - append_buf_formatted(buf, "s%#" PRIx64, tok->sint); + h_append_buf_formatted(buf, "s%#" PRIx64, tok->sint); break; case TT_UINT: - append_buf_formatted(buf, "u%#" PRIx64, tok->uint); + h_append_buf_formatted(buf, "u%#" PRIx64, tok->uint); break; case TT_ERR: - append_buf(buf, "ERR", 3); + h_append_buf(buf, "ERR", 3); break; case TT_SEQUENCE: { - append_buf_c(buf, '('); + h_append_buf_c(buf, '('); for (size_t i = 0; i < tok->seq->used; i++) { if (i > 0) - append_buf_c(buf, ' '); + h_append_buf_c(buf, ' '); unamb_sub(tok->seq->elements[i], buf); } - append_buf_c(buf, ')'); + h_append_buf_c(buf, ')'); } break; - default: - fprintf(stderr, "Unexpected token type %d\n", tok->token_type); - assert_message(0, "Should not reach here."); + default: { + const HTTEntry *e = h_get_token_type_entry(tok->token_type); + if (e) { + h_append_buf_c(buf, '{'); + e->unamb_sub(tok, buf); + h_append_buf_c(buf, '}'); + } else { + assert_message(0, "Bogus token type."); + } + } } } @@ -192,7 +199,7 @@ char* h_write_result_unamb(const HParsedToken* tok) { }; assert(buf.output != NULL); unamb_sub(tok, &buf); - append_buf_c(&buf, 0); + h_append_buf_c(&buf, 0); return buf.output; } diff --git a/src/registry.c b/src/registry.c index d905320bbdf6131e5ab449c525086e4b1205a28b..a8646c14ed97f42f263770d5ebdd3b7e8c032b10 100644 --- a/src/registry.c +++ b/src/registry.c @@ -15,18 +15,19 @@ * 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" -typedef struct Entry_ { - const char* name; - HTokenType value; -} Entry; +#if defined(_MSC_VER) +#define h_strdup _strdup +#else +#define h_strdup strdup +#endif static void *tt_registry = NULL; -static Entry** tt_by_id = NULL; +static HTTEntry** tt_by_id = NULL; static unsigned int tt_by_id_sz = 0; #define TT_START TT_USER static HTokenType tt_next = TT_START; @@ -34,23 +35,31 @@ static HTokenType tt_next = TT_START; /* // TODO: These are for the extension registry, which does not yet have a good name. static void *ext_registry = NULL; -static Entry** ext_by_id = NULL; +static HTTEntry** ext_by_id = NULL; static int ext_by_id_sz = 0; static int ext_next = 0; */ static int compare_entries(const void* v1, const void* v2) { - const Entry *e1 = (Entry*)v1, *e2 = (Entry*)v2; + const HTTEntry *e1 = (HTTEntry*)v1, *e2 = (HTTEntry*)v2; return strcmp(e1->name, e2->name); } -HTokenType h_allocate_token_type(const char* name) { - Entry* new_entry = h_alloc(&system_allocator, sizeof(*new_entry)); +static void default_unamb_sub(const HParsedToken* tok, + struct result_buf* buf) { + h_append_buf_formatted(buf, "XXX AMBIGUOUS USER TYPE %d", tok->token_type); +} + +HTokenType h_allocate_token_new( + const char* name, + void (*unamb_sub)(const HParsedToken *tok, struct result_buf *buf)) { + HTTEntry* new_entry = h_alloc(&system_allocator, sizeof(*new_entry)); assert(new_entry != NULL); new_entry->name = name; new_entry->value = 0; - Entry* probe = *(Entry**)tsearch(new_entry, &tt_registry, compare_entries); + new_entry->unamb_sub = unamb_sub; + HTTEntry* probe = *(HTTEntry**)tsearch(new_entry, &tt_registry, compare_entries); if (probe->value != 0) { // Token type already exists... // TODO: treat this as a bug? @@ -58,7 +67,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) { @@ -75,10 +84,13 @@ HTokenType h_allocate_token_type(const char* name) { return probe->value; } } +HTokenType h_allocate_token_type(const char* name) { + return h_allocate_token_new(name, default_unamb_sub); +} HTokenType h_get_token_type_number(const char* name) { - Entry e; + HTTEntry e; e.name = name; - Entry **ret = (Entry**)tfind(&e, &tt_registry, compare_entries); + HTTEntry **ret = (HTTEntry**)tfind(&e, &tt_registry, compare_entries); if (ret == NULL) return 0; else @@ -90,3 +102,9 @@ const char* h_get_token_type_name(HTokenType token_type) { else return tt_by_id[token_type - TT_START]->name; } +const HTTEntry* h_get_token_type_entry(HTokenType token_type) { + if (token_type >= tt_next || token_type < TT_START) + return NULL; + else + return tt_by_id[token_type - TT_START]; +} 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/build.bat b/tools/windows/build.bat index 20f878acab296420cb8b29fa36df74aad26eeb44..2bf3901648adfabddbfa33e76bc3d0dc1bcf53a1 100644 --- a/tools/windows/build.bat +++ b/tools/windows/build.bat @@ -24,8 +24,8 @@ cl.exe -nologo -FC -EHsc -Z7 -Oi -GR- -Gm- %CLFLAGS% -c ^ -Fo%BUILD%\obj\ if %errorlevel% neq 0 goto err -lib.exe %BUILD%\obj\*.obj -OUT:%BUILD%\hammer.lib -echo STATIC_LIBRARY %BUILD%\hammer.lib +lib.exe %BUILD%\obj\*.obj -OUT:%BUILD%\lib\hammer_s.lib +echo STATIC_LIBRARY %BUILD%\lib\hammer_s.lib if %errorlevel% neq 0 goto err popd diff --git a/tools/windows/build_examples.bat b/tools/windows/build_examples.bat index c431faebcd29d7b1a1aaeaa77558b948fc3454f0..b6f82487b1ec47d59eb1c5cc653be3961516342a 100644 --- a/tools/windows/build_examples.bat +++ b/tools/windows/build_examples.bat @@ -15,7 +15,7 @@ call %HEREPATH%\clvars.bat echo SRC=%SRC%, BUILD=%BUILD% echo CLFLAGS=%CLFLAGS% -set HAMMERLIB=%BUILD%\hammer.lib +set HAMMERLIB=%BUILD%\lib\hammer_s.lib REM Now let's build some example programs 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