diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000000000000000000000000000000000..2aef9c9423e10b6671bbddb86c4f159335b69f26 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,19 @@ +platform: +- x86 +- x64 +version: 1.0.{build} +os: Visual Studio 2015 +build_script: +- '@echo off' +- setlocal +- ps: >- + If ($env:Platform -Match "x86") { + $env:VCVARS_PLATFORM="x86" + } Else { + $env:VCVARS_PLATFORM="amd64" + } +- call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% +- call tools\windows\build.bat +# FIXME(windows) TODO(uucidl): reactivate examples +# - call tools\windows\build_examples.bat +- exit /b 0 diff --git a/src/SConscript b/src/SConscript index e192b05e182b0020ac7f931f68244b300b93b9bc..05ffa983674488db41cc0c6f32f642c2f43e30f8 100644 --- a/src/SConscript +++ b/src/SConscript @@ -5,6 +5,7 @@ Import('env testruns') dist_headers = [ "hammer.h", "allocator.h", + "compiler_specifics.h", "glue.h", "internal.h" ] @@ -61,6 +62,7 @@ misc_hammer_parts = [ 'desugar.c', 'glue.c', 'hammer.c', + 'platform_bsdlike.c', 'pprint.c', 'registry.c', 'system_allocator.c'] diff --git a/src/backends/contextfree.h b/src/backends/contextfree.h index 9105636f1d19a06bf9c69fc1484338c485904655..29b51a08ac3c39251170ce50f6c85448f5adf65f 100644 --- a/src/backends/contextfree.h +++ b/src/backends/contextfree.h @@ -22,7 +22,7 @@ struct HCFStack_ { }; #ifndef UNUSED -#define UNUSED __attribute__((unused)) +#define UNUSED H_GCC_ATTRIBUTE((unused)) #endif static inline HCFChoice* h_cfstack_new_choice_raw(HAllocator *mm__, HCFStack *stk__) UNUSED; diff --git a/src/backends/packrat.c b/src/backends/packrat.c index 33082c6c278beb09b2abf767e5314d18ab471db4..e6f86f2957e5988dd94557534ab66b6050fda915 100644 --- a/src/backends/packrat.c +++ b/src/backends/packrat.c @@ -126,7 +126,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head) h_hashtable_put(state->recursion_heads, &k->input_pos, head); HParserCacheValue *old_cached = h_hashtable_get(state->cache, k); if (!old_cached || PC_LEFT == old_cached->value_type) - errx(1, "impossible match"); + h_platform_errx(1, "impossible match"); HParseResult *old_res = old_cached->right; // rewind the input @@ -148,7 +148,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head) state->input_stream = cached->input_stream; return cached->right; } else { - errx(1, "impossible match"); + h_platform_errx(1, "impossible match"); } } } else { @@ -173,7 +173,7 @@ HParseResult* lr_answer(HParserCacheKey *k, HParseState *state, HLeftRec *growab return grow(k, state, growable->head); } } else { - errx(1, "lrAnswer with no head"); + h_platform_errx(1, "lrAnswer with no head"); } } diff --git a/src/bindings/cpp/hammer/hammer_test.hpp b/src/bindings/cpp/hammer/hammer_test.hpp index 77e6daa3fccd31d296d3d364a75bcc0cce5d7354..f3ab77a377d569a3b42255b050e7d6d8324837aa 100644 --- a/src/bindings/cpp/hammer/hammer_test.hpp +++ b/src/bindings/cpp/hammer/hammer_test.hpp @@ -5,7 +5,7 @@ #include <gtest/gtest.h> #include <hammer/hammer.hpp> -#define HAMMER_DECL_UNUSED __attribute__((unused)) +#define HAMMER_DECL_UNUSED H_GCC_ATTRIBUTE((unused)) static ::testing::AssertionResult ParseFails (hammer::Parser parser, const std::string &input) HAMMER_DECL_UNUSED; diff --git a/src/bindings/desugar-header.pl b/src/bindings/desugar-header.pl index 5bdd11e665b86af623583a94002551795d7b9ade..e836ad7a8bd0af6299008696f22f2f9a549d4b82 100644 --- a/src/bindings/desugar-header.pl +++ b/src/bindings/desugar-header.pl @@ -11,7 +11,7 @@ while(<>) { } elsif (/^HAMMER_FN_DECL\(([^,]*), ([^,]*), ([^)]*)\);/) { print "$1 $2($3);\n"; print "$1 $2__m(HAllocator* mm__, $3);\n"; - } elsif (/^HAMMER_FN_DECL_VARARGS_ATTR\((__attribute__\(\([^)]*\)\)), ([^,]*), ([^,]*), ([^)]*)\);/) { + } elsif (/^HAMMER_FN_DECL_VARARGS_ATTR\((H_GCC_ATTRIBUTE\(\([^)]*\)\)), ([^,]*), ([^,]*), ([^)]*)\);/) { print "$2 $3($4, ...);\n"; print "$2 $3__m(HAllocator *mm__, $4, ...);\n"; print "$2 $3__a(void* args);\n"; diff --git a/src/compiler_specifics.h b/src/compiler_specifics.h new file mode 100644 index 0000000000000000000000000000000000000000..ed09d664fa52557ce5505f789c37ffb881a5f753 --- /dev/null +++ b/src/compiler_specifics.h @@ -0,0 +1,16 @@ +#ifndef HAMMER_COMPILER_SPECIFICS__H +#define HAMMER_COMPILER_SPECIFICS__H + +#if defined(__clang__) || defined(__GNUC__) +#define H_GCC_ATTRIBUTE(x) __attribute__(x) +#else +#define H_GCC_ATTRIBUTE(x) +#endif + +#if defined(_MSC_VER) +#define H_MSVC_DECLSPEC(x) __declspec(x) +#else +#define H_MSVC_DECLSPEC(x) +#endif + +#endif diff --git a/src/hammer.c b/src/hammer.c index 6bb9ebb4febe53668a91ae9617ba05f2c158023d..443c77b790b10b5592958a55e7d457bc695c030a 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -17,7 +17,6 @@ #include <assert.h> #include <ctype.h> -#include <err.h> #include <limits.h> #include <stdarg.h> #include <string.h> diff --git a/src/hammer.h b/src/hammer.h index 50b3de5c939e94084f73499b031962029104c136..42c73458a4d0e513f4400e1a3c6790e9cc736a9e 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -17,6 +17,9 @@ #ifndef HAMMER_HAMMER__H #define HAMMER_HAMMER__H + +#include "compiler_specifics.h" + #ifndef HAMMER_INTERNAL__NO_STDARG_H #include <stdarg.h> #endif // HAMMER_INTERNAL__NO_STDARG_H @@ -434,7 +437,7 @@ HAMMER_FN_DECL_NOARG(HParser*, h_nothing_p); * * Result token type: TT_SEQUENCE */ -HAMMER_FN_DECL_VARARGS_ATTR(__attribute__((sentinel)), HParser*, h_sequence, HParser* p); +HAMMER_FN_DECL_VARARGS_ATTR(H_GCC_ATTRIBUTE((sentinel)), HParser*, h_sequence, HParser* p); /** * Given an array of parsers, p_array, apply each parser in order. The @@ -443,7 +446,7 @@ HAMMER_FN_DECL_VARARGS_ATTR(__attribute__((sentinel)), HParser*, h_sequence, HPa * * Result token type: The type of the first successful parser's result. */ -HAMMER_FN_DECL_VARARGS_ATTR(__attribute__((sentinel)), HParser*, h_choice, HParser* p); +HAMMER_FN_DECL_VARARGS_ATTR(H_GCC_ATTRIBUTE((sentinel)), HParser*, h_choice, HParser* p); /** * Given a null-terminated list of parsers, match a permutation phrase of these @@ -469,7 +472,7 @@ HAMMER_FN_DECL_VARARGS_ATTR(__attribute__((sentinel)), HParser*, h_choice, HPars * * Result token type: TT_SEQUENCE */ -HAMMER_FN_DECL_VARARGS_ATTR(__attribute__((sentinel)), HParser*, h_permutation, HParser* p); +HAMMER_FN_DECL_VARARGS_ATTR(H_GCC_ATTRIBUTE((sentinel)), HParser*, h_permutation, HParser* p); /** * Given two parsers, p1 and p2, this parser succeeds in the following diff --git a/src/internal.h b/src/internal.h index ed1bd0856febf3fa422a471a21051d75d33d5297..9aac4ee7dbaa4c4a1b8e87785b98f22265f37c71 100644 --- a/src/internal.h +++ b/src/internal.h @@ -24,9 +24,9 @@ #define HAMMER_INTERNAL__H #include <stdint.h> #include <assert.h> -#include <err.h> #include <string.h> #include "hammer.h" +#include "platform.h" /* "Internal" in this case means "we're not ready to commit * to a public API." Many structures and routines here will be @@ -38,7 +38,7 @@ #else #define assert_message(check, message) do { \ if (!(check)) \ - errx(1, "Assertion failed (programmer error): %s", message); \ + h_platform_errx(1, "Assertion failed (programmer error): %s", message); \ } while(0) #endif diff --git a/src/parsers/many.c b/src/parsers/many.c index 1e3b0221ceae76c782a317e1c5c17b21a496f4a1..51d733fcf87e3191e6f413a9513ac7900d29d8f2 100644 --- a/src/parsers/many.c +++ b/src/parsers/many.c @@ -246,7 +246,7 @@ static HParseResult* parse_length_value(void *env, HParseState *state) { if (!len) return NULL; if (len->ast->token_type != TT_UINT) - errx(1, "Length parser must return an unsigned integer"); + h_platform_errx(1, "Length parser must return an unsigned integer"); // TODO: allocate this using public functions HRepeat repeat = { .p = lv->value, diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 0000000000000000000000000000000000000000..0c05bfe2e7ada4e7f1c5f48c3d705a839a78730a --- /dev/null +++ b/src/platform.h @@ -0,0 +1,18 @@ +#ifndef HAMMER_PLATFORM__H +#define HAMMER_PLATFORM__H + +/** + * @file interface between hammer and the operating system / + * underlying platform. + */ + +#include "compiler_specifics.h" + +/* Error Reporting */ + +/* BSD errx function, seen in err.h */ +H_MSVC_DECLSPEC(noreturn) \ +void h_platform_errx(int err, const char* format, ...) \ + H_GCC_ATTRIBUTE((noreturn, format (printf,2,3))); + +#endif diff --git a/src/platform_bsdlike.c b/src/platform_bsdlike.c new file mode 100644 index 0000000000000000000000000000000000000000..ebb38d9df55243c75774dbfd9789932ee8d9c650 --- /dev/null +++ b/src/platform_bsdlike.c @@ -0,0 +1,10 @@ +#include "platform.h" + +#include <err.h> +#include <stdarg.h> + +void h_platform_errx(int err, const char* format, ...) { + va_list ap; + va_start(ap, format); + verrx(err, format, ap); +} diff --git a/src/platform_win32.c b/src/platform_win32.c new file mode 100644 index 0000000000000000000000000000000000000000..30af168170933456eb64370bd3cfd632b0558b50 --- /dev/null +++ b/src/platform_win32.c @@ -0,0 +1,10 @@ +#include "platform.h" + +#define WIN32_LEAN_AND_MEAN +#include "windows.h" + +void h_platform_errx(int err, const char* format, ...) { + // FIXME(windows) TODO(uucidl): to be implemented + ExitProcess(err); +} + diff --git a/tools/windows/README.md b/tools/windows/README.md new file mode 100644 index 0000000000000000000000000000000000000000..3b28eea4af4d8c436d747e3117e947c38411453c --- /dev/null +++ b/tools/windows/README.md @@ -0,0 +1 @@ +Support tools for the Windows (win32/win64) port. \ No newline at end of file diff --git a/tools/windows/build.bat b/tools/windows/build.bat new file mode 100644 index 0000000000000000000000000000000000000000..20f878acab296420cb8b29fa36df74aad26eeb44 --- /dev/null +++ b/tools/windows/build.bat @@ -0,0 +1,47 @@ +@echo off +setlocal + +REM This script must be run after vcvarsall.bat has been run, +REM so that cl.exe is in your path. +where cl.exe || goto vsmissing_err + +REM HEREPATH is <drive_letter>:<script_directory> +set HEREPATH=%~d0%~p0 + +REM Set up SRC, BUILD and CLFLAGS +call %HEREPATH%\env.bat +call %HEREPATH%\clvars.bat + +echo SRC=%SRC%, BUILD=%BUILD% +echo Building with flags: %CLFLAGS% + +pushd %SRC% +mkdir %BUILD%\obj +del /Q %BUILD%\obj\ + +cl.exe -nologo -FC -EHsc -Z7 -Oi -GR- -Gm- %CLFLAGS% -c ^ + @%HEREPATH%\hammer_lib_src_list ^ + -Fo%BUILD%\obj\ +if %errorlevel% neq 0 goto err + +lib.exe %BUILD%\obj\*.obj -OUT:%BUILD%\hammer.lib +echo STATIC_LIBRARY %BUILD%\hammer.lib +if %errorlevel% neq 0 goto err +popd + +REM TODO(uucidl): how to build and run the tests? They are written with glib.h +REM which might be a challenge on windows. On the other hand the API of glib.h +REM does not seem too hard to reimplement. + +echo SUCCESS: Successfully built +endlocal +exit /b 0 + +:vsmissing_err +echo ERROR: CL.EXE missing. Have you run vcvarsall.bat? +exit /b 1 + +:err +endlocal +echo ERROR: Failed to build +exit /b %errorlevel% diff --git a/tools/windows/build_examples.bat b/tools/windows/build_examples.bat new file mode 100644 index 0000000000000000000000000000000000000000..c431faebcd29d7b1a1aaeaa77558b948fc3454f0 --- /dev/null +++ b/tools/windows/build_examples.bat @@ -0,0 +1,53 @@ +@echo off +setlocal + +REM This script must be run after vcvarsall.bat has been run, +REM so that cl.exe is in your path. +where cl.exe || goto vsmissing_err + +REM HEREPATH is <drive_letter>:<script_directory> +set HEREPATH=%~d0%~p0 + +REM Set up SRC, BUILD and CLFLAGS +call %HEREPATH%\env.bat +call %HEREPATH%\clvars.bat + +echo SRC=%SRC%, BUILD=%BUILD% +echo CLFLAGS=%CLFLAGS% + +set HAMMERLIB=%BUILD%\hammer.lib + +REM Now let's build some example programs + +cl.exe -nologo %CLFLAGS% examples\base64.c %HAMMERLIB% -Fo%BUILD%\ -Fe%BUILD%\ +if %errorlevel% neq 0 goto err +echo PROGRAM build\base64.exe +cl.exe -nologo %CLFLAGS% examples\base64_sem1.c %HAMMERLIB% -Fo%BUILD%\ -Fe%BUILD%\ +if %errorlevel% neq 0 goto err +echo PROGRAM build\base64_sem1.exe +cl.exe -nologo %CLFLAGS% examples\base64_sem2.c %HAMMERLIB% -Fo%BUILD%\ -Fe%BUILD%\ +if %errorlevel% neq 0 goto err +echo PROGRAM build\base64_sem2.exe + +REM FIXME(windows) TODO(uucidl): dns.c only works on posix +REM cl.exe -nologo %CLFLAGS% examples\dns.c %HAMMERLIB% -Fo%BUILD%\ -Fe%BUILD%\ +REM if %errorlevel% neq 0 goto err +REM echo PROGRAM build\dns.exe + +REM FIXME(windows) TODO(uucidl): grammar.c needs to be fixed +cl.exe -nologo %CLFLAGS% examples\ties.c examples\grammar.c %HAMMERLIB% -Fo%BUILD%\ -Fe%BUILD%\ +if %errorlevel% neq 0 goto err +echo PROGRAM build\ties.exe + +echo SUCCESS: Successfully built +endlocal +exit /b 0 + +:vsmissing_err +echo ERROR: CL.EXE missing. Have you run vcvarsall.bat? +exit /b 1 + +:err +echo ERROR: Failed to build +endlocal +exit /b %errorlevel% diff --git a/tools/windows/clvars.bat b/tools/windows/clvars.bat new file mode 100644 index 0000000000000000000000000000000000000000..8e29226871988207083b61197b5efea11c1ebb69 --- /dev/null +++ b/tools/windows/clvars.bat @@ -0,0 +1,59 @@ +REM Don't call me directly +REM Exports CLFLAGS + +REM Start with the most strict warning level +set WARNINGS=-W4 -Wall -WX + +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 +REM see -Wshadow +set WARNINGS=%WARNINGS% -wd4457 -wd4456 + +REM c4701 (potentially unitialized local variable) +REM FIXME(windows) TODO(uucidl): remove occurence of c4701 if possible +set WARNINGS=%WARNINGS% -wd4701 + +REM We disable implicit casting warnings (c4244), as they occur too often here. +REM Its gcc/clang counterpart is Wconversion which does not seem to +REM be enabled by default. +REM See: [[https://gcc.gnu.org/wiki/NewWconversion#Frequently_Asked_Questions]] +REM +REM Likewise for c4242 (conversion with potential loss of data) and c4267 +REM (conversion away from size_t to a smaller type) and c4245 (conversion +REM from int to size_t signed/unsigned mismatch) +set WARNINGS=%WARNINGS% -wd4242 -wd4244 -wd4245 -wd4267 + +REM c4100 (unreferenced formal parameter) is equivalent to -Wno-unused-parameter +set WARNINGS=%WARNINGS% -wd4100 + +REM c4200 (zero-sized array) is a C idiom supported by C99 +set WARNINGS=%WARNINGS% -wd4200 + +REM c4204 (non-constant aggregate initializers) ressembles C99 support +set WARNINGS=%WARNINGS% -wd4204 + +REM c4201 (anonymous unions) ressembles C11 support. +REM see -std=gnu99 vs -std=c99 +set WARNINGS=%WARNINGS% -wd4201 + +REM c4820 (warnings about padding) and c4324 (intentional padding) are +REM not useful +set WARNINGS=%WARNINGS% -wd4820 -wd4324 + +REM c4710 (inlining could not be performed) is not useful +set WARNINGS=%WARNINGS% -wd4710 + +REM c4255 ( () vs (void) ambiguity) is not useful +set WARNINGS=%WARNINGS% -wd4255 + +REM c4127 (conditional expression is constant) is not useful +set WARNINGS=%WARNINGS% -wd4127 + +REM c4668 (an undefined symbol in a preprocessor directive) is not useful +set WARNINGS=%WARNINGS% -wd4668 + +REM we use sprintf so this should be enabled +set DEFINES=-D_CRT_SECURE_NO_WARNINGS + +set CLFLAGS=-Od -Z7 %DEFINES% %WARNINGS% -Debug diff --git a/tools/windows/env.bat b/tools/windows/env.bat new file mode 100644 index 0000000000000000000000000000000000000000..4037578cccb96202cdd20541cb84932e22a663ab --- /dev/null +++ b/tools/windows/env.bat @@ -0,0 +1,16 @@ +REM Don't call me directly. +REM +REM Expects HEREPATH (this directory) +REM Exports SRC (hammer's src directory) +REM Exports BUILD (hammer's build directory) + +set TOP=%HEREPATH%..\.. + +REM Get canonical path for TOP +pushd . +cd %TOP% +set TOP=%CD% +popd + +set SRC=%TOP%\src +set BUILD=%TOP%\build diff --git a/tools/windows/hammer_lib_src_list b/tools/windows/hammer_lib_src_list new file mode 100644 index 0000000000000000000000000000000000000000..4c85a43ca3ee36f9810d8bf02bbfee1abfd5951c --- /dev/null +++ b/tools/windows/hammer_lib_src_list @@ -0,0 +1,38 @@ +platform_win32.c +allocator.c +bitreader.c +bitwriter.c +cfgrammar.c +desugar.c +glue.c +hammer.c +parsers/action.c +parsers/and.c +parsers/attr_bool.c +parsers/butnot.c +parsers/ch.c +parsers/charset.c +parsers/difference.c +parsers/end.c +parsers/endianness.c +parsers/epsilon.c +parsers/ignore.c +parsers/ignoreseq.c +parsers/indirect.c +parsers/int_range.c +parsers/many.c +parsers/not.c +parsers/optional.c +parsers/permutation.c +parsers/sequence.c +parsers/token.c +parsers/unimplemented.c +parsers/whitespace.c +parsers/xor.c +parsers/value.c +backends/packrat.c +backends/llk.c +backends/glr.c +backends/lalr.c +backends/lr.c +backends/lr0.c diff --git a/tools/windows/status.bat b/tools/windows/status.bat new file mode 100644 index 0000000000000000000000000000000000000000..4f8bd11f9f7567f32cd17f843d2918ac6fd1e14d --- /dev/null +++ b/tools/windows/status.bat @@ -0,0 +1 @@ +git grep "FIXME(windows)"