From b5949f1361684ac6c56d23a07de44aa715151c5a Mon Sep 17 00:00:00 2001 From: Ian Hunter Date: Fri, 29 Mar 2024 12:47:30 +0000 Subject: [PATCH] [WIP] Huge numbers (#472) * Create test_huge_number.py Signed-off-by: Ian Hunter * style: format code with Autopep8, Black, Go fmt, Gofumpt, isort and Yapf This commit fixes the style issues introduced in b91775b according to the output from Autopep8, Black, Go fmt, Gofumpt, isort and Yapf. Details: https://github.com/ianfhunter/GNOLL/pull/472 * Update test_huge_number.py Signed-off-by: Ian Hunter * style: format code with Autopep8, Black, Go fmt, Gofumpt, isort and Yapf This commit fixes the style issues introduced in bf8f6a3 according to the output from Autopep8, Black, Go fmt, Gofumpt, isort and Yapf. Details: https://github.com/ianfhunter/GNOLL/pull/472 * Update test_huge_number.py Signed-off-by: Ian Hunter * Update safe_functions.c Signed-off-by: Ian Hunter * Update safe_functions.h Signed-off-by: Ian Hunter * Update dice.lex Signed-off-by: Ian Hunter * Update vec.h Signed-off-by: Ian Hunter * Update roll_parameters.h Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update vec.h Signed-off-by: Ian Hunter * Update vector_functions.h Signed-off-by: Ian Hunter * Update vector_functions.c Signed-off-by: Ian Hunter * Update string_functions.h Signed-off-by: Ian Hunter * Update vector_functions.h Signed-off-by: Ian Hunter * Update string_functions.c Signed-off-by: Ian Hunter * Update vector_functions.c Signed-off-by: Ian Hunter * Update safe_functions.h Signed-off-by: Ian Hunter * Update safe_functions.c Signed-off-by: Ian Hunter * Update mocking.h Signed-off-by: Ian Hunter * Update mocking.c Signed-off-by: Ian Hunter * Update array_functions.h Signed-off-by: Ian Hunter * Update array_functions.c Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update randomness.h Signed-off-by: Ian Hunter * Update dice_frontend.c Signed-off-by: Ian Hunter * Update dice_core.h Signed-off-by: Ian Hunter * Update dice_core.c Signed-off-by: Ian Hunter * Update vec.h Signed-off-by: Ian Hunter * Update dice_frontend.c Signed-off-by: Ian Hunter * Update vec.h Signed-off-by: Ian Hunter * Update vec.h Signed-off-by: Ian Hunter * Update dice_frontend.c Signed-off-by: Ian Hunter * Update dice_frontend.c Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update dice.lex Signed-off-by: Ian Hunter * Update shared_header.h Signed-off-by: Ian Hunter * Update vector_functions.h Signed-off-by: Ian Hunter * Update vector_functions.c Signed-off-by: Ian Hunter * Update safe_functions.c Signed-off-by: Ian Hunter * Update array_functions.h Signed-off-by: Ian Hunter * Update array_functions.c Signed-off-by: Ian Hunter * Update dice_frontend.h Signed-off-by: Ian Hunter * Update dice_frontend.c Signed-off-by: Ian Hunter * Update roll_parameters.h Signed-off-by: Ian Hunter * Update vector_functions.c Signed-off-by: Ian Hunter * Update vector_functions.c Signed-off-by: Ian Hunter * Update vector_functions.c Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update macros.c Signed-off-by: Ian Hunter * Update conditionals.c Signed-off-by: Ian Hunter * Update conditionals.h Signed-off-by: Ian Hunter * Update vector_functions.c Signed-off-by: Ian Hunter * Update vector_functions.h Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update conditionals.c Signed-off-by: Ian Hunter * Update vector_functions.c Signed-off-by: Ian Hunter * Update conditionals.c Signed-off-by: Ian Hunter * Update conditionals.h Signed-off-by: Ian Hunter * replace pcg-basic with pcg-c * Update Makefile Signed-off-by: Ian Hunter * Update test_OS.yml Signed-off-by: Ian Hunter * Update test_core.yml Signed-off-by: Ian Hunter * Update test_language_bindings.yml Signed-off-by: Ian Hunter * Update test_packages.yml Signed-off-by: Ian Hunter * Update test_OS.yml Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update safe_functions.h Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update safe_functions.c Signed-off-by: Ian Hunter * Update safe_functions.h Signed-off-by: Ian Hunter * Update safe_functions.c Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update Makefile Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update test_language_bindings.yml Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update safe_functions.c Signed-off-by: Ian Hunter * Update safe_functions.h Signed-off-by: Ian Hunter * Update lint_codeQL.yml Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update test_OS.yml Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update test_huge_number.py Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * Update test_troika.py Signed-off-by: Ian Hunter * Update target.mk Signed-off-by: Ian Hunter * remove union to another PR * Update dice.yacc Signed-off-by: Ian Hunter * Update conditionals.c Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update dice_core.c Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update __init__.py Signed-off-by: Ian Hunter * style: format code with Autopep8, Black, Go fmt, Gofumpt, isort and Yapf This commit fixes the style issues introduced in 7365bee according to the output from Autopep8, Black, Go fmt, Gofumpt, isort and Yapf. Details: https://github.com/ianfhunter/GNOLL/pull/472 * Update __init__.py Signed-off-by: Ian Hunter * style: format code with Autopep8, Black, Go fmt, Gofumpt, isort and Yapf This commit fixes the style issues introduced in 346fe6d according to the output from Autopep8, Black, Go fmt, Gofumpt, isort and Yapf. Details: https://github.com/ianfhunter/GNOLL/pull/472 * Update test_huge_number.py Signed-off-by: Ian Hunter * Update test_huge_number.py Signed-off-by: Ian Hunter * Update dice.yacc Signed-off-by: Ian Hunter * Update src/grammar/rolls/dice_core.c Signed-off-by: Ian Hunter * Update src/grammar/rolls/dice_core.c Signed-off-by: Ian Hunter * Update test_huge_number.py Signed-off-by: Ian Hunter * style: format code with Autopep8, Black, Go fmt, Gofumpt, isort and Yapf This commit fixes the style issues introduced in 85e22cf according to the output from Autopep8, Black, Go fmt, Gofumpt, isort and Yapf. Details: https://github.com/ianfhunter/GNOLL/pull/472 * Update test_huge_number.py Signed-off-by: Ian Hunter * Update __init__.py Signed-off-by: Ian Hunter * style: format code with Autopep8, Black, Go fmt, Gofumpt, isort and Yapf This commit fixes the style issues introduced in 598b67c according to the output from Autopep8, Black, Go fmt, Gofumpt, isort and Yapf. Details: https://github.com/ianfhunter/GNOLL/pull/472 * Update randomness.c Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update randomness.h Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update randomness.h Signed-off-by: Ian Hunter * Update randomness.c Signed-off-by: Ian Hunter * Update randomness.h Signed-off-by: Ian Hunter * Update test_huge_number.py Signed-off-by: Ian Hunter --------- Signed-off-by: Ian Hunter Co-authored-by: deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com> Co-authored-by: Ian Hunter --- .github/workflows/lint_codeQL.yml | 2 + .github/workflows/test_OS.yml | 6 + .github/workflows/test_core.yml | 2 + .github/workflows/test_language_bindings.yml | 27 ++ .github/workflows/test_packages.yml | 4 + .gitmodules | 3 + Makefile | 34 ++- src/R/target.mk | 2 +- src/grammar/constructs/roll_parameters.h | 6 +- src/grammar/constructs/vec.h | 6 +- src/grammar/dice.lex | 39 ++- src/grammar/dice.yacc | 262 ++++++++++++++----- src/grammar/external/pcg-c | 1 + src/grammar/external/pcg_basic.c | 105 -------- src/grammar/external/pcg_basic.h | 78 ------ src/grammar/operations/conditionals.c | 46 ++-- src/grammar/operations/conditionals.h | 6 +- src/grammar/rolls/dice_core.c | 42 +-- src/grammar/rolls/dice_core.h | 12 +- src/grammar/rolls/dice_frontend.c | 15 +- src/grammar/rolls/dice_frontend.h | 2 +- src/grammar/rolls/randomness.c | 27 +- src/grammar/rolls/randomness.h | 6 +- src/grammar/shared_header.h | 4 +- src/grammar/util/array_functions.c | 8 +- src/grammar/util/array_functions.h | 4 +- src/grammar/util/mocking.c | 6 +- src/grammar/util/mocking.h | 2 +- src/grammar/util/safe_functions.c | 80 +++++- src/grammar/util/safe_functions.h | 22 +- src/grammar/util/string_functions.c | 10 +- src/grammar/util/string_functions.h | 2 +- src/grammar/util/vector_functions.c | 182 ++++++++----- src/grammar/util/vector_functions.h | 39 +-- src/java/target.mk | 4 +- src/js/target.mk | 3 +- src/perl/target.mk | 2 +- src/python/code/gnoll/__init__.py | 35 ++- src/python/target.mk | 6 +- tests/python/systems/Troika/test_troika.py | 1 + tests/python/test_huge_number.py | 37 +++ 41 files changed, 683 insertions(+), 497 deletions(-) create mode 160000 src/grammar/external/pcg-c delete mode 100644 src/grammar/external/pcg_basic.c delete mode 100644 src/grammar/external/pcg_basic.h create mode 100644 tests/python/test_huge_number.py diff --git a/.github/workflows/lint_codeQL.yml b/.github/workflows/lint_codeQL.yml index 6e9023394..b8fc55f39 100644 --- a/.github/workflows/lint_codeQL.yml +++ b/.github/workflows/lint_codeQL.yml @@ -39,6 +39,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v3 + with: + submodules: true # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/test_OS.yml b/.github/workflows/test_OS.yml index 33a96e974..939dd5af1 100644 --- a/.github/workflows/test_OS.yml +++ b/.github/workflows/test_OS.yml @@ -19,6 +19,8 @@ jobs: with: python-version: '3.x' - uses: actions/checkout@v3 + with: + submodules: true - name: Install dependencies run: | python -m pip install -r reqs/requirements.txt @@ -49,6 +51,8 @@ jobs: python3.10-venv - uses: actions/checkout@v3 + with: + submodules: true - name: test shell: wsl-bash {0} run: | @@ -59,6 +63,8 @@ jobs: runs-on: macos-12 steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Build run: make all - name: Test diff --git a/.github/workflows/test_core.yml b/.github/workflows/test_core.yml index cf2c4292e..9b4d947bf 100644 --- a/.github/workflows/test_core.yml +++ b/.github/workflows/test_core.yml @@ -14,6 +14,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Set up Python uses: actions/setup-python@v3 with: diff --git a/.github/workflows/test_language_bindings.yml b/.github/workflows/test_language_bindings.yml index 239662138..698ce71f6 100644 --- a/.github/workflows/test_language_bindings.yml +++ b/.github/workflows/test_language_bindings.yml @@ -38,6 +38,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: make run: | make cpp @@ -49,6 +51,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: prereqs # https://linuxize.com/post/how-to-install-mono-on-ubuntu-20-04/ run: | @@ -68,6 +72,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + submodules: true - name: go install run: sudo apt install golang-go - name: make go @@ -80,6 +86,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: dep install run: | sudo apt update @@ -98,6 +106,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: java dependencies run: | sudo apt-get update @@ -113,6 +123,8 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Install LLVM and Clang uses: KyleMayes/install-llvm-action@v1 with: @@ -149,6 +161,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: julia install run: | wget https://julialang-s3.julialang.org/bin/linux/x64/1.8/julia-1.8.2-linux-x86_64.tar.gz @@ -158,12 +172,15 @@ jobs: - name: make julia run: | PATH="$PATH:$PWD/julia-1.8.2/bin" make julia + test_lua: name: "Test: Lua" runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 + with: + submodules: true - name: lua install run: | sudo apt install luajit @@ -176,6 +193,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: perl install run: | sudo apt install perl @@ -190,6 +209,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - uses: r-lib/actions/setup-r@v2 - name: make r run: make r @@ -199,6 +220,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + submodules: true - name: ruby install run: | sudo apt install ruby-full @@ -210,6 +233,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -226,6 +251,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Setup Rust run: | curl https://sh.rustup.rs -sSf | sh -s -- -y diff --git a/.github/workflows/test_packages.yml b/.github/workflows/test_packages.yml index a4bf6b68d..144fc5c36 100644 --- a/.github/workflows/test_packages.yml +++ b/.github/workflows/test_packages.yml @@ -12,6 +12,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Set up Python uses: actions/setup-python@v3 with: @@ -50,6 +52,8 @@ jobs: runs-on: macos-12 steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Build run: make all - name: Test diff --git a/.gitmodules b/.gitmodules index e69de29bb..9be9af09d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/grammar/external/pcg-c"] + path = src/grammar/external/pcg-c + url = https://github.com/imneme/pcg-c.git diff --git a/Makefile b/Makefile index 3ddbc9314..4cd86227b 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,16 @@ CODEDIRS=./src/grammar ./src/grammar/rolls ./src/grammar/util ./src/grammar/operations ./src/grammar/external -INCDIRS=./src/grammar +INCDIRS=./src/grammar ./src/grammar/external/pcg-c/include -CC=cc +PCG_SRC=./src/grammar/external/pcg-c/src + +$(info CC is $(CC)) ifeq ($(CC),g++) STANDARD= -std=c++11 else ifeq ($(CC),clang++) STANDARD= -std=c++11 +else ifeq ($(filter $(CC),gcc cc),gcc cc) + STANDARD= -std=c99 else STANDARD= -std=c99 endif @@ -25,8 +29,8 @@ ifneq ($(shell uname -s), Darwin) OPT := $(OPT) -Wl,-z,nodlopen -Wl,-z,noexecstack \ -Wl,-z,relro endif - -# -ffast-math # Problematic for Python + +# -ffast-math # Problematic for Python # YACC/LEX fails for the following, so disabled: # -Wswitch-default -Wstrict-overflow=5 @@ -91,16 +95,16 @@ ifeq ($(LEX_FALLBACK), 1) LEXER:=lex else #$(shell echo USING FLEX) -LEXER:=flex -f -Ca -Ce -Cr +LEXER:=flex -f -Ca -Ce -Cr endif # add flags and the include paths DEFS=-DUSE_SECURE_RANDOM=${USE_SECURE_RANDOM} -DJUST_YACC=${YACC_FALLBACK} -DUSE_CLT=${USE_CLT} -CFLAGS=$(foreach D,$(INCDIRS),-I$(D)) $(OPT) $(DEFS) +CFLAGS=$(foreach D,$(INCDIRS),-I$(D)) $(OPT) $(DEFS) # add flags to build for shared library and add include paths -SHAREDCFLAGS=-fPIC -c $(foreach D,$(INCDIRS),-I$(D)) $(ARC4RANDOM) $(DEFS) +SHAREDCFLAGS=-fPIC -c $(foreach D,$(INCDIRS),-I$(D)) $(ARC4RANDOM) $(DEFS) # generate list of c files and remove y.tab.c from src/grammar directory CFILES=$(foreach D,$(CODEDIRS),$(wildcard $(D)/*.c)) build/lex.yy.c build/y.tab.c @@ -127,7 +131,7 @@ install: all yacc: mkdir -p build $(foreach BD,$(CFILE_SUBDIRS),mkdir -p build/$(BD)) - $(PARSER) -d src/grammar/dice.yacc $(PARSER_DEBUG) + $(PARSER) -d src/grammar/dice.yacc $(PARSER_DEBUG) mv y.tab.c build/y.tab.c mv y.tab.h build/y.tab.h mv y.output build/y.output | true # Only present with verbose @@ -136,18 +140,22 @@ lex: mv lex.yy.c build/lex.yy.c # Executable -compile: +compile: pcg # FLEX creates warning when run with -f # MacOS creates warnings for signs. $(CC) $(CFLAGS) $(CFILES) $(ARC4RANDOM) \ -Wno-error=implicit-function-declaration \ -Wno-sign-conversion -Wno-sign-compare -lm \ - -Wno-implicit-int-conversion + -Wno-implicit-int-conversion -lpcg_random -L$(PCG_SRC) \ + -Wno-undef -Wno-conversion # For pcg-c +# PCG Submodule +pcg: + make -C src/grammar/external/pcg-c all # Shared Lib shared: $(OBJECTS) - $(CC) -shared -o build/dice.so $^ $(ARC4RANDOM) -lm + $(CC) -shared -o build/dice.so $^ $(ARC4RANDOM) -lm -lpcg_random -L$(PCG_SRC) cp build/dice.so build/libdice.so # Linux mv ./a.out build/dice | true @@ -155,10 +163,10 @@ shared: $(OBJECTS) mv ./a.exe build/dice | true # hardcode for lex and yacc files -build/y.tab.o: +build/y.tab.o: $(CC) $(SHAREDCFLAGS) -c build/y.tab.c -o $@ build/lex.yy.o: - $(CC) $(SHAREDCFLAGS) -c build/lex.yy.c -o $@ + $(CC) $(SHAREDCFLAGS) -c build/lex.yy.c -o $@ # Wildcard everything else build/*/%.o:src/grammar/*/%.c diff --git a/src/R/target.mk b/src/R/target.mk index 180940d91..8cdc53c27 100644 --- a/src/R/target.mk +++ b/src/R/target.mk @@ -2,5 +2,5 @@ r: clean yacc lex compile $(OBJECTS) mkdir -p build/r/ - $(CC) -shared -o build/r/dice.so $(OBJECTS) $(ARC4RANDOM) -lR + $(CC) -shared -o build/r/dice.so $(OBJECTS) $(ARC4RANDOM) -lR -lpcg_random -L$(PCG_SRC) Rscript src/R/main.r diff --git a/src/grammar/constructs/roll_parameters.h b/src/grammar/constructs/roll_parameters.h index cac7e04c1..2d3983dff 100644 --- a/src/grammar/constructs/roll_parameters.h +++ b/src/grammar/constructs/roll_parameters.h @@ -4,11 +4,11 @@ #include "constructs/dice_enums.h" typedef struct roll_params { - unsigned int number_of_dice; - unsigned int die_sides; + unsigned long long number_of_dice; + unsigned long long die_sides; EXPLOSION_TYPE explode; char** symbol_pool; - int start_value; + long long start_value; DIE_TYPE dtype; } roll_params; diff --git a/src/grammar/constructs/vec.h b/src/grammar/constructs/vec.h index 4cb3899f2..7478b5e79 100644 --- a/src/grammar/constructs/vec.h +++ b/src/grammar/constructs/vec.h @@ -7,11 +7,13 @@ typedef struct vec { DIE_TYPE dtype; + union { // Vectors can only contain one dice type - int* content; + long long* content; char** symbols; } storage; - unsigned int length; + unsigned long long length; + roll_params source; bool has_source; } vec; diff --git a/src/grammar/dice.lex b/src/grammar/dice.lex index 393f443b7..f77aa7330 100644 --- a/src/grammar/dice.lex +++ b/src/grammar/dice.lex @@ -20,7 +20,6 @@ [ \n]+ /* Eat Whitespace */; - /* TODO */ [A-Z_]+ { vec vector; vector.storage.symbols = (char**)safe_malloc(sizeof(char **)); @@ -39,7 +38,9 @@ [0-9]+ { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = fast_atoi(yytext); @@ -210,7 +211,9 @@ c { } u { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = IS_UNIQUE; vector.dtype = NUMERIC; @@ -237,7 +240,8 @@ o { /* Comparitors */ \!\= { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = NOT_EQUAL; vector.dtype = NUMERIC; @@ -248,7 +252,9 @@ o { } \=\= { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = EQUALS; vector.dtype = NUMERIC; @@ -259,7 +265,9 @@ o { } \< { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = LESS_THAN; vector.dtype = NUMERIC; @@ -270,7 +278,9 @@ o { } \> { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = GREATER_THAN; vector.dtype = NUMERIC; @@ -281,7 +291,9 @@ o { } \<\= { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = LESS_OR_EQUALS; vector.dtype = NUMERIC; @@ -292,7 +304,9 @@ o { } \>\= { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = GREATER_OR_EQUALS; vector.dtype = NUMERIC; @@ -303,7 +317,9 @@ o { } is_even { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = IF_EVEN; vector.dtype = NUMERIC; @@ -314,7 +330,8 @@ is_even { } is_odd { vec vector; - vector.storage.content = (int*)safe_malloc(sizeof(int)); + vector.storage.content = (long long*)safe_malloc(sizeof(long long)); + if(gnoll_errno){yyerror("Memory Err");} vector.storage.content[0] = IF_ODD; vector.dtype = NUMERIC; diff --git a/src/grammar/dice.yacc b/src/grammar/dice.yacc index 401f5b965..ff9d3c452 100644 --- a/src/grammar/dice.yacc +++ b/src/grammar/dice.yacc @@ -11,7 +11,7 @@ #include #include #include "shared_header.h" -#include "external/pcg_basic.h" +#include "external/pcg-c/include/pcg_variants.h" // TODO: Move this to randomness.c #include "external/tinydir.h" #include "operations/macros.h" #include "operations/conditionals.h" @@ -35,6 +35,7 @@ #ifdef __EMSCRIPTEN__ #define VERBOSITY 1 #else +// UNDO #define VERBOSITY 0 #endif @@ -56,16 +57,17 @@ char * output_file; extern int gnoll_errno; extern struct macro_struct *macros; -pcg32_random_t rng; +pcg64_random_t rng; // Function Signatures for this file int initialize(void); +int countDigits(long long num); // Functions int initialize(void){ if (!seeded){ unsigned long int tick = (unsigned long)time(0)+(unsigned long)clock(); - pcg32_srandom_r( + pcg64_srandom_r( &rng, tick ^ (unsigned long int)&printf, 54u @@ -75,6 +77,24 @@ int initialize(void){ return 0; } +int countDigits(long long num) { + // count units in a number + int count = 0; + + // Handle negative numbers + if (num < 0) { + num = -num; + } + + // Count digits + do { + count++; + num /= 10; + } while (num > 0); + + return count; +} + %} @@ -204,7 +224,7 @@ dice_statement: math{ #ifdef __EMSCRIPTEN__ printf("Result:"); #endif - for(unsigned int i = 0; i!= new_vec.length;i++){ + for(unsigned long long i = 0; i!= new_vec.length;i++){ if (new_vec.dtype == SYMBOLIC){ // TODO: Strings >1 character if (verbose || VERBOSITY ){ @@ -215,10 +235,12 @@ dice_statement: math{ } }else{ if(verbose || VERBOSITY ){ - printf("%d;", new_vec.storage.content[i]); + + printf("%lld;", new_vec.storage.content[i]); } if(write_to_file){ - fprintf(fp, "%d;", new_vec.storage.content[i]); + fprintf(fp, "%lld;", new_vec.storage.content[i]); + } } } @@ -253,9 +275,12 @@ math: */ vec new_vec; initialize_vector(&new_vec, NUMERIC, 1); - int vmax = MAXV( + + long long vmax = MAXV( + $3.storage.content[0], $5.storage.content[0] + ); new_vec.storage.content[0] = vmax; $$ = new_vec; @@ -320,13 +345,21 @@ math: YYABORT; yyclearin; }else{ - int v1 = collapse(vector1.storage.content, vector1.length); - int v2 = collapse(vector2.storage.content, vector2.length); + + long long v1 = collapse(vector1.storage.content, vector1.length); + long long v2 = collapse(vector2.storage.content, vector2.length); vec new_vec; - new_vec.storage.content = safe_calloc(sizeof(int), 1); + new_vec.storage.content = (long long*)safe_calloc(sizeof(long long), 1); new_vec.length = 1; + if (v1 != 0 && v2 > INT_MAX / v1){ + gnoll_errno = MATH_OVERFLOW; + } + if (v1 != 0 && v2 < INT_MIN / v1){ + gnoll_errno = MATH_UNDERFLOW; + } new_vec.storage.content[0] = v1 * v2; + new_vec.dtype = vector1.dtype; $$ = new_vec; @@ -353,11 +386,13 @@ math: yyclearin; }else{ - int v1 = collapse(vector1.storage.content, vector1.length); - int v2 = collapse(vector2.storage.content, vector2.length); + + long long v1 = collapse(vector1.storage.content, vector1.length); + long long v2 = collapse(vector2.storage.content, vector2.length); vec new_vec; - new_vec.storage.content = safe_calloc(sizeof(int), 1); + new_vec.storage.content = (long long*)safe_calloc(sizeof(long long), 1); + if(gnoll_errno){ YYABORT; yyclearin;} new_vec.length = 1; if(v2==0){ @@ -391,11 +426,13 @@ math: YYABORT; yyclearin; }else{ - int v1 = collapse(vector1.storage.content, vector1.length); - int v2 = collapse(vector2.storage.content, vector2.length); + + long long v1 = collapse(vector1.storage.content, vector1.length); + long long v2 = collapse(vector2.storage.content, vector2.length); vec new_vec; - new_vec.storage.content = safe_calloc(sizeof(int), 1); + new_vec.storage.content = (long long*)safe_calloc(sizeof(long long), 1); + if(gnoll_errno){ YYABORT; yyclearin; @@ -433,11 +470,13 @@ math: yyclearin; }else{ - int v1 = collapse(vector1.storage.content, vector1.length); - int v2 = collapse(vector2.storage.content, vector2.length); + + long long v1 = collapse(vector1.storage.content, vector1.length); + long long v2 = collapse(vector2.storage.content, vector2.length); vec new_vec; - new_vec.storage.content = safe_calloc(sizeof(int), 1); + new_vec.storage.content = (long long*)safe_calloc(sizeof(long long), 1); + if(gnoll_errno){ YYABORT; yyclearin; @@ -473,14 +512,18 @@ math: yyclearin; } else if (vector1.dtype == SYMBOLIC){ vec new_vec; - unsigned int concat_length = vector1.length + vector2.length; + + unsigned long long concat_length = vector1.length + vector2.length; new_vec.storage.symbols = safe_calloc(sizeof(char *), concat_length); + if(gnoll_errno){ YYABORT; yyclearin; } - for (unsigned int i = 0; i != concat_length; i++){ + + for (unsigned long long i = 0; i != concat_length; i++){ new_vec.storage.symbols[i] = safe_calloc(sizeof(char), MAX_SYMBOL_LENGTH); + if(gnoll_errno){ YYABORT; yyclearin; @@ -496,11 +539,13 @@ math: ); $$ = new_vec; }else{ - int v1 = collapse(vector1.storage.content, vector1.length); - int v2 = collapse(vector2.storage.content, vector2.length); + + long long v1 = collapse(vector1.storage.content, vector1.length); + long long v2 = collapse(vector2.storage.content, vector2.length); vec new_vec; - new_vec.storage.content = safe_calloc(sizeof(int), 1); + new_vec.storage.content = (long long*)safe_calloc(sizeof(long long), 1); + if(gnoll_errno){ YYABORT; yyclearin; @@ -536,11 +581,14 @@ math: }else{ // Collapse both sides and subtract - int v1 = collapse(vector1.storage.content, vector1.length); - int v2 = collapse(vector2.storage.content, vector2.length); + + long long v1 = collapse(vector1.storage.content, vector1.length); + long long v2 = collapse(vector2.storage.content, vector2.length); vec new_vec; - new_vec.storage.content = safe_calloc(sizeof(int), 1); + new_vec.storage.content = (long long*)safe_calloc(sizeof(long long), 1); + + if(gnoll_errno){ YYABORT; yyclearin; @@ -572,7 +620,9 @@ math: } else { vec new_vec; - new_vec.storage.content = safe_calloc(sizeof(int), vector.length); + + new_vec.storage.content = (long long*)safe_calloc(sizeof(long long), vector.length); + if(gnoll_errno){ YYABORT; yyclearin; @@ -580,8 +630,12 @@ math: new_vec.length = vector.length; new_vec.dtype = vector.dtype; - for(unsigned int i = 0; i != vector.length; i++){ + + for(unsigned long long i = 0; i != vector.length; i++){ new_vec.storage.content[i] = - vector.storage.content[i]; + + + } $$ = new_vec; @@ -603,7 +657,9 @@ collapsing_dice_operations: vec dice = $1; initialize_vector(&new_vec, NUMERIC, 1); - new_vec.storage.content[0] = (int)dice.length; + + new_vec.storage.content[0] = (long long)dice.length; + free_vector(dice); $$ = new_vec; } @@ -651,7 +707,9 @@ dice_operations: vec cv = $4; vec cvno = $5; - int check = cv.storage.content[0]; + + int check = (int)cv.storage.content[0]; + if(dice.dtype == NUMERIC){ int count = 0; @@ -665,11 +723,13 @@ dice_operations: } vec number_of_dice; initialize_vector(&number_of_dice, NUMERIC, 1); - number_of_dice.storage.content[0] = (int)dice.source.number_of_dice; + + number_of_dice.storage.content[0] = (long long)dice.source.number_of_dice; vec die_sides; initialize_vector(&die_sides, NUMERIC, 1); - die_sides.storage.content[0] = (int)dice.source.die_sides; + die_sides.storage.content[0] = (long long)dice.source.die_sides; + roll_plain_sided_dice( &number_of_dice, @@ -704,7 +764,9 @@ dice_operations: vec dice = $1; vec comp = $3; - int check = comp.storage.content[0]; + + int check = (int)comp.storage.content[0]; + vec numv = $4; if(dice.dtype == NUMERIC){ @@ -712,11 +774,13 @@ dice_operations: vec number_of_dice; initialize_vector(&number_of_dice, NUMERIC, 1); - number_of_dice.storage.content[0] = (int)dice.source.number_of_dice; + + number_of_dice.storage.content[0] = (long long)dice.source.number_of_dice; vec die_sides; initialize_vector(&die_sides, NUMERIC, 1); - die_sides.storage.content[0] = (int)dice.source.die_sides; + die_sides.storage.content[0] = (long long)dice.source.die_sides; + roll_plain_sided_dice( &number_of_dice, @@ -753,7 +817,9 @@ dice_operations: vec condition = $4; vec cv = $3; - int check = cv.storage.content[0]; + + int check = (int)cv.storage.content[0]; + if(dice.dtype == NUMERIC){ initialize_vector(&new_vec, NUMERIC, dice.length); @@ -778,7 +844,10 @@ dice_operations: * singular_condition symbol */ vec dice = $1; - int check = $3.storage.content[0]; + + int check = (int)$3.storage.content[0]; + + vec new_vec; if(dice.dtype == NUMERIC){ @@ -793,7 +862,6 @@ dice_operations: yyclearin;; } free_vector(dice); - } | dice_operations UNIQUE{ @@ -826,8 +894,11 @@ dice_operations: */ vec roll_vec = $1; vec keep_vector = $3; + vec **new_vec; - unsigned int num_to_hold = (unsigned int)keep_vector.storage.content[0]; + + unsigned long long num_to_hold = (unsigned long long)keep_vector.storage.content[0]; + initialize_vector_pointer(&new_vec, roll_vec.dtype, num_to_hold); @@ -847,7 +918,9 @@ dice_operations: vec roll_vec = $1; vec keep_vector = $3; - unsigned int num_to_hold = (unsigned int)keep_vector.storage.content[0]; + + unsigned long long num_to_hold = (unsigned long long)keep_vector.storage.content[0]; + vec **new_vec; initialize_vector_pointer(&new_vec, roll_vec.dtype, roll_vec.length - num_to_hold); @@ -869,8 +942,11 @@ dice_operations: vec roll_vec = $1; vec keep_vector = $3; + vec **new_vec; - unsigned int num_to_hold = (unsigned int)keep_vector.storage.content[0]; + + unsigned long long num_to_hold = (unsigned long long)keep_vector.storage.content[0]; + initialize_vector_pointer(&new_vec, roll_vec.dtype, num_to_hold); keep_lowest_values(&roll_vec, new_vec, num_to_hold); @@ -889,8 +965,10 @@ dice_operations: vec roll_vec = $1; vec keep_vector = $3; + unsigned long long num_to_hold = (unsigned long long)keep_vector.storage.content[0]; + vec **new_vec; - unsigned int num_to_hold = (unsigned int)keep_vector.storage.content[0]; + initialize_vector_pointer(&new_vec, roll_vec.dtype, roll_vec.length - num_to_hold); drop_lowest_values(&roll_vec, new_vec, num_to_hold); @@ -905,8 +983,9 @@ dice_operations: * dice_operations vector * KEEP_HIGHEST symbol 'kh' */ + vec roll_vec = $1; - unsigned int num_to_hold = 1; + unsigned long long num_to_hold = 1; vec **new_vec; initialize_vector_pointer(&new_vec, roll_vec.dtype, num_to_hold); @@ -922,7 +1001,8 @@ dice_operations: * DROP_HIGHEST symbol 'dh' */ vec roll_vec = $1; - unsigned int num_to_hold = 1; + + unsigned long long num_to_hold = 1; vec **new_vec; initialize_vector_pointer(&new_vec, roll_vec.dtype, roll_vec.length - num_to_hold); drop_highest_values(&roll_vec, new_vec, num_to_hold); @@ -937,10 +1017,13 @@ dice_operations: * KEEP_LOWEST symbol 'kl' */ vec roll_vec = $1; - unsigned int num_to_hold = 1; + + unsigned long long num_to_hold = 1; + vec **new_vec; initialize_vector_pointer(&new_vec, roll_vec.dtype, num_to_hold); + keep_lowest_values(&roll_vec, new_vec, num_to_hold); $$ = **new_vec; @@ -953,10 +1036,13 @@ dice_operations: * DROP_LOWEST symbol 'dl' */ vec roll_vec = $1; - unsigned int num_to_hold = 1; + + unsigned long long num_to_hold = 1; + vec **new_vec; initialize_vector_pointer(&new_vec, roll_vec.dtype, roll_vec.length - num_to_hold); + drop_lowest_values(&roll_vec, new_vec, num_to_hold); $$ = **new_vec; @@ -979,7 +1065,9 @@ die_roll: vec ds = $2; vec numB = $3; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + vec number_of_dice; initialize_vector(&number_of_dice, NUMERIC, 1); @@ -1008,7 +1096,9 @@ die_roll: vec ds = $1; vec numB = $2; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + vec number_of_dice; initialize_vector(&number_of_dice, NUMERIC, 1); @@ -1037,7 +1127,9 @@ die_roll: vec numA = $1; vec ds = $2; vec numB = $3; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + roll_plain_sided_dice( &numA, @@ -1062,7 +1154,9 @@ die_roll: vec ds = $1; vec numB = $2; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + vec number_of_dice; initialize_vector(&number_of_dice, NUMERIC, 1); @@ -1091,7 +1185,9 @@ die_roll: vec numA = $1; vec ds = $2; vec numB = $3; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + roll_plain_sided_dice( &numA, @@ -1114,7 +1210,9 @@ die_roll: vec ds = $1; vec numB = $2; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + vec number_of_dice; initialize_vector(&number_of_dice, NUMERIC, 1); @@ -1141,7 +1239,9 @@ die_roll: vec numA = $1; vec ds = $2; vec numB = $3; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + roll_plain_sided_dice( &numA, @@ -1164,7 +1264,9 @@ die_roll: vec numB = $2; vec new_vec; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + vec number_of_dice; initialize_vector(&number_of_dice, NUMERIC, 1); @@ -1240,7 +1342,9 @@ die_roll: */ vec num = $1; vec die_sym = $2; - int start_from = die_sym.storage.content[0]; + + long long start_from = die_sym.storage.content[0]; + vec dice_sides; initialize_vector(&dice_sides, NUMERIC, 1); @@ -1263,7 +1367,9 @@ die_roll: * DO_COUNT symbol 'c' */ vec ds= $1; - int start_from = ds.storage.content[0]; + + long long start_from = ds.storage.content[0]; + vec num_dice; initialize_vector(&num_dice, NUMERIC, 1); @@ -1387,10 +1493,13 @@ custom_symbol_dice: initialize_vector(&result_vec, NUMERIC, 1); num_dice.storage.content[0] = 1; - int start_value = csd_vec.storage.content[0]; - int end_value = csd_vec.storage.content[csd_vec.length-1]; + + long long start_value = csd_vec.storage.content[0]; + long long end_value = csd_vec.storage.content[csd_vec.length-1]; + dice_sides.storage.content[0] = end_value - start_value + 1; + // Range roll_plain_sided_dice( &num_dice, @@ -1413,7 +1522,7 @@ custom_symbol_dice: }; result_vec.source = rp; result_vec.has_source = true; - for(unsigned int i = 0; i != csd_vec.length; i++){ + for(unsigned long long i = 0; i != csd_vec.length; i++){ result_vec.source.symbol_pool[i] = (char*)safe_calloc(sizeof(char),MAX_SYMBOL_LENGTH); memcpy( result_vec.source.symbol_pool[i], @@ -1456,7 +1565,9 @@ custom_symbol_dice: // Set Num Dice initialize_vector(&number_of_dice, NUMERIC, 1); - number_of_dice.storage.content[0] = (int)new_vector.source.number_of_dice; + + number_of_dice.storage.content[0] = (long long)new_vector.source.number_of_dice; + // Set Die Sides // die_sides.storage.content[0] = (int)new_vector.source.die_sides; @@ -1542,12 +1653,14 @@ csd: vec start = $1; vec end = $3; - int s = start.storage.content[0]; - int e = end.storage.content[0]; + + long long s = start.storage.content[0]; + long long e = end.storage.content[0]; + if (s > e){ - printf("Range: %i -> %i\n", s, e); + printf("Range: %lld -> %lld\n", s, e); printf("Reversed Ranged not supported yet.\n"); gnoll_errno = NOT_IMPLEMENTED; YYABORT; @@ -1558,12 +1671,14 @@ csd: // 2..2 = 1 // 2..3 = 2 // etc. - unsigned int spread = (unsigned int)e - (unsigned int)s + 1; + unsigned long long spread = (unsigned long long)e - (unsigned long long)s + 1; vec new_vector; initialize_vector(&new_vector, SYMBOLIC, spread); - for (int i = 0; i <= (e-s); i++){ - sprintf(new_vector.storage.symbols[i], "%d", s+i); + + for (unsigned long long i = 0; i <= spread-1; i++){ + sprintf(new_vector.storage.symbols[i], "%lld", s+i); + } $$ = new_vector; } @@ -1576,12 +1691,14 @@ csd: * return A vector containing the numeric values as symbols */ vec in = $1; - int tmp = in.storage.content[0]; + + long long tmp = in.storage.content[0]; free(in.storage.content); in.storage.symbols = safe_calloc(1, sizeof(char *)); // an int has 10 characters max - in.storage.symbols[0] = safe_calloc(10, sizeof(char)); - sprintf(in.storage.symbols[0], "%d", tmp); + in.storage.symbols[0] = safe_calloc(countDigits(LLONG_MAX), sizeof(char)); + sprintf(in.storage.symbols[0], "%lld", tmp); + in.dtype = SYMBOLIC; $$ = in; } @@ -1634,7 +1751,7 @@ int roll_full_options( int enable_mocking, int enable_builtins, int mocking_type, - int mocking_seed + long long mocking_seed ){ /** * @brief the main GNOLL roll function @@ -1655,6 +1772,7 @@ int roll_full_options( printf("Trying to roll '%s'\n", roll_request); } if (enable_mocking){ + if (enable_verbosity){ printf("mocking_seed '%lld'\n", mocking_seed); } init_mocking((MOCK_METHOD)mocking_type, mocking_seed); } if (log_file != NULL){ @@ -1775,7 +1893,7 @@ void roll_and_write_R(int* return_code, char** s, char** f){ (*return_code) = roll_full_options(s[0], f[0], 0, 0, 0, 0, 0, 0); } -int mock_roll(char * s, char * f, int mock_value, int mock_const){ +int mock_roll(char * s, char * f, int mock_value, long long mock_const){ return roll_full_options(s, f, 0, 0, 1, 0, mock_value, mock_const); } diff --git a/src/grammar/external/pcg-c b/src/grammar/external/pcg-c new file mode 160000 index 000000000..83252d9c2 --- /dev/null +++ b/src/grammar/external/pcg-c @@ -0,0 +1 @@ +Subproject commit 83252d9c23df9c82ecb42210afed61a7b42402d7 diff --git a/src/grammar/external/pcg_basic.c b/src/grammar/external/pcg_basic.c deleted file mode 100644 index 716ae8897..000000000 --- a/src/grammar/external/pcg_basic.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * PCG Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * For additional information about the PCG random number generation scheme, - * including its license and other licensing options, visit - * - * http://www.pcg-random.org - */ - -/* - * This code is derived from the full C implementation, which is in turn - * derived from the canonical C++ PCG implementation. The C++ version - * has many additional features and is preferable if you can use C++ in - * your project. - */ - -#include "external/pcg_basic.h" - -// state for global RNGs - -static pcg32_random_t pcg32_global = PCG32_INITIALIZER; - -// pcg32_srandom(initstate, initseq) -// pcg32_srandom_r(rng, initstate, initseq): -// Seed the rng. Specified in two parts, state initializer and a -// sequence selection constant (a.k.a. stream id) - -void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, - uint64_t initseq) { - rng->state = 0U; - rng->inc = (initseq << 1u) | 1u; - pcg32_random_r(rng); - rng->state += initstate; - pcg32_random_r(rng); -} - -void pcg32_srandom(uint64_t seed, uint64_t seq) { - pcg32_srandom_r(&pcg32_global, seed, seq); -} - -// pcg32_random() -// pcg32_random_r(rng) -// Generate a uniformly distributed 32-bit random number - -uint32_t pcg32_random_r(pcg32_random_t* rng) { - uint64_t oldstate = rng->state; - rng->state = oldstate * 6364136223846793005ULL + rng->inc; - uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u); - uint32_t rot = (uint32_t)(oldstate >> 59u); - return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); -} - -uint32_t pcg32_random(void) { return pcg32_random_r(&pcg32_global); } - -// pcg32_boundedrand(bound): -// pcg32_boundedrand_r(rng, bound): -// Generate a uniformly distributed number, r, where 0 <= r < bound - -uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound) { - // To avoid bias, we need to make the range of the RNG a multiple of - // bound, which we do by dropping output less than a threshold. - // A naive scheme to calculate the threshold would be to do - // - // uint32_t threshold = 0x100000000ull % bound; - // - // but 64-bit div/mod is slower than 32-bit div/mod (especially on - // 32-bit platforms). In essence, we do - // - // uint32_t threshold = (0x100000000ull-bound) % bound; - // - // because this version will calculate the same modulus, but the LHS - // value is less than 2^32. - - uint32_t threshold = -bound % bound; - - // Uniformity guarantees that this loop will terminate. In practice, it - // should usually terminate quickly; on average (assuming all bounds are - // equally likely), 82.25% of the time, we can expect it to require just - // one iteration. In the worst case, someone passes a bound of 2^31 + 1 - // (i.e., 2147483649), which invalidates almost 50% of the range. In - // practice, bounds are typically small and only a tiny amount of the range - // is eliminated. - for (;;) { - uint32_t r = pcg32_random_r(rng); - if (r >= threshold) return r % bound; - } -} - -uint32_t pcg32_boundedrand(uint32_t bound) { - return pcg32_boundedrand_r(&pcg32_global, bound); -} diff --git a/src/grammar/external/pcg_basic.h b/src/grammar/external/pcg_basic.h deleted file mode 100644 index 639db9a7b..000000000 --- a/src/grammar/external/pcg_basic.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * PCG Random Number Generation for C. - * - * Copyright 2014 Melissa O'Neill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * For additional information about the PCG random number generation scheme, - * including its license and other licensing options, visit - * - * http://www.pcg-random.org - */ - -/* - * This code is derived from the full C implementation, which is in turn - * derived from the canonical C++ PCG implementation. The C++ version - * has many additional features and is preferable if you can use C++ in - * your project. - */ - -#ifndef PCG_BASIC_H_INCLUDED -#define PCG_BASIC_H_INCLUDED 1 - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct pcg_state_setseq_64 { // Internals are *Private*. - uint64_t state; // RNG state. All values are possible. - uint64_t inc; // Controls which RNG sequence (stream) is - // selected. Must *always* be odd. -}; -typedef struct pcg_state_setseq_64 pcg32_random_t; - -// If you *must* statically initialize it, here's one. - -#define PCG32_INITIALIZER \ - { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL } - -// pcg32_srandom(initstate, initseq) -// pcg32_srandom_r(rng, initstate, initseq): -// Seed the rng. Specified in two parts, state initializer and a -// sequence selection constant (a.k.a. stream id) - -void pcg32_srandom(uint64_t initstate, uint64_t initseq); -void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq); - -// pcg32_random() -// pcg32_random_r(rng) -// Generate a uniformly distributed 32-bit random number - -uint32_t pcg32_random(void); -uint32_t pcg32_random_r(pcg32_random_t* rng); - -// pcg32_boundedrand(bound): -// pcg32_boundedrand_r(rng, bound): -// Generate a uniformly distributed number, r, where 0 <= r < bound - -uint32_t pcg32_boundedrand(uint32_t bound); -uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound); - -#ifdef __cplusplus -} -#endif - -#endif // PCG_BASIC_H_INCLUDED diff --git a/src/grammar/operations/conditionals.c b/src/grammar/operations/conditionals.c index 033868ac7..6e2737143 100644 --- a/src/grammar/operations/conditionals.c +++ b/src/grammar/operations/conditionals.c @@ -21,45 +21,49 @@ extern int gnoll_errno; * @return true - the condition is True * @return false - the condition is False */ -int check_condition(vec* x, vec* y, COMPARATOR c) { - if (gnoll_errno) return 1; +bool check_condition(vec* x, vec* y, COMPARATOR c) { + if (gnoll_errno) return true; if(c == IS_UNIQUE || c == IF_ODD || c == IF_EVEN){ return check_condition_vector(x, c); }else{ - int xvalue = collapse(x->storage.content, x->length); - int yvalue = y->storage.content[0]; + + long long xvalue = collapse(x->storage.content, x->length); + long long yvalue = y->storage.content[0]; + return check_condition_scalar(xvalue, yvalue, c); } } -int check_condition_vector(vec* v, COMPARATOR c) { +bool check_condition_vector(vec* v, COMPARATOR c) { switch (c){ case IS_UNIQUE: { gnoll_errno = NOT_IMPLEMENTED; - return 1; + return true; } case IF_EVEN:{ - int x = collapse(v->storage.content, v->length); - return (x+1) % 2; + + long long x = collapse(v->storage.content, v->length); + return (x+1) % 2 != 0; } case IF_ODD: { - int x = collapse(v->storage.content, v->length); - return x % 2; + long long x = collapse(v->storage.content, v->length); + return x % 2 != 0; + } default: { gnoll_errno = NOT_IMPLEMENTED; - return 0; + return false; } } } -int check_condition_scalar(int x, int y, COMPARATOR c) { - if (gnoll_errno) return 1; +bool check_condition_scalar(long long x, long long y, COMPARATOR c) { + if (gnoll_errno) return true; - int xvalue = x; - int yvalue = y; + long long xvalue = x; + long long yvalue = y; switch (c) { case EQUALS: { return xvalue == yvalue; @@ -81,26 +85,26 @@ int check_condition_scalar(int x, int y, COMPARATOR c) { } case IS_UNIQUE: { // Unique by the fact that it is scalar - return 1; + return true; } case IF_ODD: { - return x % 2; + return x % 2 != 0; } case IF_EVEN: { - return (x+1) % 2; + return (x+1) % 2 != 0; } case INVALID: { printf("Invalid Conditional\n"); gnoll_errno = UNDEFINED_BEHAVIOUR; - return 0; + return false; } default: { printf("Unknown Conditional\n"); gnoll_errno = UNDEFINED_BEHAVIOUR; - return 0; + return false; } } printf("Unknown Conditional\n"); gnoll_errno = UNDEFINED_BEHAVIOUR; - return 1; + return true; } diff --git a/src/grammar/operations/conditionals.h b/src/grammar/operations/conditionals.h index a571aa15b..89a1e4316 100644 --- a/src/grammar/operations/conditionals.h +++ b/src/grammar/operations/conditionals.h @@ -17,8 +17,8 @@ typedef enum { IF_ODD = 9, } COMPARATOR; -int check_condition(vec* x, vec* y, COMPARATOR c); +bool check_condition(vec* x, vec* y, COMPARATOR c); -int check_condition_scalar(int x, int y, COMPARATOR c); -int check_condition_vector(vec* v, COMPARATOR c); +bool check_condition_scalar(long long x, long long y, COMPARATOR c); +bool check_condition_vector(vec* v, COMPARATOR c); #endif diff --git a/src/grammar/rolls/dice_core.c b/src/grammar/rolls/dice_core.c index 2377dac2c..2463dc637 100644 --- a/src/grammar/rolls/dice_core.c +++ b/src/grammar/rolls/dice_core.c @@ -20,12 +20,12 @@ extern char * output_file; // Mocking Externs extern int random_fn_run_count; -extern int global_mock_value; +extern long long global_mock_value; extern MOCK_METHOD global_mock_style; extern int gnoll_errno; -int random_fn(int small, int big) { +long long random_fn(long long small, long long big) { /** * @brief Get a random number between 'small' and 'big' * @param small lower value @@ -48,7 +48,7 @@ int random_fn(int small, int big) { return small; }; - int value = 0; + long long value = 0; if (global_mock_style == NO_MOCK) { value = get_random_uniformly(); value = value % (big + 1 - small) + small; @@ -56,13 +56,13 @@ int random_fn(int small, int big) { value = global_mock_value; mocking_tick(); } - // printf("Dice Roll Value: %i\n", value); + // printf("Dice Roll Value: %lld\n", value); return value; } -int* perform_roll(unsigned int number_of_dice, unsigned int die_sides, - EXPLOSION_TYPE explode, int start_value) { +long long* perform_roll(unsigned long long number_of_dice, unsigned long long die_sides, + EXPLOSION_TYPE explode, long long start_value) { /** * @brief Controls logic of dice rolling above basic dX * @param number_of_dice - How many dice to roll @@ -75,17 +75,17 @@ int* perform_roll(unsigned int number_of_dice, unsigned int die_sides, return NULL; } - int explosion_condition_score = 0; - int explosion_count = 0; + long long explosion_condition_score = 0; + long long explosion_count = 0; if (gnoll_errno) { return 0; } - int single_die_roll; - int exploded_result = 0; - int* all_dice_roll; + long long single_die_roll; + long long exploded_result = 0; + long long* all_dice_roll; - int end_value = (int)start_value + (int)die_sides - 1; + long long end_value = (long long)start_value + (long long)die_sides - 1; #if USE_CLT /* Central Limit Theorom Optimization @@ -98,19 +98,19 @@ int* perform_roll(unsigned int number_of_dice, unsigned int die_sides, * PRO: We do not have to calculate all the dice rolled * CON: We lose per-dice information */ - all_dice_roll = (int*)safe_calloc(1, sizeof(int)); - float midpoint = ((float)(end_value - start_value))/2 ; - float val = get_random_normally(0, 1); + all_dice_roll = (long long*)safe_calloc(1, sizeof(long long)); + double midpoint = ((double)(end_value - start_value))/2 ; + double val = get_random_normally(0, 1); val += 3; val = ((val/6)*(number_of_dice*midpoint)) + start_value*number_of_dice; - int ival = round(val); + long long ival = round(val); all_dice_roll[0] = ival; #else - all_dice_roll = (int*)safe_calloc(number_of_dice, sizeof(int)); + all_dice_roll = (long long*)safe_calloc(number_of_dice, sizeof(long long)); do { - for (unsigned int i = 0; i < number_of_dice; i++) { + for (unsigned long long i = 0; i < number_of_dice; i++) { if (die_sides == 0) { break; } @@ -118,14 +118,14 @@ int* perform_roll(unsigned int number_of_dice, unsigned int die_sides, single_die_roll = random_fn(start_value, end_value); if (dice_breakdown){ FILE *fp = safe_fopen(output_file, "a+"); - fprintf(fp, "%i,", single_die_roll); + fprintf(fp, "%lld,", single_die_roll); fclose(fp); } all_dice_roll[i] += single_die_roll; exploded_result += single_die_roll; } - explosion_condition_score += (int)number_of_dice * (int)die_sides; + explosion_condition_score += (long long)number_of_dice * (long long)die_sides; if (explode != NO_EXPLOSION) { if (explode == ONLY_ONCE_EXPLOSION && explosion_count > 0) { break; @@ -151,7 +151,7 @@ int* perform_roll(unsigned int number_of_dice, unsigned int die_sides, return all_dice_roll; } -int* do_roll(roll_params rp) { +long long* do_roll(roll_params rp) { /** * @brief Unfurls the roll_params struct and calls dice rolling logic */ diff --git a/src/grammar/rolls/dice_core.h b/src/grammar/rolls/dice_core.h index 836fcfc3c..d68e6bac4 100644 --- a/src/grammar/rolls/dice_core.h +++ b/src/grammar/rolls/dice_core.h @@ -10,16 +10,16 @@ // Random Functions -int random_fn(int small, int big); +long long random_fn(long long small, long long big); // Rolling Functions -int* perform_roll( - unsigned int number_of_dice, - unsigned int die_sides, +long long* perform_roll( + unsigned long long number_of_dice, + unsigned long long die_sides, EXPLOSION_TYPE explode, - int start_value + long long start_value ); -int* do_roll(roll_params rp); +long long* do_roll(roll_params rp); // #ifdef __cplusplus // } diff --git a/src/grammar/rolls/dice_frontend.c b/src/grammar/rolls/dice_frontend.c index 1fa7b2e43..003a8e457 100644 --- a/src/grammar/rolls/dice_frontend.c +++ b/src/grammar/rolls/dice_frontend.c @@ -12,7 +12,7 @@ extern int gnoll_errno; void roll_plain_sided_dice(vec* x, vec* y, vec* result, EXPLOSION_TYPE explode, - int start_offset) { + long long start_offset) { /** * @brief Roll numeric dice * @param x - Amount of dice (xDy) @@ -24,8 +24,10 @@ void roll_plain_sided_dice(vec* x, vec* y, vec* result, EXPLOSION_TYPE explode, if (gnoll_errno) return; // XdY - unsigned int num_dice = (unsigned int)x->storage.content[0]; - unsigned int sides = (unsigned int)y->storage.content[0]; + + unsigned long long num_dice = (unsigned long long)x->storage.content[0]; + unsigned long long sides = (unsigned long long)y->storage.content[0]; + // e.g. d4, it is implied that it is a single dice roll_params rp; @@ -34,7 +36,7 @@ void roll_plain_sided_dice(vec* x, vec* y, vec* result, EXPLOSION_TYPE explode, rp.die_sides = sides; rp.explode = explode; rp.start_value = start_offset; - int* roll_result = do_roll(rp); + long long* roll_result = do_roll(rp); #if USE_CLT // Must Accumulate. Loses details of per-item values @@ -63,7 +65,8 @@ void roll_symbolic_dice(vec* x, vec* y, vec* result) { return; #endif - unsigned int num_dice = (unsigned int)x->storage.content[0]; + unsigned long long num_dice = (unsigned long long)x->storage.content[0]; + // e.g. d4, it is implied that it is a single dice roll_params rp; @@ -83,7 +86,7 @@ void roll_symbolic_dice(vec* x, vec* y, vec* result) { rp.start_value = 0; // First index of array - int* indexes = do_roll(rp); + long long* indexes = do_roll(rp); free_2d_array(&rp.symbol_pool, y->length); diff --git a/src/grammar/rolls/dice_frontend.h b/src/grammar/rolls/dice_frontend.h index d2cd01f3a..033e89fbd 100644 --- a/src/grammar/rolls/dice_frontend.h +++ b/src/grammar/rolls/dice_frontend.h @@ -7,7 +7,7 @@ #include "constructs/vec.h" void roll_plain_sided_dice(vec* x, vec* y, vec* result, EXPLOSION_TYPE explode, - int start_offset); + long long start_offset); void roll_symbolic_dice(vec* x, vec* y, vec* result); diff --git a/src/grammar/rolls/randomness.c b/src/grammar/rolls/randomness.c index ae411f6ff..3a2a73d57 100644 --- a/src/grammar/rolls/randomness.c +++ b/src/grammar/rolls/randomness.c @@ -1,22 +1,31 @@ -#include "external/pcg_basic.h" +#include "external/pcg-c/include/pcg_variants.h" #include "rolls/randomness.h" #include #include #include #include +#include #if USE_SECURE_RANDOM == 1 #include #endif -extern pcg32_random_t rng; +extern pcg64_random_t rng; -int get_random_uniformly(void){ - int value; +#if USE_SECURE_RANDOM == 1 +long long arc4random_uniform64() { + int64_t random_value; + random_value = (((int64_t)arc4random_uniform(INT_MAX)) << 32) | arc4random_uniform(INT_MAX); + return random_value; +} +#endif + +long long get_random_uniformly(void){ + long long value; #if USE_SECURE_RANDOM == 1 - value = (int)arc4random_uniform(INT_MAX); + value = (long long)arc4random_uniform64(); #else - value = (int)pcg32_boundedrand_r(&rng, INT_MAX); + value = (long long)pcg64_boundedrand_r(&rng, LLONG_MAX); #endif return value; } @@ -30,8 +39,8 @@ double get_random_normally(double mean, double std) { if (cached == 0.0) { double x, y, r; do { - x = 2.0 * (int)pcg32_boundedrand_r(&rng, INT_MAX) / UINT32_MAX - 1; - y = 2.0 * (int)pcg32_boundedrand_r(&rng, INT_MAX) / UINT32_MAX - 1; + x = 2.0 * (double)pcg64_boundedrand_r(&rng, LLONG_MAX) / (double)ULLONG_MAX - 1; + y = 2.0 * (double)pcg64_boundedrand_r(&rng, LLONG_MAX) / (double)ULLONG_MAX - 1; r = x * x + y * y; } while (r == 0.0 || r > 1.0); @@ -55,7 +64,7 @@ double get_random_normally(double mean, double std) { } // The rest of the function only calculates one half - int other_side = (int)pcg32_boundedrand_r(&rng, 2); + bool other_side = (bool)pcg64_boundedrand_r(&rng, 2); if (other_side){ return res*-1; } diff --git a/src/grammar/rolls/randomness.h b/src/grammar/rolls/randomness.h index 0bf8a3854..194b09766 100644 --- a/src/grammar/rolls/randomness.h +++ b/src/grammar/rolls/randomness.h @@ -1,7 +1,11 @@ #ifndef __RANDOMNESS_H__ #define __RANDOMNESS_H__ -int get_random_uniformly(void); +#if USE_SECURE_RANDOM == 1 +long long arc4random_uniform64(); +#endif + +long long get_random_uniformly(void); double get_random_normally(double mean, double std); #endif diff --git a/src/grammar/shared_header.h b/src/grammar/shared_header.h index 5ae1b71f7..bd0d638de 100644 --- a/src/grammar/shared_header.h +++ b/src/grammar/shared_header.h @@ -26,14 +26,14 @@ int roll_full_options( int enable_mocking, int enable_builtins, int mocking_type, - int mocking_seed + long long mocking_seed ); int roll(char* s); int roll_with_breakdown(char * s, char* f); int roll_and_write(char* s, char* f); void roll_and_write_R(int* return_code, char** s, char** f ); -int mock_roll(char* s, char* f, int mock_value, int mock_const); +int mock_roll(char* s, char* f, int mock_value, long long mock_const); void load_builtins(char* root); diff --git a/src/grammar/util/array_functions.c b/src/grammar/util/array_functions.c index 18399c5eb..c6a84836f 100644 --- a/src/grammar/util/array_functions.c +++ b/src/grammar/util/array_functions.c @@ -1,12 +1,12 @@ #include "util/array_functions.h" -int collapse(int * arr, unsigned int len){ +long long collapse(long long * arr, unsigned long long len){ return sum(arr, len); } -int sum(int * arr, unsigned int len){ - int result = 0; - for(unsigned int i = 0; i != len; i++) result += arr[i]; +long long sum(long long * arr, unsigned long long len){ + long long result = 0; + for(unsigned long long i = 0; i != len; i++) result += arr[i]; return result; } diff --git a/src/grammar/util/array_functions.h b/src/grammar/util/array_functions.h index f3d0ffa2c..0a187a7d7 100644 --- a/src/grammar/util/array_functions.h +++ b/src/grammar/util/array_functions.h @@ -2,7 +2,7 @@ #ifndef ARRAY_FN_HEADER #define ARRAY_FN_HEADER -int sum(int* arr, unsigned int len); -int collapse(int* arr, unsigned int len); +long long sum(long long* arr, unsigned long long len); +long long collapse(long long* arr, unsigned long long len); #endif diff --git a/src/grammar/util/mocking.c b/src/grammar/util/mocking.c index 05d09d132..16d2f182b 100644 --- a/src/grammar/util/mocking.c +++ b/src/grammar/util/mocking.c @@ -1,8 +1,8 @@ #include "util/mocking.h" int random_fn_run_count = 0; -int global_mock_value = 0; -int secondary_mock_value = 0; +long long global_mock_value = 0; +long long secondary_mock_value = 0; MOCK_METHOD global_mock_style = NO_MOCK; @@ -14,7 +14,7 @@ void reset_mocking(void) { global_mock_value = 0; global_mock_style = NO_MOCK; } -void init_mocking(MOCK_METHOD mock_style, int starting_value) { +void init_mocking(MOCK_METHOD mock_style, long long starting_value) { /** * @brief Initializes test mocking with given settings * @param mock_style How to apply mocking diff --git a/src/grammar/util/mocking.h b/src/grammar/util/mocking.h index 6f1b93f1b..94c7cb8c6 100644 --- a/src/grammar/util/mocking.h +++ b/src/grammar/util/mocking.h @@ -15,7 +15,7 @@ typedef enum { // Mocking Util void reset_mocking(void); -void init_mocking(MOCK_METHOD mock_style, int starting_value); +void init_mocking(MOCK_METHOD mock_style, long long starting_value); void mocking_tick(void); #endif diff --git a/src/grammar/util/safe_functions.c b/src/grammar/util/safe_functions.c index c59aa82ff..9a6a580ca 100644 --- a/src/grammar/util/safe_functions.c +++ b/src/grammar/util/safe_functions.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "shared_header.h" @@ -16,6 +17,53 @@ extern int verbose; #define ANSI_COLOR_GREEN "\x1b[32m" #define ANSI_COLOR_RESET "\x1b[0m" +long long safe_add(long long a, long long b){ + /* + A wrapper around addition to catch and signal over/underflow + Credit: https://stackoverflow.com/a/1514309/1421555 + */ + if (a > 0 && b > LLONG_MAX - a) { + gnoll_errno = MATH_OVERFLOW; + return LLONG_MAX; + } else if (a < 0 && b < LLONG_MIN - a) { + gnoll_errno = MATH_UNDERFLOW; + return LLONG_MIN; + } + return a + b; +} + + +long long safe_subtract(long long a, long long b){ + /* + A wrapper around addition to catch and signal over/underflow + Credit: https://stackoverflow.com/a/1514309/1421555 + */ + if ((b < 0 && a > LLONG_MAX + b)) { + gnoll_errno = MATH_OVERFLOW; + return LLONG_MAX; + } else if (b > 0 && a < LLONG_MIN + b) { + gnoll_errno = MATH_UNDERFLOW; + return LLONG_MIN; + } + return a - b; +} + + +long long safe_mul(long long a, long long b){ + /* + A wrapper around addition to catch and signal over/underflow + Credit: https://stackoverflow.com/a/1514309/1421555 + */ + if (b != 0 && a > LLONG_MAX / b) { + gnoll_errno = MATH_OVERFLOW; + return LLONG_MAX; + } else if (b != 0 && a < LLONG_MAX / b) { + gnoll_errno = MATH_UNDERFLOW; + return LLONG_MIN; + } + return a * b; +} + void print_gnoll_errors(void){ /** @@ -77,6 +125,14 @@ void print_gnoll_errors(void){ printf("%sErrorCheck: Undefined Macro.%s\n",ANSI_COLOR_RED, ANSI_COLOR_RESET); break; } + case MATH_OVERFLOW:{ + printf("%sErrorCheck: Math overflow/saturation.%s\n",ANSI_COLOR_RED, ANSI_COLOR_RESET); + break; + } + case MATH_UNDERFLOW:{ + printf("%sErrorCheck: Math underflow/desaturation.%s\n",ANSI_COLOR_RED, ANSI_COLOR_RESET); + break; + } default:{ printf("%sErrorCheck: Error (Undetermined. Code %i).%s\n",ANSI_COLOR_RED, gnoll_errno, ANSI_COLOR_RESET); break; @@ -84,7 +140,7 @@ void print_gnoll_errors(void){ } } -void *safe_malloc(size_t size) { +void *safe_malloc(unsigned long long size) { /** * @brief Safe version of malloc. Populates gnoll_errno on error * @param size @@ -116,14 +172,14 @@ void free_vector(vec v){ } } -void free_2d_array(char ***arr, unsigned int items) { +void free_2d_array(char ***arr, unsigned long long items) { /** * @brief Free a 2d char array in a repeatable manner. * @param arr * @param items */ if (*arr) { - for (unsigned int i = 0; i != items; i++) { + for (unsigned long long i = 0; i != items; i++) { if ((*arr)[i]) { free((*arr)[i]); } @@ -133,8 +189,8 @@ void free_2d_array(char ***arr, unsigned int items) { } void safe_copy_2d_chararray_with_allocation(char ***dst, char **src, - unsigned int items, - unsigned int max_size) { + unsigned long long items, + unsigned long long max_size) { /** * @brief Copy from one 2d char array to another in a repeatable manner. * @param dst @@ -148,7 +204,7 @@ void safe_copy_2d_chararray_with_allocation(char ***dst, char **src, return; } - for (unsigned int i = 0; i != items; i++) { + for (unsigned long long i = 0; i != items; i++) { (*dst)[i] = (char*)safe_calloc(sizeof(char), max_size); if (gnoll_errno) { @@ -160,7 +216,7 @@ void safe_copy_2d_chararray_with_allocation(char ***dst, char **src, } -void * safe_calloc(size_t nitems, size_t size) { +void * safe_calloc(unsigned long long nitems, unsigned long long size) { /** * @brief Safe version of calloc. Populates gnoll_errno on error * @param size @@ -173,7 +229,7 @@ void * safe_calloc(size_t nitems, size_t size) { } void *calloc_result = NULL; calloc_result = calloc(nitems, size); - long unsigned int total_sz = nitems * size; + unsigned long long total_sz = nitems * size; if (!calloc_result && total_sz) { gnoll_errno = BAD_ALLOC; } @@ -223,21 +279,21 @@ char *safe_strdup(const char *str1) { return result; } -int fast_atoi(const char *str) { +long long fast_atoi(const char *str) { /** * @brief Safe version of atoi. Populates gnoll_errno on error * @param str * @return */ // Ref: https://stackoverflow.com/a/16826908/1421555 - int val = 0; + long long val = 0; while (*str) { val = val * 10 + (*str++ - '0'); } return val; } -long int safe_strtol(const char *str, char **endptr, int base) { +long long safe_strtol(const char *str, char **endptr, int base) { /** * @brief Safe version of strtol. Populates gnoll_errno on error * @param str @@ -248,7 +304,7 @@ long int safe_strtol(const char *str, char **endptr, int base) { if (gnoll_errno) { return 0; } - long int result; + long long result; result = strtol(str, endptr, base); if (errno == ERANGE) { gnoll_errno = OUT_OF_RANGE; diff --git a/src/grammar/util/safe_functions.h b/src/grammar/util/safe_functions.h index 7fef7cfe8..ac97611b7 100644 --- a/src/grammar/util/safe_functions.h +++ b/src/grammar/util/safe_functions.h @@ -19,23 +19,29 @@ typedef enum { MAX_LOOP_LIMIT_HIT = 9, SYNTAX_ERROR = 10, DIVIDE_BY_ZERO = 11, - UNDEFINED_MACRO = 12 + UNDEFINED_MACRO = 12, + MATH_OVERFLOW = 13, + MATH_UNDERFLOW = 14 } ERROR_CODES; +long long safe_subtract(long long a, long long b); +long long safe_add(long long a, long long b); +long long safe_mul(long long a, long long b); + void print_gnoll_errors(void); -void *safe_malloc(size_t size); -void *safe_calloc(size_t nitems, size_t size); +void *safe_malloc(unsigned long long size); +void *safe_calloc(unsigned long long nitems, unsigned long long size); FILE *safe_fopen(const char *filename, const char *mode); char *safe_strdup(const char *str1); -long int safe_strtol(const char *str, char **endptr, int base); +long long int safe_strtol(const char *str, char **endptr, int base); void safe_copy_2d_chararray_with_allocation(char ***dst, char **src, - unsigned int items, - unsigned int max_size); -void free_2d_array(char ***arr, unsigned int items); + unsigned long long items, + unsigned long long max_size); +void free_2d_array(char ***arr, unsigned long long items); void free_vector(vec v); -int fast_atoi(const char *str); +long long fast_atoi(const char *str); #endif diff --git a/src/grammar/util/string_functions.c b/src/grammar/util/string_functions.c index 771cfaeb6..8a787ecaf 100644 --- a/src/grammar/util/string_functions.c +++ b/src/grammar/util/string_functions.c @@ -5,7 +5,7 @@ extern int gnoll_errno; -char * concat_strings(char ** s, unsigned int num_s){ +char * concat_strings(char ** s, unsigned long long num_s){ /** * @brief Given an array of strings, join them together. * @param s array of strings @@ -15,9 +15,9 @@ char * concat_strings(char ** s, unsigned int num_s){ if (num_s == 1){ return s[0]; } - long unsigned int size_total = 0; - unsigned int spaces = 0; - for(unsigned int i = 1; i != num_s + 1; i++){ + unsigned long long size_total = 0; + unsigned long long spaces = 0; + for(unsigned long long i = 1; i != num_s + 1; i++){ size_total += strlen(s[i]) + 1; } if (num_s > 1){ @@ -30,7 +30,7 @@ char * concat_strings(char ** s, unsigned int num_s){ char * result = (char *)safe_calloc((size_total+1), sizeof(char)); if(gnoll_errno){return NULL;} - for(unsigned int i = 1; i != num_s + 1; i++){ + for(unsigned long long i = 1; i != num_s + 1; i++){ // printf() strcat(result, s[i]); if (spaces && i < num_s){ diff --git a/src/grammar/util/string_functions.h b/src/grammar/util/string_functions.h index 9d88c00e9..ad975ac19 100644 --- a/src/grammar/util/string_functions.h +++ b/src/grammar/util/string_functions.h @@ -1,4 +1,4 @@ #ifndef __STR_FNS_H__ #define __STR_FNS_H__ -char * concat_strings(char ** s, unsigned int num_s); +char * concat_strings(char ** s, unsigned long long num_s); #endif diff --git a/src/grammar/util/vector_functions.c b/src/grammar/util/vector_functions.c index be5037d38..00eea16a0 100644 --- a/src/grammar/util/vector_functions.c +++ b/src/grammar/util/vector_functions.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "operations/conditionals.h" #include "shared_header.h" @@ -13,7 +14,7 @@ extern int gnoll_errno; void light_initialize_vector(vec *vector, DIE_TYPE dt, - unsigned int number_of_items) { + unsigned long long number_of_items) { /** * @brief Initializes a vector, but does not fill out 2d arrays * @param vector vector to initialize @@ -26,14 +27,17 @@ void light_initialize_vector(vec *vector, DIE_TYPE dt, vector->has_source = false; if (dt == NUMERIC) { - vector->storage.content = (int*)safe_calloc(number_of_items, sizeof(int)); + + vector->storage.content = (long long*)safe_calloc(number_of_items, sizeof(long long)); + if (gnoll_errno) return; } else if (dt == SYMBOLIC) { vector->storage.symbols = (char**)safe_calloc(1, sizeof(char **)); } } -void initialize_vector_pointer(vec ***vector, DIE_TYPE dt, unsigned int number_of_items) { + +void initialize_vector_pointer(vec ***vector, DIE_TYPE dt, unsigned long long number_of_items) { // Initialize a pointer to a vector // Note: Is not a 2d vector. *vector = (vec**)safe_calloc(1, sizeof(vec*)); @@ -44,7 +48,8 @@ void initialize_vector_pointer(vec ***vector, DIE_TYPE dt, unsigned int number_o initialize_vector((*vector)[0], dt, number_of_items); } -void initialize_vector(vec *vector, DIE_TYPE dt, unsigned int number_of_items) { +void initialize_vector(vec *vector, DIE_TYPE dt, unsigned long long number_of_items) { + /** * @brief Initializes a vector, reserving space for 2d arrays * @param vector vector to initialize @@ -61,7 +66,10 @@ void initialize_vector(vec *vector, DIE_TYPE dt, unsigned int number_of_items) { vector->has_source = false; if (dt == NUMERIC) { - vector->storage.content = (int*)safe_calloc(number_of_items, sizeof(int)); + + vector->storage.content = (long long*)safe_calloc(number_of_items, sizeof(long long)); + + if (gnoll_errno) return; } else if (dt == SYMBOLIC) @@ -69,15 +77,17 @@ void initialize_vector(vec *vector, DIE_TYPE dt, unsigned int number_of_items) { vector->storage.symbols = (char**)safe_calloc(number_of_items, sizeof(char *)); if (gnoll_errno) return; - for (unsigned int i = 0; i < number_of_items; i++) { + for (unsigned long long i = 0; i < number_of_items; i++) { vector->storage.symbols[i] = (char*)safe_calloc(MAX_SYMBOL_LENGTH, sizeof(char)); + + if (gnoll_errno) return; } } } -void concat_symbols(char **arr1, unsigned int len1, char **arr2, - unsigned int len2, char **new_arr) { +void concat_symbols(char **arr1, unsigned long long len1, char **arr2, + unsigned long long len2, char **new_arr) { /** * @brief Concatenates two 2D arrays of dice symbols * @param arr1 @@ -91,18 +101,18 @@ void concat_symbols(char **arr1, unsigned int len1, char **arr2, return; } - for (unsigned int i = 0; i != len1; i++) { + for (unsigned long long i = 0; i != len1; i++) { strcpy(new_arr[i], arr1[i]); // free(arr1[i]); } - for (unsigned int i = 0; i != len2; i++) { - unsigned int idx = len1 + i; + for (unsigned long long i = 0; i != len2; i++) { + unsigned long long idx = len1 + i; strcpy(new_arr[idx], arr2[i]); // free(arr2[i]); } } -void pop(int *arr, unsigned int len, int value, int *new_arr) { +void pop(long long *arr, unsigned long long len, long long value, long long *new_arr) { /** * @brief Removes a value from an array * @param arr @@ -115,11 +125,11 @@ void pop(int *arr, unsigned int len, int value, int *new_arr) { } // This could be done in-place. - int seen = 0; + bool seen = false; - for (unsigned int i = 0; i != len; i++) { + for (unsigned long long i = 0; i != len; i++) { if (arr[i] == value && !seen) { - seen = 1; + seen = true; // Don't insert into new area. } else if (seen) { new_arr[i - 1] = arr[i]; @@ -129,7 +139,7 @@ void pop(int *arr, unsigned int len, int value, int *new_arr) { } } -int contains(int *arr, unsigned int len, int value) { +bool contains(long long *arr, unsigned long long len, long long value) { /** * @brief Checks if a value exists in an array * @param arr @@ -138,16 +148,16 @@ int contains(int *arr, unsigned int len, int value) { * @return true or false (1 or 0) */ if (gnoll_errno) { - return 0; + return true; } - for (unsigned int i = 0; i != len; i++) { - if (arr[i] == value) return 1; + for (unsigned long long i = 0; i != len; i++) { + if (arr[i] == value) return true; } - return 0; + return false; } -int min_in_vec(int *arr, unsigned int len) { +long long min_in_vec(long long *arr, unsigned long long len) { /** * @brief Return the smallest value from an array * @param arr @@ -158,14 +168,14 @@ int min_in_vec(int *arr, unsigned int len) { return 0; } - int lowest = INT_MAX; - for (unsigned int i = 0; i != len; i++) { + long long lowest = LLONG_MAX; + for (unsigned long long i = 0; i != len; i++) { if (arr[i] < lowest) lowest = arr[i]; } return lowest; } -int max_in_vec(int *arr, unsigned int len) { +long long max_in_vec(long long *arr, unsigned long long len) { /** * @brief Return the biggest value in an array * @param arr @@ -176,15 +186,17 @@ int max_in_vec(int *arr, unsigned int len) { return 0; } - int highest = INT_MIN; - for (unsigned int i = 0; i != len; i++) { + long long highest = LLONG_MIN; + for (unsigned long long i = 0; i != len; i++) { if (arr[i] > highest) highest = arr[i]; } return highest; } void abs_vec(vec *x) { - for (unsigned int i = 0; i != x->length; i++) { - int v = x->storage.content[i]; + + for (unsigned long long i = 0; i != x->length; i++) { + long long v = x->storage.content[i]; + if (v < 0) { x->storage.content[i] *= -1; } @@ -200,17 +212,21 @@ void print_vec(vec vector) { return; } - printf("Vector Size: %u\n", vector.length); + printf("Vector Size: %llu\n", vector.length); if (vector.dtype == NUMERIC) { printf("Vector Type: NUMERIC\n"); - for (unsigned int i = 0; i != vector.length; i++) { - printf("\t%d\n", vector.storage.content[i]); + + for (unsigned long long i = 0; i != vector.length; i++) { + printf("\t%lld\n", vector.storage.content[i]); + } } else { printf("Vector Type: SYMBOLIC\n"); printf("Symbols:\n"); - for (unsigned int i = 0; i != vector.length; i++) { + + for (unsigned long long i = 0; i != vector.length; i++) { printf("\t- %s\n", vector.storage.symbols[i]); + } } } @@ -238,12 +254,14 @@ void collapse_vector(vec *vector, vec *new_vector) { new_vector->has_source = false; } else { - int c = 0; - for (unsigned int i = 0; i != vector->length; i++) { + + long long c = 0; + for (unsigned long long i = 0; i != vector->length; i++) { c += vector->storage.content[i]; } - new_vector->storage.content = (int*)safe_calloc(sizeof(int), 1); + new_vector->storage.content = (long long*)safe_calloc(sizeof(long long), 1); + if (gnoll_errno) return; new_vector->storage.content[0] = c; new_vector->length = 1; @@ -253,8 +271,10 @@ void collapse_vector(vec *vector, vec *new_vector) { return; } -void keep_logic(vec *vector, vec **output_vector, unsigned int number_to_keep, - int keep_high) { + +void keep_logic(vec *vector, vec **output_vector, unsigned long long number_to_keep, + bool keep_high) { + /** * @brief Collapses multiple Numeric dice to one value by summing * @param vector source (Freed at end) @@ -266,7 +286,7 @@ void keep_logic(vec *vector, vec **output_vector, unsigned int number_to_keep, return; } - unsigned int available_amount = vector->length; + unsigned long long available_amount = vector->length; if (vector->dtype == SYMBOLIC) { printf( @@ -284,22 +304,28 @@ void keep_logic(vec *vector, vec **output_vector, unsigned int number_to_keep, // } // output_vector->length = number_to_keep; - int *arr = vector->storage.content; - int *new_arr; - unsigned int length = vector->length; + + long long *arr = vector->storage.content; + long long *new_arr; + unsigned long long length = vector->length; + // while (number needed) // Get Max/Min from vector // Store in output - for (unsigned int i = 0; i != number_to_keep; i++) { - int m; + for (unsigned long long i = 0; i != number_to_keep; i++) { + long long m; if (keep_high) { m = max_in_vec(arr, length); } else { m = min_in_vec(arr, length); } + + (*output_vector)->storage.content[i] = m; - new_arr = (int*)safe_calloc(sizeof(int), length - 1); + new_arr = (long long*)safe_calloc(sizeof(long long), length - 1); + + if (gnoll_errno) { return; } @@ -320,52 +346,59 @@ void keep_logic(vec *vector, vec **output_vector, unsigned int number_to_keep, } } + void keep_lowest_values(vec *vector, vec **new_vector, - unsigned int number_to_keep) { + unsigned long long number_to_keep) { /** * @brief Keep the lowest values from a set of dice */ - keep_logic(vector, new_vector, number_to_keep, 0); + keep_logic(vector, new_vector, number_to_keep, false); } + void keep_highest_values(vec *vector, vec **new_vector, - unsigned int number_to_keep) { + unsigned long long number_to_keep) { + /** * @brief Keep the Highest values from a set of dice */ - keep_logic(vector, new_vector, number_to_keep, 1); + keep_logic(vector, new_vector, number_to_keep, true); } + void drop_lowest_values(vec *vector, vec **new_vector, - unsigned int number_to_drop) { + unsigned long long number_to_drop) { /** * @brief Drop the lowest values from a set of dice */ - int calc_keep = (int)vector->length - (int)number_to_drop; - unsigned int number_to_keep; + long long calc_keep = (long long)vector->length - (long long)number_to_drop; + unsigned long long number_to_keep; + if (calc_keep > 0) { - number_to_keep = (unsigned int)calc_keep; + number_to_keep = (unsigned long long)calc_keep; } else { - number_to_keep = (unsigned int)vector->length; + number_to_keep = (unsigned long long)vector->length; } - keep_logic(vector, new_vector, number_to_keep, 1); + keep_logic(vector, new_vector, number_to_keep, true); } + void drop_highest_values(vec *vector, vec **new_vector, - unsigned int number_to_drop) { + unsigned long long number_to_drop) { /** * @brief Drop the highest values from a set of dice */ - int calc_keep = (int)vector->length - (int)number_to_drop; - unsigned int number_to_keep; + long long calc_keep = (long long)vector->length - (long long)number_to_drop; + unsigned long long number_to_keep; + if (calc_keep > 0) { - number_to_keep = (unsigned int)calc_keep; + number_to_keep = (unsigned long long)calc_keep; } else { - number_to_keep = (unsigned int)vector->length; + number_to_keep = (unsigned long long)vector->length; } keep_logic(vector, new_vector, number_to_keep, 0); } -void extract_symbols(char **symbols_list, char **result_symbols, int *indexes, - unsigned int idx_length) { +void extract_symbols(char **symbols_list, char **result_symbols, long long *indexes, + unsigned long long idx_length) { /** * @brief Take symbols from indexed locations in an array and save to a new * location @@ -379,14 +412,14 @@ void extract_symbols(char **symbols_list, char **result_symbols, int *indexes, } // Free up memory before overwriting (done in vec-init) - for (unsigned int i = 0; i != idx_length; i++) { + for (unsigned long long i = 0; i != idx_length; i++) { if (result_symbols[i]) { free(result_symbols[i]); } } - for (unsigned int i = 0; i != idx_length; i++) { - int index = indexes[i]; + for (unsigned long long i = 0; i != idx_length; i++) { + long long index = indexes[i]; result_symbols[i] = safe_strdup(symbols_list[index]); } } @@ -407,9 +440,11 @@ void filter(vec *dice, vec *cond, int comp_op, vec *output) { return; } - unsigned int success_idx = 0; - for (unsigned int i = 0; i != dice->length; i++) { - int v = dice->storage.content[i]; + + unsigned long long success_idx = 0; + for (unsigned long long i = 0; i != dice->length; i++) { + long long v = dice->storage.content[i]; + if (comp_op == IF_EVEN || comp_op == IF_ODD){ if(check_condition_scalar(v, v, (COMPARATOR)comp_op)){ output->storage.content[success_idx] = v; @@ -417,7 +452,10 @@ void filter(vec *dice, vec *cond, int comp_op, vec *output) { } }else{ - int compare_to = cond->storage.content[0]; + + long long compare_to = cond->storage.content[0]; + + if (check_condition_scalar(v, compare_to, (COMPARATOR)comp_op)) { output->storage.content[success_idx] = v; @@ -438,9 +476,11 @@ void filter_unique(vec *dice, vec *new_vec) { return; } - unsigned int tracker_idx = 0; - for (unsigned int i = 0; i != dice->length; i++) { - int v = dice->storage.content[i]; + + unsigned long long tracker_idx = 0; + for (unsigned long long i = 0; i != dice->length; i++) { + long long v = dice->storage.content[i]; + if (!contains(new_vec->storage.content, new_vec->length, v)) { new_vec->storage.content[tracker_idx] = v; diff --git a/src/grammar/util/vector_functions.h b/src/grammar/util/vector_functions.h index feaf5c51c..408036a4f 100644 --- a/src/grammar/util/vector_functions.h +++ b/src/grammar/util/vector_functions.h @@ -4,38 +4,43 @@ #include "constructs/dice_enums.h" #include "constructs/vec.h" #include "shared_header.h" +#include + + +void initialize_vector_pointer(vec ***vector, DIE_TYPE dt, unsigned long long number_of_items); +void initialize_vector(vec* vector, DIE_TYPE dt, unsigned long long number_of_items); -void initialize_vector_pointer(vec ***vector, DIE_TYPE dt, unsigned int number_of_items); -void initialize_vector(vec* vector, DIE_TYPE dt, unsigned int number_of_items); void light_initialize_vector(vec* vector, DIE_TYPE dt, - unsigned int number_of_items); + unsigned long long number_of_items); -void pop(int* arr, unsigned int len, int value, int* new_arr); +void pop(long long* arr, unsigned long long len, long long value, long long* new_arr); void abs_vec(vec* x); -int contains(int* arr, unsigned int len, int value); -int min_in_vec(int* arr, unsigned int len); -int max_in_vec(int* arr, unsigned int len); +bool contains(long long* arr, unsigned long long len, long long value); +long long min_in_vec(long long* arr, unsigned long long len); +long long max_in_vec(long long* arr, unsigned long long len); -void concat_symbols(char** arr1, unsigned int len1, char** arr2, - unsigned int len2, char** new_arr); +void concat_symbols(char** arr1, unsigned long long len1, char** arr2, + unsigned long long len2, char** new_arr); void collapse_vector(vec* vector, vec* new_vector); -void keep_logic(vec* vector, vec** new_vector, unsigned int number_to_keep, - int keep_high); + +void keep_logic(vec* vector, vec** new_vector, unsigned long long umber_to_keep, + bool keep_high); void keep_highest_values(vec* vector, vec** new_vector, - unsigned int number_to_keep); + unsigned long long number_to_keep); void keep_lowest_values(vec* vector, vec** new_vector, - unsigned int number_to_keep); + unsigned long long number_to_keep); void drop_highest_values(vec* vector, vec** new_vector, - unsigned int number_to_drop); + unsigned long long number_to_drop); void drop_lowest_values(vec* vector, vec** new_vector, - unsigned int number_to_drop); + unsigned long long number_to_drop); + -void extract_symbols(char** symbols_list, char** result_symbols, int* indexes, - unsigned int idx_length); +void extract_symbols(char** symbols_list, char** result_symbols, long long* indexes, + unsigned long long idx_length); void print_vec(vec vector); diff --git a/src/java/target.mk b/src/java/target.mk index 5d40c9090..8895461d4 100644 --- a/src/java/target.mk +++ b/src/java/target.mk @@ -10,8 +10,8 @@ JAVA_FOLDER=$(PWD)/src/java java: clean yacc lex compile $(OBJECTS) mkdir -p build/java/ cd $(JAVA_FOLDER)/src ; javac org/gnoll/DiceNotationParser.java -h .; cd ../.. - $(CC) $(SHAREDCFLAGS) -c src/java/src/org_gnoll_DiceNotationParser.c -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux - $(CC) -shared -o build/java/libdice.so org_gnoll_DiceNotationParser.o $(OBJECTS) $(ARC4RANDOM) -Wl,-soname,gnoll + $(CC) $(SHAREDCFLAGS) -c src/java/src/org_gnoll_DiceNotationParser.c -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux + $(CC) -shared -o build/java/libdice.so org_gnoll_DiceNotationParser.o $(OBJECTS) $(ARC4RANDOM) -Wl,-soname,gnoll -lpcg_random -L$(PCG_SRC) cp build/java/libdice.so src/java/libdice.so cd $(JAVA_FOLDER)/src/; LD_LIBRARY_PATH=$(PWD)/build/java/ javac -cp .:$(JAVA_FOLDER)/classes/ -d $(JAVA_FOLDER)/classes/ Test.java cd $(JAVA_FOLDER)/src/; LD_LIBRARY_PATH=$(PWD)/build/java/ java -cp .:$(JAVA_FOLDER)/classes/ Test diff --git a/src/js/target.mk b/src/js/target.mk index 895136d78..8cd29e0e9 100644 --- a/src/js/target.mk +++ b/src/js/target.mk @@ -2,7 +2,8 @@ JS_OPT=-O3 -Wall # YACC/LEX generates code with errors, so disabling warning-to-error escalation -DISABLE_ERRORS= -Wno-error=implicit-function-declaration +# PCG also generates code with errors +DISABLE_ERRORS= -Wno-error=implicit-function-declaration -Wno-sign-conversion -Wno-sign-compare -Wno-implicit-int-conversion -Wno-undef -Wno-shorten-64-to-32 ifneq ($(OS),Windows_NT) UNAME_S := $(shell uname -s) diff --git a/src/perl/target.mk b/src/perl/target.mk index f4b455c00..126d61111 100644 --- a/src/perl/target.mk +++ b/src/perl/target.mk @@ -7,7 +7,7 @@ swig_perl: clean yacc lex compile $(OBJECTS) PERL_VERSION=5.30 compile_perl: swig_perl $(CC) -fPIC -c build/perl/gnoll_wrap.c -I/usr/lib/x86_64-linux-gnu/perl/$(PERL_VERSION)/CORE/ -Dbool=char -Doff64_t=__off64_t -o build/gnoll_perl_wrap.o - $(CC) -shared -o build/gnoll.so build/gnoll_perl_wrap.o $(OBJECTS) + $(CC) -shared -o build/gnoll.so build/gnoll_perl_wrap.o $(OBJECTS) -lpcg_random -L$(PCG_SRC) perl: compile_perl echo "Done" diff --git a/src/python/code/gnoll/__init__.py b/src/python/code/gnoll/__init__.py index 16afc4f91..c0a461e87 100644 --- a/src/python/code/gnoll/__init__.py +++ b/src/python/code/gnoll/__init__.py @@ -1,7 +1,7 @@ import os import sys import tempfile -from ctypes import cdll +from ctypes import c_long, cdll BUILD_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "c_build")) C_SHARED_LIB = os.path.join(BUILD_DIR, "dice.so") @@ -37,19 +37,23 @@ def raise_gnoll_error(value): GNOLLException("SYNTAX_ERROR"), GNOLLException("DIVIDE_BY_ZERO"), GNOLLException("UNDEFINED_MACRO"), + GNOLLException("MATH_OVERFLOW"), + GNOLLException("MATH_UNDERFLOW"), ] err = d[value] if err is not None: raise err -def roll(s, - verbose=False, - mock=None, - mock_const=3, - breakdown=False, - builtins=False, - keep_temp_file=False): +def roll( + s, + verbose=False, + mock=None, + mock_const=3, + breakdown=False, + builtins=False, + keep_temp_file=False, +): """Parse some dice notation with GNOLL. @param s the string to parse @param verbose whether to enable verbosity (primarily for debug) @@ -60,6 +64,7 @@ def roll(s, @param force_dll_reload destroy the dll/shared object and reload (inadvisable) @return return code, final result, dice breakdown (None if disabled) """ + def make_native_type(v): """ Change a string to a more appropriate type if possible. @@ -86,9 +91,9 @@ def extract_from_dice_file(lines, seperator): return v try: - temp = tempfile.NamedTemporaryFile(prefix="gnoll_roll_", - suffix=".die", - delete=False) + temp = tempfile.NamedTemporaryFile( + prefix="gnoll_roll_", suffix=".die", delete=False + ) temp.close() die_file = temp.name @@ -100,6 +105,8 @@ def extract_from_dice_file(lines, seperator): s = s.encode("ascii") + mock_const = c_long(mock_const) + return_code = libc.roll_full_options( s, out_file, @@ -133,9 +140,11 @@ def extract_from_dice_file(lines, seperator): arg = "".join(sys.argv[1:]) arg = arg if arg != "" else "1d20" code, r, detailed_r = roll(arg, verbose=False) - print(f""" + print( + f""" [[GNOLL Results]] Dice Roll: {arg} Result: {r} Exit Code: {code}, -Dice Breakdown: {detailed_r}""") +Dice Breakdown: {detailed_r}""" + ) diff --git a/src/python/target.mk b/src/python/target.mk index 5957b8ba0..17e0592f6 100644 --- a/src/python/target.mk +++ b/src/python/target.mk @@ -7,7 +7,11 @@ python: all rm -rf src/python/code/gnoll.egg-info/ cp -r build/ src/python/code/gnoll/c_build/ - cp -r src/grammar/ src/python/code/gnoll/c_includes/ + rsync -avR --mkpath --progress src/grammar/ src/python/code/gnoll/c_includes/ \ + --exclude src/grammar/external/pcg-c/extras \ + --exclude src/grammar/external/pcg-c/sample \ + --exclude src/grammar/external/pcg-c/test-high \ + --exclude src/grammar/external/pcg-c/test-low pip : python cd src/python/ ; python3 -m build diff --git a/tests/python/systems/Troika/test_troika.py b/tests/python/systems/Troika/test_troika.py index d3e9d0eaa..d9780b898 100644 --- a/tests/python/systems/Troika/test_troika.py +++ b/tests/python/systems/Troika/test_troika.py @@ -7,6 +7,7 @@ def test_d6(): r = "d6" result, _ = roll(r, mock_mode=Mock.RETURN_CONSTANT, mock_const=3) + print("TROIKA: GOT: ", result) assert result == 3 diff --git a/tests/python/test_huge_number.py b/tests/python/test_huge_number.py new file mode 100644 index 000000000..34d41a1f4 --- /dev/null +++ b/tests/python/test_huge_number.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import pytest +from util import roll + + +@pytest.mark.parametrize( + "r, at_least", + [("1d922337203685477580", 10000000000000000)], +) +def test_longlong(r, at_least): + largest_value = 0 + for _ in range(300): + result, _ = roll(r) + largest_value = max(largest_value, result) + if largest_value > at_least: + break + assert largest_value > at_least + + +@pytest.mark.skip(reason="Not Implemented yet") +@pytest.mark.parametrize( + "r, at_least", + [ + ("1d" + "9" * 100, int("1" * 100)), + ("1d" + "9" * 1000, int("1" * 1000)), + # Numbers larger than this start causing issues in python even if we dont run the test. + ], +) +def test_ridiculously_big_numbers(r, at_least): + largest_value = 0 + for _ in range(300): + result, _ = roll(r) + largest_value = max(largest_value, result) + if largest_value > at_least: + break + assert largest_value > at_least