From 50cf424146977ad7bc90d05269817112daaf3675 Mon Sep 17 00:00:00 2001 From: "lei.chen" Date: Tue, 20 Oct 2026 18:04:16 +0000 Subject: [PATCH] build: remove nix dependency layer -- apt system libs + meson wrap subprojects The build no longer self-wraps into `nix develop`: src/tools/xce-build.sh now runs meson+ninja directly on system packages, with a dependency preflight that fails early naming the missing tool/pkg-config package (DEPS.md). Dependencies (see DEPS.md for the full tables): - 11 C libraries from apt (libuv, openssl, libedit, sqlite3, hwloc, libcgroup, libtirpc, libcyaml, libyaml, zlib, libsystemd) with version floors in meson.build mirroring the Ubuntu 24.04 baseline. - sd-bus: default libsystemd, -Duse_elogind=true opt-back for nix-era hosts. - 6 libraries/tools unavailable in apt become committed meson wrap subprojects under src/subprojects/ (source closure, ~500 files): the upstream trees plus packagefiles/ overlays and diff_files patches registering dependency/program overrides the nix .pc files used to provide (incl. the '-raw' variable deps the Go CGO path reads). Fresh-clone reproducibility verified: wiped trees + `meson subprojects download` reproduce the committed state exactly (fixed librtti.wrap's dangling patch_directory and c-capnproto's empty packagefiles overlay). - xceadmin: self-contained venv built from requirements-build.txt (pinned, offline-seedable via PIP_FIND_LINKS) instead of --system-site-packages. Build/packaging: - Makefile facade over xce-build.sh; scripts/ci-ubuntu.sh drives a bare Ubuntu 24.04 container through deps + build + tests. - src/tools/xce-package.sh: release-tree tarball packager. Collects non-base DT_NEEDED libs from the BUILD-tree binaries (staged ldd lies: the dangling build RPATH makes ldd drop the very lines the naive filter needs), sets $ORIGIN RPATHs, rebases the xceadmin venv at install time (kernel does not parse quotes in shebangs), ships systemd unit samples + install.sh. Local smoke test: all 8 binaries resolve, xceadmin works from both bin/ wrapper and venv script. Test fixes found on the way (all environmental, not build bugs): - harness_test.c setUp(): pin XCE_CONTROLLER_PEERS to a bound-then-closed loopback port so the CLI-error tests assert the no-controller failure path even on a dev box running a live cluster on localhost:9990. - test_test_cli.c: setpgid(0,0) in the spawned-xce_test child. libedit's sig_handler re-raises received signals via kill(0, sig) -- process GROUP wide (strace -k evidence) -- and the child previously shared the harness's pgrp, so an interrupted SSL handshake killed the whole suite (exit 130). Also fixed while re-baselining on the de-nix toolchain (pre-existing, now deterministic): raft_init zeroes pre-vote tally state (pre_vote_in_progress/ pre_votes_granted/pre_vote_replies were left at stack garbage); push_config_to_standbys clears stale config acks before fan-out (repl_reset_config_acks) -- SHA-256-derived tags are not monotonic, so a previous push's ack numerically above the new tag fabricated a barrier quorum; capnpc-c's generated encode_* memsets the destination first (skipped Data fields fed garbage into capn_setp). Validation: asan profile 161/161 meson tests green (one known p2_integration -110 timing flake on first run, green on re-run); debug + release full builds OK; tarball smoke-tested on the build host. Cluster rollout on t1/t2/t3 follows. Co-Authored-By: Claude Code --- .gitignore | 10 + DEPS.md | 81 + Makefile | 43 + gaps.md | 168 + scripts/ci-ubuntu.sh | 47 + src/controller/config_repl.c | 7 + src/controller/meson.build | 7 +- src/controller/repl.c | 15 + .../testsuite/test_commit_barrier_rollout.c | 84 +- src/frontend/apiserver/meson.build | 29 +- src/harness/meson.build | 9 +- src/harness/testsuite/harness_test.c | 31 + src/harness/testsuite/test_test_cli.c | 12 + src/include/repl.h | 10 + src/lib/meson.build | 30 +- src/lib/raft/raft.c | 12 + src/meson.build | 17 +- src/meson.options | 2 + src/scheduler/meson.build | 2 +- src/scheduler/testsuite/meson.build | 9 +- src/subprojects/c-capnproto.wrap | 11 + .../c-capnproto/.github/workflows/ci.yml | 38 + src/subprojects/c-capnproto/.gitignore | 41 + src/subprojects/c-capnproto/.gitlab-ci.yml | 67 + src/subprojects/c-capnproto/.gitmodules | 0 src/subprojects/c-capnproto/.travis.yml | 20 + .../c-capnproto/.vscode/settings.json | 4 + src/subprojects/c-capnproto/CHANGES.md | 37 + src/subprojects/c-capnproto/CMakeLists.txt | 181 + src/subprojects/c-capnproto/CMakePresets.json | 306 + .../CMakeUserPresets-SUGGESTED.json | 86 + src/subprojects/c-capnproto/COPYING | 21 + src/subprojects/c-capnproto/CTestConfig.cmake | 1 + src/subprojects/c-capnproto/Makefile.am | 94 + src/subprojects/c-capnproto/README.md | 166 + src/subprojects/c-capnproto/ac/.gitignore | 2 + src/subprojects/c-capnproto/c-capnproto.pc.in | 12 + .../ci/ctest/Sanitizers-ASAN-CTest.cmake | 66 + .../ci/ctest/Sanitizers-UBSAN-CTest.cmake | 69 + .../c-capnproto/ci/gitlab/test.gitlab-ci.yml | 155 + .../c-capnproto/ci/run-with-msvc.cmd | 3 + .../c-capnproto/cmake/FindDkToolScripts.cmake | 187 + .../c-capnproto/compiler/c++.capnp | 26 + .../c-capnproto/compiler/c++.capnp.c | 10 + .../c-capnproto/compiler/c++.capnp.h | 35 + src/subprojects/c-capnproto/compiler/c.capnp | 69 + .../c-capnproto/compiler/c.capnp.c | 10 + .../c-capnproto/compiler/c.capnp.h | 35 + .../c-capnproto/compiler/capnpc-c.c | 2875 +++++ .../c-capnproto/compiler/schema-test.cpp | 203 + .../c-capnproto/compiler/schema.capnp | 477 + .../c-capnproto/compiler/schema.capnp.c | 1336 +++ .../c-capnproto/compiler/schema.capnp.h | 734 ++ src/subprojects/c-capnproto/compiler/str.c | 112 + src/subprojects/c-capnproto/compiler/str.h | 61 + .../c-capnproto/compiler/test.capnp | 661 + .../c-capnproto/compiler/test.capnp.c | 5434 +++++++++ .../c-capnproto/compiler/test.capnp.h | 2056 ++++ .../c-capnproto/compiler/update-notes.md | 18 + src/subprojects/c-capnproto/configure.ac | 53 + src/subprojects/c-capnproto/dk | 701 ++ src/subprojects/c-capnproto/dk.cmd | 146 + src/subprojects/c-capnproto/environment.yml | 7 + .../c-capnproto/examples/book/CMakeLists.txt | 44 + .../c-capnproto/examples/book/book.capnp | 42 + .../c-capnproto/examples/book/book.h | 49 + .../c-capnproto/examples/book/test.c | 147 + src/subprojects/c-capnproto/lib/capn-list.inc | 162 + src/subprojects/c-capnproto/lib/capn-malloc.c | 435 + src/subprojects/c-capnproto/lib/capn-stream.c | 217 + src/subprojects/c-capnproto/lib/capn.c | 1147 ++ src/subprojects/c-capnproto/lib/capnp_c.h | 461 + src/subprojects/c-capnproto/lib/capnp_priv.h | 62 + src/subprojects/c-capnproto/m4/.gitignore | 1 + src/subprojects/c-capnproto/meson.build | 130 + src/subprojects/c-capnproto/meson_options.txt | 1 + .../c-capnproto/subprojects/gtest.wrap | 15 + .../c-capnproto/tests/CMakeLists.txt | 48 + .../c-capnproto/tests/addressbook.capnp | 59 + .../c-capnproto/tests/addressbook.capnp.c | 200 + .../c-capnproto/tests/addressbook.capnp.h | 134 + .../c-capnproto/tests/capn-stream-test.cpp | 338 + .../c-capnproto/tests/capn-test.cpp | 454 + .../c-capnproto/tests/example-test.cpp | 165 + src/subprojects/c-capnproto/xmake.lua | 60 + src/subprojects/librtti.wrap | 10 + src/subprojects/librtti/.clang-format | 36 + src/subprojects/librtti/.gitignore | 2 + src/subprojects/librtti/LICENSE | 9 + src/subprojects/librtti/README.md | 3 + src/subprojects/librtti/examples/meson.build | 18 + src/subprojects/librtti/flake.lock | 131 + src/subprojects/librtti/flake.nix | 43 + src/subprojects/librtti/include/rtti.h | 7 + .../librtti/include/rtti/typeinfo.h | 272 + src/subprojects/librtti/meson.build | 18 + src/subprojects/librtti/meson.options | 1 + .../librtti/nixSupport/default.nix | 20 + .../librtti/nixSupport/librtti.nix | 35 + src/subprojects/librtti/src/attr.c | 41 + src/subprojects/librtti/src/bitmap.c | 77 + src/subprojects/librtti/src/create.c | 120 + src/subprojects/librtti/src/hash.c | 22 + src/subprojects/librtti/src/iter.c | 98 + src/subprojects/librtti/src/kv.c | 59 + src/subprojects/librtti/src/length.c | 23 + src/subprojects/librtti/src/lock.c | 42 + src/subprojects/librtti/src/meson.build | 68 + src/subprojects/librtti/src/ref.c | 41 + src/subprojects/librtti/src/str.c | 30 + src/subprojects/librtti/src/typeinfo.c | 27 + src/subprojects/librtti/src/varray.c | 168 + src/subprojects/librtti/testsuite/meson.build | 15 + src/subprojects/librtti/testsuite/test.c | 34 + src/subprojects/librtti/testsuite/test_attr.c | 119 + .../librtti/testsuite/test_invalid_obj.c | 26 + src/subprojects/librtti/testsuite/test_iter.c | 176 + .../packagefiles/c-capnproto.patch | 39 + .../packagefiles/c-capnproto/meson.build | 130 + src/subprojects/packagefiles/librtti.patch | 39 + .../packagefiles/packcc/meson.build | 15 + .../packagefiles/struct2json.patch | 33 + .../packagefiles/struct2json/cjson/cJSON.h | 13 + .../packagefiles/struct2json/cjson/s2j.h | 9 + .../packagefiles/struct2json/cjson/s2jdef.h | 9 + .../packagefiles/tinylog/meson.build | 43 + src/subprojects/packagefiles/unity.patch | 79 + .../packagefiles/unity/unity/unity.h | 698 ++ .../unity/unity/unity_internals.h | 1183 ++ src/subprojects/packcc.wrap | 9 + .../packcc/.github/workflows/testing.yml | 38 + src/subprojects/packcc/.gitignore | 11 + src/subprojects/packcc/LICENSE | 21 + src/subprojects/packcc/README.md | 936 ++ src/subprojects/packcc/benchmark/benchmark.sh | 190 + .../packcc/benchmark/grammars/calc.peg | 40 + .../packcc/benchmark/grammars/json.peg | 23 + .../packcc/benchmark/grammars/kotlin.peg | 452 + .../packcc/benchmark/inputs/calc.txt | 10000 ++++++++++++++++ .../packcc/benchmark/inputs/json.json | 9002 ++++++++++++++ .../packcc/benchmark/inputs/kotlin.kt | 1175 ++ src/subprojects/packcc/build/clang/Makefile | 58 + src/subprojects/packcc/build/gcc/Makefile | 58 + .../packcc/build/mingw-clang/Makefile | 58 + .../packcc/build/mingw-gcc/Makefile | 58 + .../build/msvc/examples/calc/calc.vcxproj | 206 + .../msvc/examples/calc/calc.vcxproj.filters | 22 + .../msvc/examples/calc/calc.vcxproj.user | 4 + src/subprojects/packcc/build/msvc/msvc.sln | 49 + .../packcc/build/msvc/packcc.vcxproj | 171 + .../packcc/build/msvc/packcc.vcxproj.filters | 22 + .../packcc/build/msvc/packcc.vcxproj.user | 4 + src/subprojects/packcc/examples/README.md | 13 + src/subprojects/packcc/examples/ast-calc.peg | 122 + .../packcc/examples/ast-tinyc/.gitignore | 1 + .../packcc/examples/ast-tinyc/CMakeLists.txt | 17 + .../packcc/examples/ast-tinyc/README.md | 142 + .../examples/ast-tinyc/inputs/erroneous1.c | 7 + .../examples/ast-tinyc/inputs/example1.c | 2 + .../examples/ast-tinyc/inputs/example2.c | 2 + .../examples/ast-tinyc/inputs/example3.c | 2 + .../examples/ast-tinyc/inputs/example4.c | 2 + .../examples/ast-tinyc/inputs/example5.c | 2 + .../packcc/examples/ast-tinyc/main.c | 53 + .../packcc/examples/ast-tinyc/parser.peg | 587 + .../packcc/examples/ast-tinyc/system.c | 482 + .../packcc/examples/ast-tinyc/system.h | 177 + .../packcc/examples/ast-tinyc/utility.c | 77 + .../packcc/examples/ast-tinyc/utility.h | 70 + src/subprojects/packcc/examples/calc.peg | 51 + src/subprojects/packcc/import/README.md | 12 + src/subprojects/packcc/import/char/README.md | 121 + .../import/char/ascii_character_group.peg | 35 + .../import/char/unicode_derived_core.peg | 34 + .../import/char/unicode_general_category.peg | 53 + src/subprojects/packcc/import/code/README.md | 310 + .../packcc/import/code/pcc_ast.peg | 413 + src/subprojects/packcc/meson.build | 15 + src/subprojects/packcc/misc/README.md | 37 + .../packcc/misc/unicode_derived_core.py | 118 + .../packcc/misc/unicode_general_category.py | 141 + src/subprojects/packcc/src/packcc.c | 5877 +++++++++ src/subprojects/packcc/tests/.gitignore | 10 + src/subprojects/packcc/tests/README.md | 87 + .../packcc/tests/ascii.d/ascii.bats | 19 + .../packcc/tests/ascii.d/expected.txt | 4 + .../packcc/tests/ascii.d/input.peg | 3 + .../packcc/tests/ascii.d/input.txt | 1 + .../packcc/tests/ast-calc.d/ast-calc.bats | 15 + .../packcc/tests/ast-calc.d/expected.txt | 26 + .../packcc/tests/ast-calc.d/input.txt | 2 + .../packcc/tests/basic.d/expected.txt | 4 + .../packcc/tests/basic.d/input.peg | 3 + .../packcc/tests/basic.d/input.txt | 1 + src/subprojects/packcc/tests/calc.d/calc.bats | 15 + .../packcc/tests/calc.d/expected.txt | 4 + src/subprojects/packcc/tests/calc.d/input.txt | 4 + .../packcc/tests/captures.d/expected.txt | 7 + .../packcc/tests/captures.d/input.peg | 13 + .../packcc/tests/captures.d/input.txt | 7 + .../tests/character_classes_0.d/expected.txt | 8 + .../tests/character_classes_0.d/input.peg | 9 + .../tests/character_classes_0.d/input.txt | 1 + .../character_classes_1.d/expected-utf8.txt | 3 + .../tests/character_classes_1.d/expected.txt | 23 + .../character_classes_1.d/input-utf8.txt | 1 + .../tests/character_classes_1.d/input.peg | 32 + .../tests/character_classes_1.d/input.txt | 4 + .../tests/character_classes_2.d/expected.txt | 8 + .../tests/character_classes_2.d/input.peg | 9 + .../tests/character_classes_2.d/input.txt | 1 + .../tests/code_generation.d/generation.bats | 108 + .../packcc/tests/code_generation.d/input.peg | 31 + .../packcc/tests/code_generation.d/main.c | 9 + .../tests/code_line_continuation.d/dump.bats | 8 + .../code_line_continuation.d/expected.txt | 9 + .../tests/code_line_continuation.d/input.peg | 13 + .../packcc/tests/debug_macro.d/expected.txt | 64 + .../packcc/tests/debug_macro.d/input.peg | 14 + .../packcc/tests/debug_macro.d/input.txt | 2 + src/subprojects/packcc/tests/dump.d/dump.bats | 8 + .../packcc/tests/dump.d/expected.txt | 163 + .../packcc/tests/error_action.d/expected.txt | 8 + .../packcc/tests/error_action.d/input.peg | 17 + .../packcc/tests/error_action.d/input.txt | 8 + .../escape_sequences.d/expected-hex-0.txt | 1 + .../escape_sequences.d/expected-unicode-0.txt | 1 + .../escape_sequences.d/expected-unicode-1.txt | 1 + .../tests/escape_sequences.d/input-hex-0.txt | 1 + .../escape_sequences.d/input-unicode-0.txt | 1 + .../escape_sequences.d/input-unicode-1.txt | 1 + .../packcc/tests/escape_sequences.d/input.peg | 6 + .../packcc/tests/import.d/.gitignore | 2 + .../tests/import.d/check_line_number.py | 76 + .../packcc/tests/import.d/import.bats | 543 + .../packcc/tests/import.d/make_input.py | 48 + .../packcc/tests/import.d/reference.peg | 526 + .../packcc/tests/import.d/template.peg | 37 + .../tests/import_char.d/import_char.bats | 8 + .../packcc/tests/import_char.d/input.peg | 3 + .../packcc/tests/issue_28.d/expected.txt | 3 + .../packcc/tests/issue_28.d/input.peg | 9 + .../packcc/tests/issue_28.d/input.txt | 2 + .../packcc/tests/issue_78.d/input.peg | 1 + .../packcc/tests/issue_78.d/issue_78.bats | 9 + .../packcc/tests/lines.d/input.peg | 33 + .../packcc/tests/lines.d/lines.bats | 118 + src/subprojects/packcc/tests/main.c | 20 + .../tests/negative_predicate.d/expected.txt | 4 + .../tests/negative_predicate.d/input.peg | 4 + .../tests/negative_predicate.d/input.txt | 4 + .../packcc/tests/position.d/expected.txt | 2 + .../packcc/tests/position.d/input.peg | 6 + .../packcc/tests/position.d/input.txt | 1 + .../tests/positive_predicate.d/expected.txt | 4 + .../tests/positive_predicate.d/input.peg | 4 + .../tests/positive_predicate.d/input.txt | 4 + .../expected-optional-repeatable.txt | 4 + .../tests/quantifiers.d/expected-optional.txt | 2 + .../quantifiers.d/expected-repeatable.txt | 3 + .../input-optional-repeatable.txt | 4 + .../tests/quantifiers.d/input-optional.txt | 2 + .../tests/quantifiers.d/input-repeatable.txt | 3 + .../packcc/tests/quantifiers.d/input.peg | 6 + .../tests/strings.d/expected-escapes.txt | 1 + .../packcc/tests/strings.d/expected-utf8.txt | 3 + .../packcc/tests/strings.d/expected.txt | 2 + .../packcc/tests/strings.d/input-escapes.txt | 1 + .../packcc/tests/strings.d/input-utf8.txt | 1 + .../packcc/tests/strings.d/input.peg | 7 + .../packcc/tests/strings.d/input.txt | 1 + .../packcc/tests/style.d/style.bats | 34 + .../tests/substitution.d/expected.c.txt | 83 + .../tests/substitution.d/expected.h.txt | 40 + .../packcc/tests/substitution.d/input.peg | 134 + .../packcc/tests/substitution.d/subst.bats | 13 + src/subprojects/packcc/tests/test.sh | 74 + src/subprojects/packcc/tests/uncrustify.cfg | 3128 +++++ .../tests/unused_rule_elimination.d/dump.bats | 8 + .../unused_rule_elimination.d/expected.txt | 163 + .../tests/unused_rule_elimination.d/input.peg | 35 + src/subprojects/packcc/tests/utils.sh | 28 + src/subprojects/struct2json.wrap | 10 + src/subprojects/struct2json/.gitattributes | 40 + src/subprojects/struct2json/LICENSE | 23 + src/subprojects/struct2json/README.md | 84 + src/subprojects/struct2json/cJSON/cJSON.c | 3202 +++++ src/subprojects/struct2json/cJSON/cJSON.h | 297 + .../struct2json/cJSON/cJSON_Utils.c | 1498 +++ .../struct2json/cJSON/cJSON_Utils.h | 88 + src/subprojects/struct2json/cjson/cJSON.h | 13 + src/subprojects/struct2json/cjson/s2j.h | 9 + src/subprojects/struct2json/cjson/s2jdef.h | 9 + .../struct2json/demo/error_print.txt | 10 + .../struct2json/demo/generate_s2j_code.py | 296 + .../demo/generate_struct_defination.py | 41 + .../struct2json/demo/inc/mc_usr_def.h | 101 + src/subprojects/struct2json/demo/main.c | 138 + .../struct2json/demo/my_struct_2_json.c | 232 + .../struct2json/demo/my_struct_2_json.h | 23 + .../struct2json/demo/my_struct_2_json.inc | 131 + .../struct2json/demo/struct_defination.json | 140 + .../struct2json/demo/struct_defination.txt | 43 + src/subprojects/struct2json/demo/tests2j | Bin 0 -> 89040 bytes src/subprojects/struct2json/docs/README.md | 4 + src/subprojects/struct2json/docs/readme.md | 4 + src/subprojects/struct2json/docs/zh/api.md | 194 + .../docs/zh/assets/not_use_struct2json.c | 30 + .../zh/assets/not_use_struct2json_for_json.c | 46 + .../docs/zh/assets/used_struct2json.c | 19 + .../zh/assets/used_struct2json_for_json.c | 17 + .../docs/zh/images/not_use_struct2json.png | Bin 0 -> 85919 bytes .../images/not_use_struct2json_for_json.png | Bin 0 -> 71583 bytes .../docs/zh/images/used_struct2json.png | Bin 0 -> 59204 bytes .../zh/images/used_struct2json_for_json.png | Bin 0 -> 41961 bytes src/subprojects/struct2json/docs/zh/readme.md | 3 + src/subprojects/struct2json/meson.build | 57 + .../struct2json/struct2json/inc/s2j.h | 113 + .../struct2json/struct2json/inc/s2jdef.h | 286 + .../struct2json/struct2json/src/s2j.c | 52 + src/subprojects/tinylog.wrap | 9 + src/subprojects/tinylog/.clang-format | 2 + src/subprojects/tinylog/.gitignore | 5 + src/subprojects/tinylog/CMakeLists.txt | 13 + src/subprojects/tinylog/LICENSE | 22 + src/subprojects/tinylog/README.md | 266 + src/subprojects/tinylog/README_zh-CN.md | 268 + .../tinylog/example/CMakeLists.txt | 10 + src/subprojects/tinylog/example/Makefile | 18 + src/subprojects/tinylog/example/example.cpp | 33 + src/subprojects/tinylog/makefile | 13 + src/subprojects/tinylog/meson.build | 43 + src/subprojects/tinylog/test/Makefile | 20 + src/subprojects/tinylog/test/test.c | 70 + src/subprojects/tinylog/tlog.c | 2224 ++++ src/subprojects/tinylog/tlog.h | 363 + src/subprojects/unity.wrap | 10 + src/subprojects/unity/.editorconfig | 27 + src/subprojects/unity/.gitattributes | 31 + .../unity/.github/workflows/main.yml | 35 + src/subprojects/unity/.gitignore | 19 + src/subprojects/unity/CMakeLists.txt | 172 + src/subprojects/unity/LICENSE.txt | 21 + src/subprojects/unity/README.md | 234 + src/subprojects/unity/auto/__init__.py | 7 + src/subprojects/unity/auto/colour_prompt.rb | 120 + src/subprojects/unity/auto/colour_reporter.rb | 40 + src/subprojects/unity/auto/extract_version.py | 22 + .../unity/auto/generate_config.yml | 43 + src/subprojects/unity/auto/generate_module.rb | 318 + .../unity/auto/generate_test_runner.rb | 547 + src/subprojects/unity/auto/parse_output.rb | 390 + src/subprojects/unity/auto/run_test.erb | 37 + .../unity/auto/stylize_as_junit.py | 161 + .../unity/auto/stylize_as_junit.rb | 253 + .../unity/auto/test_file_filter.rb | 28 + src/subprojects/unity/auto/type_sanitizer.rb | 13 + .../unity/auto/unity_test_summary.py | 140 + .../unity/auto/unity_test_summary.rb | 140 + src/subprojects/unity/auto/yaml_helper.rb | 23 + src/subprojects/unity/docs/CODE_OF_CONDUCT.md | 138 + src/subprojects/unity/docs/CONTRIBUTING.md | 238 + .../unity/docs/MesonGeneratorRunner.md | 18 + .../docs/ThrowTheSwitchCodingStandard.md | 187 + ...tSuitableforPrintingandPossiblyFraming.pdf | Bin 0 -> 144467 bytes .../unity/docs/UnityAssertionsReference.md | 860 ++ src/subprojects/unity/docs/UnityChangeLog.md | 110 + .../unity/docs/UnityConfigurationGuide.md | 654 + .../unity/docs/UnityGettingStartedGuide.md | 242 + .../unity/docs/UnityHelperScriptsGuide.md | 533 + .../unity/docs/UnityKnownIssues.md | 13 + .../unity/examples/example_1/makefile | 73 + .../unity/examples/example_1/meson.build | 48 + .../unity/examples/example_1/readme.txt | 12 + .../examples/example_1/src/ProductionCode.c | 30 + .../examples/example_1/src/ProductionCode.h | 9 + .../examples/example_1/src/ProductionCode2.c | 17 + .../examples/example_1/src/ProductionCode2.h | 8 + .../examples/example_1/subprojects/unity.wrap | 3 + .../example_1/test/TestProductionCode.c | 68 + .../example_1/test/TestProductionCode2.c | 37 + .../test_runners/TestProductionCode2_Runner.c | 53 + .../test_runners/TestProductionCode_Runner.c | 57 + .../unity/examples/example_2/makefile | 72 + .../unity/examples/example_2/readme.txt | 5 + .../examples/example_2/src/ProductionCode.c | 30 + .../examples/example_2/src/ProductionCode.h | 9 + .../examples/example_2/src/ProductionCode2.c | 17 + .../examples/example_2/src/ProductionCode2.h | 8 + .../example_2/test/TestProductionCode.c | 71 + .../example_2/test/TestProductionCode2.c | 40 + .../test_runners/TestProductionCode2_Runner.c | 16 + .../test_runners/TestProductionCode_Runner.c | 18 + .../example_2/test/test_runners/all_tests.c | 19 + .../examples/example_3/helper/UnityHelper.c | 17 + .../examples/example_3/helper/UnityHelper.h | 19 + .../unity/examples/example_3/rakefile.rb | 45 + .../examples/example_3/rakefile_helper.rb | 255 + .../unity/examples/example_3/readme.txt | 13 + .../examples/example_3/src/ProductionCode.c | 30 + .../examples/example_3/src/ProductionCode.h | 9 + .../examples/example_3/src/ProductionCode2.c | 17 + .../examples/example_3/src/ProductionCode2.h | 8 + .../examples/example_3/target_gcc_32.yml | 54 + .../example_3/test/TestProductionCode.c | 68 + .../example_3/test/TestProductionCode2.c | 37 + .../unity/examples/example_4/meson.build | 12 + .../unity/examples/example_4/readme.txt | 15 + .../examples/example_4/src/ProductionCode.c | 30 + .../examples/example_4/src/ProductionCode.h | 9 + .../examples/example_4/src/ProductionCode2.c | 17 + .../examples/example_4/src/ProductionCode2.h | 8 + .../unity/examples/example_4/src/meson.build | 16 + .../examples/example_4/subprojects/unity.wrap | 6 + .../example_4/test/TestProductionCode.c | 69 + .../example_4/test/TestProductionCode2.c | 41 + .../unity/examples/example_4/test/meson.build | 7 + .../test_runners/TestProductionCode2_Runner.c | 53 + .../test_runners/TestProductionCode_Runner.c | 57 + .../example_4/test/test_runners/meson.build | 13 + src/subprojects/unity/examples/unity_config.h | 251 + src/subprojects/unity/extras/bdd/readme.md | 40 + .../unity/extras/bdd/src/unity_bdd.h | 44 + .../unity/extras/bdd/test/meson.build | 9 + .../unity/extras/bdd/test/test_bdd.c | 129 + .../unity/extras/eclipse/error_parsers.txt | 26 + .../unity/extras/fixture/readme.md | 26 + .../unity/extras/fixture/src/meson.build | 10 + .../unity/extras/fixture/src/unity_fixture.c | 310 + .../unity/extras/fixture/src/unity_fixture.h | 94 + .../fixture/src/unity_fixture_internals.h | 50 + .../unity/extras/fixture/test/main/AllTests.c | 20 + .../fixture/test/template_fixture_tests.c | 39 + .../extras/fixture/test/unity_fixture_Test.c | 245 + .../fixture/test/unity_fixture_TestRunner.c | 32 + src/subprojects/unity/extras/memory/readme.md | 42 + .../unity/extras/memory/src/meson.build | 9 + .../unity/extras/memory/src/unity_memory.c | 203 + .../unity/extras/memory/src/unity_memory.h | 61 + .../extras/memory/test/unity_memory_Test.c | 326 + .../memory/test/unity_memory_TestRunner.c | 50 + .../extras/memory/test/unity_output_Spy.c | 57 + .../extras/memory/test/unity_output_Spy.h | 17 + src/subprojects/unity/library.json | 25 + src/subprojects/unity/meson.build | 89 + src/subprojects/unity/meson_options.txt | 3 + src/subprojects/unity/platformio-build.py | 24 + src/subprojects/unity/src/meson.build | 17 + src/subprojects/unity/src/unity.c | 2501 ++++ src/subprojects/unity/src/unity.h | 698 ++ src/subprojects/unity/src/unity_internals.h | 1183 ++ src/subprojects/unity/test/.rubocop.yml | 83 + .../unity/test/expectdata/testsample_cmd.c | 61 + .../unity/test/expectdata/testsample_def.c | 57 + .../unity/test/expectdata/testsample_head1.c | 55 + .../unity/test/expectdata/testsample_head1.h | 15 + .../test/expectdata/testsample_mock_cmd.c | 80 + .../test/expectdata/testsample_mock_def.c | 76 + .../test/expectdata/testsample_mock_head1.c | 75 + .../test/expectdata/testsample_mock_head1.h | 13 + .../test/expectdata/testsample_mock_new1.c | 89 + .../test/expectdata/testsample_mock_new2.c | 89 + .../test/expectdata/testsample_mock_param.c | 77 + .../test/expectdata/testsample_mock_run1.c | 89 + .../test/expectdata/testsample_mock_run2.c | 89 + .../test/expectdata/testsample_mock_yaml.c | 90 + .../unity/test/expectdata/testsample_new1.c | 67 + .../unity/test/expectdata/testsample_new2.c | 70 + .../unity/test/expectdata/testsample_param.c | 58 + .../unity/test/expectdata/testsample_run1.c | 67 + .../unity/test/expectdata/testsample_run2.c | 70 + .../unity/test/expectdata/testsample_yaml.c | 71 + src/subprojects/unity/test/rakefile | 164 + src/subprojects/unity/test/rakefile_helper.rb | 316 + .../generate_module_existing_file_spec.rb | 164 + src/subprojects/unity/test/targets/ansi.yml | 51 + .../unity/test/targets/clang_file.yml | 79 + .../unity/test/targets/clang_strict.yml | 79 + src/subprojects/unity/test/targets/gcc_32.yml | 52 + src/subprojects/unity/test/targets/gcc_64.yml | 53 + .../unity/test/targets/gcc_auto_limits.yml | 50 + .../unity/test/targets/gcc_auto_stdint.yml | 62 + .../unity/test/targets/gcc_manual_math.yml | 50 + .../unity/test/targets/hitech_picc18.yml | 98 + .../unity/test/targets/iar_arm_v4.yml | 105 + .../unity/test/targets/iar_arm_v5.yml | 99 + .../unity/test/targets/iar_arm_v5_3.yml | 99 + .../targets/iar_armcortex_LM3S9B92_v5_4.yml | 97 + .../unity/test/targets/iar_cortexm3_v5.yml | 101 + .../unity/test/targets/iar_msp430.yml | 119 + .../unity/test/targets/iar_sh2a_v6.yml | 106 + .../unity/test/testdata/CException.h | 18 + src/subprojects/unity/test/testdata/Defs.h | 16 + src/subprojects/unity/test/testdata/cmock.h | 21 + .../unity/test/testdata/mockMock.h | 20 + .../unity/test/testdata/testRunnerGenerator.c | 204 + .../test/testdata/testRunnerGeneratorSmall.c | 73 + .../testdata/testRunnerGeneratorWithMocks.c | 200 + .../unity/test/tests/self_assessment_utils.h | 151 + .../test/tests/test_generate_test_runner.rb | 1341 +++ .../unity/test/tests/test_unity_arrays.c | 2941 +++++ .../unity/test/tests/test_unity_core.c | 375 + .../unity/test/tests/test_unity_doubles.c | 1285 ++ .../unity/test/tests/test_unity_floats.c | 1395 +++ .../unity/test/tests/test_unity_integers.c | 2863 +++++ .../unity/test/tests/test_unity_integers_64.c | 783 ++ .../unity/test/tests/test_unity_memory.c | 82 + .../test/tests/test_unity_parameterized.c | 309 + .../test/tests/test_unity_parameterizedDemo.c | 28 + .../unity/test/tests/test_unity_strings.c | 330 + .../unity/test/tests/types_for_test.h | 21 + src/subprojects/unity/unity/unity.h | 698 ++ src/subprojects/unity/unity/unity_internals.h | 1183 ++ src/subprojects/unity/unityConfig.cmake | 1 + src/tools/go_build | 5 + src/tools/xce-build.sh | 52 +- src/tools/xce-package.sh | 232 + src/worker/meson.build | 21 +- src/worker/testsuite/meson.build | 9 +- src/xceadmin/meson-build.sh | 31 +- src/xceadmin/requirements-build.txt | 11 + 521 files changed, 106066 insertions(+), 83 deletions(-) create mode 100644 DEPS.md create mode 100644 Makefile create mode 100644 gaps.md create mode 100755 scripts/ci-ubuntu.sh create mode 100644 src/subprojects/c-capnproto.wrap create mode 100644 src/subprojects/c-capnproto/.github/workflows/ci.yml create mode 100644 src/subprojects/c-capnproto/.gitignore create mode 100644 src/subprojects/c-capnproto/.gitlab-ci.yml create mode 100644 src/subprojects/c-capnproto/.gitmodules create mode 100644 src/subprojects/c-capnproto/.travis.yml create mode 100644 src/subprojects/c-capnproto/.vscode/settings.json create mode 100644 src/subprojects/c-capnproto/CHANGES.md create mode 100644 src/subprojects/c-capnproto/CMakeLists.txt create mode 100644 src/subprojects/c-capnproto/CMakePresets.json create mode 100644 src/subprojects/c-capnproto/CMakeUserPresets-SUGGESTED.json create mode 100644 src/subprojects/c-capnproto/COPYING create mode 100644 src/subprojects/c-capnproto/CTestConfig.cmake create mode 100644 src/subprojects/c-capnproto/Makefile.am create mode 100644 src/subprojects/c-capnproto/README.md create mode 100644 src/subprojects/c-capnproto/ac/.gitignore create mode 100644 src/subprojects/c-capnproto/c-capnproto.pc.in create mode 100644 src/subprojects/c-capnproto/ci/ctest/Sanitizers-ASAN-CTest.cmake create mode 100644 src/subprojects/c-capnproto/ci/ctest/Sanitizers-UBSAN-CTest.cmake create mode 100644 src/subprojects/c-capnproto/ci/gitlab/test.gitlab-ci.yml create mode 100644 src/subprojects/c-capnproto/ci/run-with-msvc.cmd create mode 100644 src/subprojects/c-capnproto/cmake/FindDkToolScripts.cmake create mode 100644 src/subprojects/c-capnproto/compiler/c++.capnp create mode 100644 src/subprojects/c-capnproto/compiler/c++.capnp.c create mode 100644 src/subprojects/c-capnproto/compiler/c++.capnp.h create mode 100644 src/subprojects/c-capnproto/compiler/c.capnp create mode 100644 src/subprojects/c-capnproto/compiler/c.capnp.c create mode 100644 src/subprojects/c-capnproto/compiler/c.capnp.h create mode 100644 src/subprojects/c-capnproto/compiler/capnpc-c.c create mode 100644 src/subprojects/c-capnproto/compiler/schema-test.cpp create mode 100644 src/subprojects/c-capnproto/compiler/schema.capnp create mode 100644 src/subprojects/c-capnproto/compiler/schema.capnp.c create mode 100644 src/subprojects/c-capnproto/compiler/schema.capnp.h create mode 100644 src/subprojects/c-capnproto/compiler/str.c create mode 100644 src/subprojects/c-capnproto/compiler/str.h create mode 100644 src/subprojects/c-capnproto/compiler/test.capnp create mode 100644 src/subprojects/c-capnproto/compiler/test.capnp.c create mode 100644 src/subprojects/c-capnproto/compiler/test.capnp.h create mode 100755 src/subprojects/c-capnproto/compiler/update-notes.md create mode 100755 src/subprojects/c-capnproto/configure.ac create mode 100755 src/subprojects/c-capnproto/dk create mode 100755 src/subprojects/c-capnproto/dk.cmd create mode 100644 src/subprojects/c-capnproto/environment.yml create mode 100644 src/subprojects/c-capnproto/examples/book/CMakeLists.txt create mode 100644 src/subprojects/c-capnproto/examples/book/book.capnp create mode 100644 src/subprojects/c-capnproto/examples/book/book.h create mode 100644 src/subprojects/c-capnproto/examples/book/test.c create mode 100644 src/subprojects/c-capnproto/lib/capn-list.inc create mode 100644 src/subprojects/c-capnproto/lib/capn-malloc.c create mode 100644 src/subprojects/c-capnproto/lib/capn-stream.c create mode 100644 src/subprojects/c-capnproto/lib/capn.c create mode 100644 src/subprojects/c-capnproto/lib/capnp_c.h create mode 100644 src/subprojects/c-capnproto/lib/capnp_priv.h create mode 100644 src/subprojects/c-capnproto/m4/.gitignore create mode 100644 src/subprojects/c-capnproto/meson.build create mode 100644 src/subprojects/c-capnproto/meson_options.txt create mode 100644 src/subprojects/c-capnproto/subprojects/gtest.wrap create mode 100644 src/subprojects/c-capnproto/tests/CMakeLists.txt create mode 100644 src/subprojects/c-capnproto/tests/addressbook.capnp create mode 100644 src/subprojects/c-capnproto/tests/addressbook.capnp.c create mode 100644 src/subprojects/c-capnproto/tests/addressbook.capnp.h create mode 100644 src/subprojects/c-capnproto/tests/capn-stream-test.cpp create mode 100644 src/subprojects/c-capnproto/tests/capn-test.cpp create mode 100644 src/subprojects/c-capnproto/tests/example-test.cpp create mode 100644 src/subprojects/c-capnproto/xmake.lua create mode 100644 src/subprojects/librtti.wrap create mode 100644 src/subprojects/librtti/.clang-format create mode 100644 src/subprojects/librtti/.gitignore create mode 100644 src/subprojects/librtti/LICENSE create mode 100644 src/subprojects/librtti/README.md create mode 100644 src/subprojects/librtti/examples/meson.build create mode 100644 src/subprojects/librtti/flake.lock create mode 100644 src/subprojects/librtti/flake.nix create mode 100644 src/subprojects/librtti/include/rtti.h create mode 100644 src/subprojects/librtti/include/rtti/typeinfo.h create mode 100644 src/subprojects/librtti/meson.build create mode 100644 src/subprojects/librtti/meson.options create mode 100644 src/subprojects/librtti/nixSupport/default.nix create mode 100644 src/subprojects/librtti/nixSupport/librtti.nix create mode 100644 src/subprojects/librtti/src/attr.c create mode 100644 src/subprojects/librtti/src/bitmap.c create mode 100644 src/subprojects/librtti/src/create.c create mode 100644 src/subprojects/librtti/src/hash.c create mode 100644 src/subprojects/librtti/src/iter.c create mode 100644 src/subprojects/librtti/src/kv.c create mode 100644 src/subprojects/librtti/src/length.c create mode 100644 src/subprojects/librtti/src/lock.c create mode 100644 src/subprojects/librtti/src/meson.build create mode 100644 src/subprojects/librtti/src/ref.c create mode 100644 src/subprojects/librtti/src/str.c create mode 100644 src/subprojects/librtti/src/typeinfo.c create mode 100644 src/subprojects/librtti/src/varray.c create mode 100644 src/subprojects/librtti/testsuite/meson.build create mode 100644 src/subprojects/librtti/testsuite/test.c create mode 100644 src/subprojects/librtti/testsuite/test_attr.c create mode 100644 src/subprojects/librtti/testsuite/test_invalid_obj.c create mode 100644 src/subprojects/librtti/testsuite/test_iter.c create mode 100644 src/subprojects/packagefiles/c-capnproto.patch create mode 100644 src/subprojects/packagefiles/c-capnproto/meson.build create mode 100644 src/subprojects/packagefiles/librtti.patch create mode 100644 src/subprojects/packagefiles/packcc/meson.build create mode 100644 src/subprojects/packagefiles/struct2json.patch create mode 100644 src/subprojects/packagefiles/struct2json/cjson/cJSON.h create mode 100644 src/subprojects/packagefiles/struct2json/cjson/s2j.h create mode 100644 src/subprojects/packagefiles/struct2json/cjson/s2jdef.h create mode 100644 src/subprojects/packagefiles/tinylog/meson.build create mode 100644 src/subprojects/packagefiles/unity.patch create mode 100644 src/subprojects/packagefiles/unity/unity/unity.h create mode 100644 src/subprojects/packagefiles/unity/unity/unity_internals.h create mode 100644 src/subprojects/packcc.wrap create mode 100644 src/subprojects/packcc/.github/workflows/testing.yml create mode 100644 src/subprojects/packcc/.gitignore create mode 100644 src/subprojects/packcc/LICENSE create mode 100644 src/subprojects/packcc/README.md create mode 100755 src/subprojects/packcc/benchmark/benchmark.sh create mode 100644 src/subprojects/packcc/benchmark/grammars/calc.peg create mode 100644 src/subprojects/packcc/benchmark/grammars/json.peg create mode 100644 src/subprojects/packcc/benchmark/grammars/kotlin.peg create mode 100644 src/subprojects/packcc/benchmark/inputs/calc.txt create mode 100644 src/subprojects/packcc/benchmark/inputs/json.json create mode 100644 src/subprojects/packcc/benchmark/inputs/kotlin.kt create mode 100644 src/subprojects/packcc/build/clang/Makefile create mode 100644 src/subprojects/packcc/build/gcc/Makefile create mode 100644 src/subprojects/packcc/build/mingw-clang/Makefile create mode 100644 src/subprojects/packcc/build/mingw-gcc/Makefile create mode 100644 src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj create mode 100644 src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj.filters create mode 100644 src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj.user create mode 100644 src/subprojects/packcc/build/msvc/msvc.sln create mode 100644 src/subprojects/packcc/build/msvc/packcc.vcxproj create mode 100644 src/subprojects/packcc/build/msvc/packcc.vcxproj.filters create mode 100644 src/subprojects/packcc/build/msvc/packcc.vcxproj.user create mode 100644 src/subprojects/packcc/examples/README.md create mode 100644 src/subprojects/packcc/examples/ast-calc.peg create mode 100644 src/subprojects/packcc/examples/ast-tinyc/.gitignore create mode 100644 src/subprojects/packcc/examples/ast-tinyc/CMakeLists.txt create mode 100644 src/subprojects/packcc/examples/ast-tinyc/README.md create mode 100644 src/subprojects/packcc/examples/ast-tinyc/inputs/erroneous1.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/inputs/example1.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/inputs/example2.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/inputs/example3.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/inputs/example4.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/inputs/example5.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/main.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/parser.peg create mode 100644 src/subprojects/packcc/examples/ast-tinyc/system.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/system.h create mode 100644 src/subprojects/packcc/examples/ast-tinyc/utility.c create mode 100644 src/subprojects/packcc/examples/ast-tinyc/utility.h create mode 100644 src/subprojects/packcc/examples/calc.peg create mode 100644 src/subprojects/packcc/import/README.md create mode 100644 src/subprojects/packcc/import/char/README.md create mode 100644 src/subprojects/packcc/import/char/ascii_character_group.peg create mode 100644 src/subprojects/packcc/import/char/unicode_derived_core.peg create mode 100644 src/subprojects/packcc/import/char/unicode_general_category.peg create mode 100644 src/subprojects/packcc/import/code/README.md create mode 100644 src/subprojects/packcc/import/code/pcc_ast.peg create mode 100644 src/subprojects/packcc/meson.build create mode 100644 src/subprojects/packcc/misc/README.md create mode 100644 src/subprojects/packcc/misc/unicode_derived_core.py create mode 100644 src/subprojects/packcc/misc/unicode_general_category.py create mode 100644 src/subprojects/packcc/src/packcc.c create mode 100644 src/subprojects/packcc/tests/.gitignore create mode 100644 src/subprojects/packcc/tests/README.md create mode 100644 src/subprojects/packcc/tests/ascii.d/ascii.bats create mode 100644 src/subprojects/packcc/tests/ascii.d/expected.txt create mode 100644 src/subprojects/packcc/tests/ascii.d/input.peg create mode 100644 src/subprojects/packcc/tests/ascii.d/input.txt create mode 100644 src/subprojects/packcc/tests/ast-calc.d/ast-calc.bats create mode 100644 src/subprojects/packcc/tests/ast-calc.d/expected.txt create mode 100644 src/subprojects/packcc/tests/ast-calc.d/input.txt create mode 100644 src/subprojects/packcc/tests/basic.d/expected.txt create mode 100644 src/subprojects/packcc/tests/basic.d/input.peg create mode 100644 src/subprojects/packcc/tests/basic.d/input.txt create mode 100644 src/subprojects/packcc/tests/calc.d/calc.bats create mode 100644 src/subprojects/packcc/tests/calc.d/expected.txt create mode 100644 src/subprojects/packcc/tests/calc.d/input.txt create mode 100644 src/subprojects/packcc/tests/captures.d/expected.txt create mode 100644 src/subprojects/packcc/tests/captures.d/input.peg create mode 100644 src/subprojects/packcc/tests/captures.d/input.txt create mode 100644 src/subprojects/packcc/tests/character_classes_0.d/expected.txt create mode 100644 src/subprojects/packcc/tests/character_classes_0.d/input.peg create mode 100644 src/subprojects/packcc/tests/character_classes_0.d/input.txt create mode 100644 src/subprojects/packcc/tests/character_classes_1.d/expected-utf8.txt create mode 100644 src/subprojects/packcc/tests/character_classes_1.d/expected.txt create mode 100644 src/subprojects/packcc/tests/character_classes_1.d/input-utf8.txt create mode 100644 src/subprojects/packcc/tests/character_classes_1.d/input.peg create mode 100644 src/subprojects/packcc/tests/character_classes_1.d/input.txt create mode 100644 src/subprojects/packcc/tests/character_classes_2.d/expected.txt create mode 100644 src/subprojects/packcc/tests/character_classes_2.d/input.peg create mode 100644 src/subprojects/packcc/tests/character_classes_2.d/input.txt create mode 100644 src/subprojects/packcc/tests/code_generation.d/generation.bats create mode 100644 src/subprojects/packcc/tests/code_generation.d/input.peg create mode 100644 src/subprojects/packcc/tests/code_generation.d/main.c create mode 100644 src/subprojects/packcc/tests/code_line_continuation.d/dump.bats create mode 100644 src/subprojects/packcc/tests/code_line_continuation.d/expected.txt create mode 100644 src/subprojects/packcc/tests/code_line_continuation.d/input.peg create mode 100644 src/subprojects/packcc/tests/debug_macro.d/expected.txt create mode 100644 src/subprojects/packcc/tests/debug_macro.d/input.peg create mode 100644 src/subprojects/packcc/tests/debug_macro.d/input.txt create mode 100644 src/subprojects/packcc/tests/dump.d/dump.bats create mode 100644 src/subprojects/packcc/tests/dump.d/expected.txt create mode 100644 src/subprojects/packcc/tests/error_action.d/expected.txt create mode 100644 src/subprojects/packcc/tests/error_action.d/input.peg create mode 100644 src/subprojects/packcc/tests/error_action.d/input.txt create mode 100644 src/subprojects/packcc/tests/escape_sequences.d/expected-hex-0.txt create mode 100644 src/subprojects/packcc/tests/escape_sequences.d/expected-unicode-0.txt create mode 100644 src/subprojects/packcc/tests/escape_sequences.d/expected-unicode-1.txt create mode 100644 src/subprojects/packcc/tests/escape_sequences.d/input-hex-0.txt create mode 100644 src/subprojects/packcc/tests/escape_sequences.d/input-unicode-0.txt create mode 100644 src/subprojects/packcc/tests/escape_sequences.d/input-unicode-1.txt create mode 100644 src/subprojects/packcc/tests/escape_sequences.d/input.peg create mode 100644 src/subprojects/packcc/tests/import.d/.gitignore create mode 100644 src/subprojects/packcc/tests/import.d/check_line_number.py create mode 100644 src/subprojects/packcc/tests/import.d/import.bats create mode 100644 src/subprojects/packcc/tests/import.d/make_input.py create mode 100644 src/subprojects/packcc/tests/import.d/reference.peg create mode 100644 src/subprojects/packcc/tests/import.d/template.peg create mode 100644 src/subprojects/packcc/tests/import_char.d/import_char.bats create mode 100644 src/subprojects/packcc/tests/import_char.d/input.peg create mode 100644 src/subprojects/packcc/tests/issue_28.d/expected.txt create mode 100644 src/subprojects/packcc/tests/issue_28.d/input.peg create mode 100644 src/subprojects/packcc/tests/issue_28.d/input.txt create mode 100644 src/subprojects/packcc/tests/issue_78.d/input.peg create mode 100644 src/subprojects/packcc/tests/issue_78.d/issue_78.bats create mode 100644 src/subprojects/packcc/tests/lines.d/input.peg create mode 100644 src/subprojects/packcc/tests/lines.d/lines.bats create mode 100644 src/subprojects/packcc/tests/main.c create mode 100644 src/subprojects/packcc/tests/negative_predicate.d/expected.txt create mode 100644 src/subprojects/packcc/tests/negative_predicate.d/input.peg create mode 100644 src/subprojects/packcc/tests/negative_predicate.d/input.txt create mode 100644 src/subprojects/packcc/tests/position.d/expected.txt create mode 100644 src/subprojects/packcc/tests/position.d/input.peg create mode 100644 src/subprojects/packcc/tests/position.d/input.txt create mode 100644 src/subprojects/packcc/tests/positive_predicate.d/expected.txt create mode 100644 src/subprojects/packcc/tests/positive_predicate.d/input.peg create mode 100644 src/subprojects/packcc/tests/positive_predicate.d/input.txt create mode 100644 src/subprojects/packcc/tests/quantifiers.d/expected-optional-repeatable.txt create mode 100644 src/subprojects/packcc/tests/quantifiers.d/expected-optional.txt create mode 100644 src/subprojects/packcc/tests/quantifiers.d/expected-repeatable.txt create mode 100644 src/subprojects/packcc/tests/quantifiers.d/input-optional-repeatable.txt create mode 100644 src/subprojects/packcc/tests/quantifiers.d/input-optional.txt create mode 100644 src/subprojects/packcc/tests/quantifiers.d/input-repeatable.txt create mode 100644 src/subprojects/packcc/tests/quantifiers.d/input.peg create mode 100644 src/subprojects/packcc/tests/strings.d/expected-escapes.txt create mode 100644 src/subprojects/packcc/tests/strings.d/expected-utf8.txt create mode 100644 src/subprojects/packcc/tests/strings.d/expected.txt create mode 100644 src/subprojects/packcc/tests/strings.d/input-escapes.txt create mode 100644 src/subprojects/packcc/tests/strings.d/input-utf8.txt create mode 100644 src/subprojects/packcc/tests/strings.d/input.peg create mode 100644 src/subprojects/packcc/tests/strings.d/input.txt create mode 100644 src/subprojects/packcc/tests/style.d/style.bats create mode 100644 src/subprojects/packcc/tests/substitution.d/expected.c.txt create mode 100644 src/subprojects/packcc/tests/substitution.d/expected.h.txt create mode 100644 src/subprojects/packcc/tests/substitution.d/input.peg create mode 100644 src/subprojects/packcc/tests/substitution.d/subst.bats create mode 100755 src/subprojects/packcc/tests/test.sh create mode 100644 src/subprojects/packcc/tests/uncrustify.cfg create mode 100644 src/subprojects/packcc/tests/unused_rule_elimination.d/dump.bats create mode 100644 src/subprojects/packcc/tests/unused_rule_elimination.d/expected.txt create mode 100644 src/subprojects/packcc/tests/unused_rule_elimination.d/input.peg create mode 100644 src/subprojects/packcc/tests/utils.sh create mode 100644 src/subprojects/struct2json.wrap create mode 100644 src/subprojects/struct2json/.gitattributes create mode 100644 src/subprojects/struct2json/LICENSE create mode 100644 src/subprojects/struct2json/README.md create mode 100644 src/subprojects/struct2json/cJSON/cJSON.c create mode 100644 src/subprojects/struct2json/cJSON/cJSON.h create mode 100644 src/subprojects/struct2json/cJSON/cJSON_Utils.c create mode 100644 src/subprojects/struct2json/cJSON/cJSON_Utils.h create mode 100644 src/subprojects/struct2json/cjson/cJSON.h create mode 100644 src/subprojects/struct2json/cjson/s2j.h create mode 100644 src/subprojects/struct2json/cjson/s2jdef.h create mode 100644 src/subprojects/struct2json/demo/error_print.txt create mode 100644 src/subprojects/struct2json/demo/generate_s2j_code.py create mode 100644 src/subprojects/struct2json/demo/generate_struct_defination.py create mode 100644 src/subprojects/struct2json/demo/inc/mc_usr_def.h create mode 100644 src/subprojects/struct2json/demo/main.c create mode 100644 src/subprojects/struct2json/demo/my_struct_2_json.c create mode 100644 src/subprojects/struct2json/demo/my_struct_2_json.h create mode 100644 src/subprojects/struct2json/demo/my_struct_2_json.inc create mode 100644 src/subprojects/struct2json/demo/struct_defination.json create mode 100644 src/subprojects/struct2json/demo/struct_defination.txt create mode 100644 src/subprojects/struct2json/demo/tests2j create mode 100644 src/subprojects/struct2json/docs/README.md create mode 100644 src/subprojects/struct2json/docs/readme.md create mode 100644 src/subprojects/struct2json/docs/zh/api.md create mode 100644 src/subprojects/struct2json/docs/zh/assets/not_use_struct2json.c create mode 100644 src/subprojects/struct2json/docs/zh/assets/not_use_struct2json_for_json.c create mode 100644 src/subprojects/struct2json/docs/zh/assets/used_struct2json.c create mode 100644 src/subprojects/struct2json/docs/zh/assets/used_struct2json_for_json.c create mode 100644 src/subprojects/struct2json/docs/zh/images/not_use_struct2json.png create mode 100644 src/subprojects/struct2json/docs/zh/images/not_use_struct2json_for_json.png create mode 100644 src/subprojects/struct2json/docs/zh/images/used_struct2json.png create mode 100644 src/subprojects/struct2json/docs/zh/images/used_struct2json_for_json.png create mode 100644 src/subprojects/struct2json/docs/zh/readme.md create mode 100644 src/subprojects/struct2json/meson.build create mode 100644 src/subprojects/struct2json/struct2json/inc/s2j.h create mode 100644 src/subprojects/struct2json/struct2json/inc/s2jdef.h create mode 100644 src/subprojects/struct2json/struct2json/src/s2j.c create mode 100644 src/subprojects/tinylog.wrap create mode 100644 src/subprojects/tinylog/.clang-format create mode 100644 src/subprojects/tinylog/.gitignore create mode 100644 src/subprojects/tinylog/CMakeLists.txt create mode 100644 src/subprojects/tinylog/LICENSE create mode 100644 src/subprojects/tinylog/README.md create mode 100644 src/subprojects/tinylog/README_zh-CN.md create mode 100644 src/subprojects/tinylog/example/CMakeLists.txt create mode 100644 src/subprojects/tinylog/example/Makefile create mode 100644 src/subprojects/tinylog/example/example.cpp create mode 100644 src/subprojects/tinylog/makefile create mode 100644 src/subprojects/tinylog/meson.build create mode 100644 src/subprojects/tinylog/test/Makefile create mode 100644 src/subprojects/tinylog/test/test.c create mode 100644 src/subprojects/tinylog/tlog.c create mode 100644 src/subprojects/tinylog/tlog.h create mode 100644 src/subprojects/unity.wrap create mode 100644 src/subprojects/unity/.editorconfig create mode 100644 src/subprojects/unity/.gitattributes create mode 100644 src/subprojects/unity/.github/workflows/main.yml create mode 100644 src/subprojects/unity/.gitignore create mode 100644 src/subprojects/unity/CMakeLists.txt create mode 100644 src/subprojects/unity/LICENSE.txt create mode 100644 src/subprojects/unity/README.md create mode 100644 src/subprojects/unity/auto/__init__.py create mode 100644 src/subprojects/unity/auto/colour_prompt.rb create mode 100644 src/subprojects/unity/auto/colour_reporter.rb create mode 100755 src/subprojects/unity/auto/extract_version.py create mode 100644 src/subprojects/unity/auto/generate_config.yml create mode 100644 src/subprojects/unity/auto/generate_module.rb create mode 100755 src/subprojects/unity/auto/generate_test_runner.rb create mode 100644 src/subprojects/unity/auto/parse_output.rb create mode 100644 src/subprojects/unity/auto/run_test.erb create mode 100644 src/subprojects/unity/auto/stylize_as_junit.py create mode 100755 src/subprojects/unity/auto/stylize_as_junit.rb create mode 100644 src/subprojects/unity/auto/test_file_filter.rb create mode 100644 src/subprojects/unity/auto/type_sanitizer.rb create mode 100644 src/subprojects/unity/auto/unity_test_summary.py create mode 100644 src/subprojects/unity/auto/unity_test_summary.rb create mode 100644 src/subprojects/unity/auto/yaml_helper.rb create mode 100644 src/subprojects/unity/docs/CODE_OF_CONDUCT.md create mode 100644 src/subprojects/unity/docs/CONTRIBUTING.md create mode 100644 src/subprojects/unity/docs/MesonGeneratorRunner.md create mode 100644 src/subprojects/unity/docs/ThrowTheSwitchCodingStandard.md create mode 100644 src/subprojects/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf create mode 100644 src/subprojects/unity/docs/UnityAssertionsReference.md create mode 100644 src/subprojects/unity/docs/UnityChangeLog.md create mode 100644 src/subprojects/unity/docs/UnityConfigurationGuide.md create mode 100644 src/subprojects/unity/docs/UnityGettingStartedGuide.md create mode 100644 src/subprojects/unity/docs/UnityHelperScriptsGuide.md create mode 100644 src/subprojects/unity/docs/UnityKnownIssues.md create mode 100644 src/subprojects/unity/examples/example_1/makefile create mode 100644 src/subprojects/unity/examples/example_1/meson.build create mode 100644 src/subprojects/unity/examples/example_1/readme.txt create mode 100644 src/subprojects/unity/examples/example_1/src/ProductionCode.c create mode 100644 src/subprojects/unity/examples/example_1/src/ProductionCode.h create mode 100644 src/subprojects/unity/examples/example_1/src/ProductionCode2.c create mode 100644 src/subprojects/unity/examples/example_1/src/ProductionCode2.h create mode 100644 src/subprojects/unity/examples/example_1/subprojects/unity.wrap create mode 100644 src/subprojects/unity/examples/example_1/test/TestProductionCode.c create mode 100644 src/subprojects/unity/examples/example_1/test/TestProductionCode2.c create mode 100644 src/subprojects/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c create mode 100644 src/subprojects/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c create mode 100644 src/subprojects/unity/examples/example_2/makefile create mode 100644 src/subprojects/unity/examples/example_2/readme.txt create mode 100644 src/subprojects/unity/examples/example_2/src/ProductionCode.c create mode 100644 src/subprojects/unity/examples/example_2/src/ProductionCode.h create mode 100644 src/subprojects/unity/examples/example_2/src/ProductionCode2.c create mode 100644 src/subprojects/unity/examples/example_2/src/ProductionCode2.h create mode 100644 src/subprojects/unity/examples/example_2/test/TestProductionCode.c create mode 100644 src/subprojects/unity/examples/example_2/test/TestProductionCode2.c create mode 100644 src/subprojects/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c create mode 100644 src/subprojects/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c create mode 100644 src/subprojects/unity/examples/example_2/test/test_runners/all_tests.c create mode 100644 src/subprojects/unity/examples/example_3/helper/UnityHelper.c create mode 100644 src/subprojects/unity/examples/example_3/helper/UnityHelper.h create mode 100644 src/subprojects/unity/examples/example_3/rakefile.rb create mode 100644 src/subprojects/unity/examples/example_3/rakefile_helper.rb create mode 100644 src/subprojects/unity/examples/example_3/readme.txt create mode 100644 src/subprojects/unity/examples/example_3/src/ProductionCode.c create mode 100644 src/subprojects/unity/examples/example_3/src/ProductionCode.h create mode 100644 src/subprojects/unity/examples/example_3/src/ProductionCode2.c create mode 100644 src/subprojects/unity/examples/example_3/src/ProductionCode2.h create mode 100644 src/subprojects/unity/examples/example_3/target_gcc_32.yml create mode 100644 src/subprojects/unity/examples/example_3/test/TestProductionCode.c create mode 100644 src/subprojects/unity/examples/example_3/test/TestProductionCode2.c create mode 100644 src/subprojects/unity/examples/example_4/meson.build create mode 100644 src/subprojects/unity/examples/example_4/readme.txt create mode 100644 src/subprojects/unity/examples/example_4/src/ProductionCode.c create mode 100644 src/subprojects/unity/examples/example_4/src/ProductionCode.h create mode 100644 src/subprojects/unity/examples/example_4/src/ProductionCode2.c create mode 100644 src/subprojects/unity/examples/example_4/src/ProductionCode2.h create mode 100644 src/subprojects/unity/examples/example_4/src/meson.build create mode 100755 src/subprojects/unity/examples/example_4/subprojects/unity.wrap create mode 100644 src/subprojects/unity/examples/example_4/test/TestProductionCode.c create mode 100644 src/subprojects/unity/examples/example_4/test/TestProductionCode2.c create mode 100644 src/subprojects/unity/examples/example_4/test/meson.build create mode 100644 src/subprojects/unity/examples/example_4/test/test_runners/TestProductionCode2_Runner.c create mode 100644 src/subprojects/unity/examples/example_4/test/test_runners/TestProductionCode_Runner.c create mode 100644 src/subprojects/unity/examples/example_4/test/test_runners/meson.build create mode 100644 src/subprojects/unity/examples/unity_config.h create mode 100644 src/subprojects/unity/extras/bdd/readme.md create mode 100644 src/subprojects/unity/extras/bdd/src/unity_bdd.h create mode 100644 src/subprojects/unity/extras/bdd/test/meson.build create mode 100644 src/subprojects/unity/extras/bdd/test/test_bdd.c create mode 100644 src/subprojects/unity/extras/eclipse/error_parsers.txt create mode 100644 src/subprojects/unity/extras/fixture/readme.md create mode 100644 src/subprojects/unity/extras/fixture/src/meson.build create mode 100644 src/subprojects/unity/extras/fixture/src/unity_fixture.c create mode 100644 src/subprojects/unity/extras/fixture/src/unity_fixture.h create mode 100644 src/subprojects/unity/extras/fixture/src/unity_fixture_internals.h create mode 100644 src/subprojects/unity/extras/fixture/test/main/AllTests.c create mode 100644 src/subprojects/unity/extras/fixture/test/template_fixture_tests.c create mode 100644 src/subprojects/unity/extras/fixture/test/unity_fixture_Test.c create mode 100644 src/subprojects/unity/extras/fixture/test/unity_fixture_TestRunner.c create mode 100644 src/subprojects/unity/extras/memory/readme.md create mode 100644 src/subprojects/unity/extras/memory/src/meson.build create mode 100644 src/subprojects/unity/extras/memory/src/unity_memory.c create mode 100644 src/subprojects/unity/extras/memory/src/unity_memory.h create mode 100644 src/subprojects/unity/extras/memory/test/unity_memory_Test.c create mode 100644 src/subprojects/unity/extras/memory/test/unity_memory_TestRunner.c create mode 100644 src/subprojects/unity/extras/memory/test/unity_output_Spy.c create mode 100644 src/subprojects/unity/extras/memory/test/unity_output_Spy.h create mode 100644 src/subprojects/unity/library.json create mode 100644 src/subprojects/unity/meson.build create mode 100644 src/subprojects/unity/meson_options.txt create mode 100644 src/subprojects/unity/platformio-build.py create mode 100644 src/subprojects/unity/src/meson.build create mode 100644 src/subprojects/unity/src/unity.c create mode 100644 src/subprojects/unity/src/unity.h create mode 100644 src/subprojects/unity/src/unity_internals.h create mode 100644 src/subprojects/unity/test/.rubocop.yml create mode 100644 src/subprojects/unity/test/expectdata/testsample_cmd.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_def.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_head1.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_head1.h create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_cmd.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_def.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_head1.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_head1.h create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_new1.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_new2.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_param.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_run1.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_run2.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_mock_yaml.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_new1.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_new2.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_param.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_run1.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_run2.c create mode 100644 src/subprojects/unity/test/expectdata/testsample_yaml.c create mode 100644 src/subprojects/unity/test/rakefile create mode 100644 src/subprojects/unity/test/rakefile_helper.rb create mode 100644 src/subprojects/unity/test/spec/generate_module_existing_file_spec.rb create mode 100644 src/subprojects/unity/test/targets/ansi.yml create mode 100644 src/subprojects/unity/test/targets/clang_file.yml create mode 100644 src/subprojects/unity/test/targets/clang_strict.yml create mode 100644 src/subprojects/unity/test/targets/gcc_32.yml create mode 100644 src/subprojects/unity/test/targets/gcc_64.yml create mode 100644 src/subprojects/unity/test/targets/gcc_auto_limits.yml create mode 100644 src/subprojects/unity/test/targets/gcc_auto_stdint.yml create mode 100644 src/subprojects/unity/test/targets/gcc_manual_math.yml create mode 100644 src/subprojects/unity/test/targets/hitech_picc18.yml create mode 100644 src/subprojects/unity/test/targets/iar_arm_v4.yml create mode 100644 src/subprojects/unity/test/targets/iar_arm_v5.yml create mode 100644 src/subprojects/unity/test/targets/iar_arm_v5_3.yml create mode 100644 src/subprojects/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml create mode 100644 src/subprojects/unity/test/targets/iar_cortexm3_v5.yml create mode 100644 src/subprojects/unity/test/targets/iar_msp430.yml create mode 100644 src/subprojects/unity/test/targets/iar_sh2a_v6.yml create mode 100644 src/subprojects/unity/test/testdata/CException.h create mode 100644 src/subprojects/unity/test/testdata/Defs.h create mode 100644 src/subprojects/unity/test/testdata/cmock.h create mode 100644 src/subprojects/unity/test/testdata/mockMock.h create mode 100644 src/subprojects/unity/test/testdata/testRunnerGenerator.c create mode 100644 src/subprojects/unity/test/testdata/testRunnerGeneratorSmall.c create mode 100644 src/subprojects/unity/test/testdata/testRunnerGeneratorWithMocks.c create mode 100644 src/subprojects/unity/test/tests/self_assessment_utils.h create mode 100644 src/subprojects/unity/test/tests/test_generate_test_runner.rb create mode 100644 src/subprojects/unity/test/tests/test_unity_arrays.c create mode 100644 src/subprojects/unity/test/tests/test_unity_core.c create mode 100644 src/subprojects/unity/test/tests/test_unity_doubles.c create mode 100644 src/subprojects/unity/test/tests/test_unity_floats.c create mode 100644 src/subprojects/unity/test/tests/test_unity_integers.c create mode 100644 src/subprojects/unity/test/tests/test_unity_integers_64.c create mode 100644 src/subprojects/unity/test/tests/test_unity_memory.c create mode 100644 src/subprojects/unity/test/tests/test_unity_parameterized.c create mode 100644 src/subprojects/unity/test/tests/test_unity_parameterizedDemo.c create mode 100644 src/subprojects/unity/test/tests/test_unity_strings.c create mode 100644 src/subprojects/unity/test/tests/types_for_test.h create mode 100644 src/subprojects/unity/unity/unity.h create mode 100644 src/subprojects/unity/unity/unity_internals.h create mode 100644 src/subprojects/unity/unityConfig.cmake create mode 100755 src/tools/xce-package.sh create mode 100644 src/xceadmin/requirements-build.txt diff --git a/.gitignore b/.gitignore index aa110b22..3396de60 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,13 @@ src/lib/controller.capnp.c src/lib/controller.capnp.h .wolf/daemon.log .wolf/token-ledger.json + +# --- de-nix build (build/de-nix): vendored wrap-subproject trees are COMMITTED +# (source closure, DEPS.md), but their nested git repos and meson's wrap-hash +# bookkeeping are local artifacts -- never check them in --- +src/subprojects/*/.git/ +src/subprojects/*/.meson-subproject-wrap-hash.txt +src/subprojects/.wraplock + +# --- de-nix build: packaging output (src/tools/xce-package.sh) --- +src/dist/ diff --git a/DEPS.md b/DEPS.md new file mode 100644 index 00000000..7ea102b9 --- /dev/null +++ b/DEPS.md @@ -0,0 +1,81 @@ +# XCE 第三方依赖清单 + +> 建立:2026-10-20(build/de-nix 分支)。背景与决策见 gaps.md "六、构建/分发系统"。 +> +> **原则**:系统库优先(apt/发行版包),发行版没有的用 meson wrap subproject 从源码构建; +> 运行期需要自带的库由打包脚本 bundle(`$ORIGIN` RPATH),不引入 /nix/store 或任何 +> 内容寻址二进制闭包。glibc/libm/libpthread/pthread 永不 bundle。 + +## 构建工具链 + +| 工具 | 最低版本 | 获取 | 备注 | +|---|---|---|---| +| gcc | 13 | 系统包 | `apt install gcc`(glibc 2.39+ 基线) | +| meson | 1.5 | `pip install meson` / `apt install meson`(≥1.3 时 pip 补) | src/meson.build 要求 >=1.5 | +| ninja | 1.11 | `apt install ninja-build` | meson 默认 backend | +| pkg-config | 0.29 | `apt install pkg-config` | | +| go | 1.22 | 上游 tarball / `apt install golang-go` | apiserver/xcecli 已 vendor 全部模块,构建离线 | +| capnp (capnproto) | 1.0.1 | `apt install capnproto`(含 libcapnp-dev) | schema 编译器 + C++ 运行时(pycapnp 链接用) | +| packcc | 2.2 | wrap subproject(Ubuntu 24.04 无包) | 3 个 .peg 解析器(lib/section, rusage, xce_resreq, xce_select) | +| python3 | 3.10 | 系统自带 | xceadmin 构建/测试;no-fork rule 检查脚本 | +| swag | latest | `go install github.com/swaggo/swag/cmd/swag@latest` | 仅 apiserver 文档再生成时需要,非构建必需 | + +## C 库依赖 + +### apt 可直接安装(11 个) + +| 依赖 (meson 名) | apt 包 | 版本下限 | 用途 | +|---|---|---|---| +| libuv | libuv1-dev | >=1.44 | 所有 daemon 事件循环 | +| openssl | libssl-dev | >=3.0 | TLS(controller 互联、apiserver)、SHA256 | +| libedit | libedit-dev | >=3.1 | xce_test REPL(BSD 许可,替代 GPL readline) | +| sqlite3 | libsqlite3-dev | >=3.37 | worker 本地状态 | +| hwloc | libhwloc-dev | >=2.8 | worker 拓扑/槽位 | +| libcgroup | libcgroup-dev | >=2.0 | worker cgroup v2 限额 | +| libtirpc | libtirpc-dev | >=1.3 | rpc 头文件 | +| libcyaml | libcyaml-dev | >=1.2 | YAML 配置读取 | +| yaml-0.1 | libyaml-dev | >=0.2.5 | 同上(libcyaml 依赖) | +| zlib | zlib1g-dev | >=1.2.11 | 压缩 | +| threads/math/rt | (libc) | — | 无需安装 | + +### apt 没有 → meson wrap subproject(源码随 repo 拉取构建,6 个) + +| 依赖 (meson 名) | 上游 | 版本 | 用途 / 备注 | +|---|---|---|---| +| c-capnproto | github:shen390s/c-capnproto(pin e45ff68) | — | Cap'n Proto C runtime(libCapnC_Runtime)+ capnpc-c 代码生成器;32 个源文件 include capnp_c.h | +| librtti | git+ssh gitea rshen/librtti(pin 2149f778) | 0.0.2 | C 运行时类型信息库;上游本身是零依赖 meson 项目;93 个源文件消费 | +| struct2json | xbuild channel 源码 vendor | 1.0.0 | cJSON + s2j 封装(纯静态库);6 个 meson 消费点 | +| tinylog | xbuild channel 源码 vendor | 1.0.0 | 轻量异步日志(-ltlog + tlog.h);13 个源文件消费 | +| unity | xbuild channel 源码 vendor(上游 ThrowTheSwitch/Unity) | 2.6.1 | 单元测试框架(libunity.a + unity/unity.h);仅测试目标链接 | +| packcc | 上游 arithy/packcc | >=2.2 | PEG 解析器生成器;构建工具而非链接库 | + +### 特殊:libelogind → libsystemd + +worker 的 systemd transient unit 管理(`sd_bus_*`,263 处调用)目前链 nix 的 elogind 255.5。 +Ubuntu 24.04 无 elogind 包,但有 **libsystemd-dev 255.4**——sd-bus API 同源兼容。 +构建默认 `dependency('libsystemd')`,保留 `-Duse_elogind=true` 选项供非 systemd 平台。 +(Step 2 实施时验证;这是本迁移唯一有 ABI 行为风险的替换点,worker 单测兜底。) + +### Python(xceadmin) + +`src/xceadmin/pyproject.toml` 已声明全部运行依赖:click>=8.0, pycapnp>=1.3, PyYAML>=6.0, +jsonschema>=4.0。构建用普通 venv(**不要** --system-site-packages——那是 nix 环境的产物): +`python3 -m venv .venv && .venv/bin/pip install .`。pycapnp 的 C 扩展链系统的 +capnproto C++ 运行时(apt capnproto/libcapnp-dev 提供版本 1.0.1;pycapnp>=1.3 兼容)。 + +## 为什么不用 nix store(决策记录) + +nix 把依赖闭包做成内容寻址的 /nix/store 路径 + mount namespace,要求闭包出现在**每一台 +运行机器**上,且 patchelf 重定位后 ldd/gdb/stack trace 全部变形(t2/t3 master 进程 argv 是 +`ld-linux... --library-path /opt/newxce/app/nix/store/...`,人读不懂)。EDA 客户环境没有 +/nix/store,这条路在产品定义上不可用。本 repo 依赖只有十来个中小型库,"自包含"的正确形态 +是**源码闭包**(wrap subproject)+ 运行期 bundle 清单,不需要二进制 store。此外 nix 的 +LD_LIBRARY_PATH 泄漏会导致系统工具崩溃(t2/t3 的 ls/head segfault 实录)。 + +## 运行期 bundle 规则(打包脚本用) + +- **bundle**:libuv、libcapnp/libCapnC_Runtime、librtti、libtlog、libstruct2json、 + libcyaml、libyaml、libtirpc、libedit、libcgroup、libhwloc、libssl/libcrypto(若目标基线 <3.0) +- **永不 bundle**:libc/libm/libpthread/libdl/librt(glibc)、libsystemd(按目标发行版) +- 判定方法:对每个产物 `ldd`,凡路径不在 {/lib, /usr/lib, /lib64} 的(即 wrap 构建产物) + 一律复制进 `lib/`,二进制设 `$ORIGIN/../lib` RPATH。 diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..80798cda --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +# Thin facade over src/tools/xce-build.sh (which drives meson+ninja directly). +# The real build logic lives there and in src/*/meson.build; this file exists +# only so `make` / `make test` work out of habit for anyone arriving from the +# old make-based layout. Dependency prerequisites and policy: see DEPS.md. + +PROFILE ?= asan +COMPONENT ?= all +JOBS ?= + +BUILD_ARGS := $(COMPONENT) $(PROFILE) +ifneq ($(JOBS),) + BUILD_ARGS += --jobs $(JOBS) +endif + +.PHONY: all build test debug release clean help + +all: build + +build: + bash src/tools/xce-build.sh $(BUILD_ARGS) + +test: + bash src/tools/xce-build.sh $(COMPONENT) asan $(if $(JOBS),--jobs $(JOBS),) + +debug: + bash src/tools/xce-build.sh $(COMPONENT) debug $(if $(JOBS),--jobs $(JOBS),) + +release: + bash src/tools/xce-build.sh $(COMPONENT) release $(if $(JOBS),--jobs $(JOBS),) + +clean: + rm -rf src/xce.build src/build.dbg src/build.release + +help: + @echo "Targets:" + @echo " make / make build - build all components ($(PROFILE) profile) + run unit tests" + @echo " make test - same as build (asan profile runs tests)" + @echo " make debug - build without ASAN (-O0 -g3, gdb-friendly, no tests)" + @echo " make release - build -O3, no sanitizer (no tests)" + @echo " make clean - remove build dirs" + @echo "Variables: COMPONENT=all|lib|controller|harness|scheduler|worker|apiserver|xcecli|xceadmin" + @echo " PROFILE=asan|debug|release (for build), JOBS=N (parallelism cap)" + @echo "Dependency prerequisites and policy: see DEPS.md" diff --git a/gaps.md b/gaps.md new file mode 100644 index 00000000..3e21aa03 --- /dev/null +++ b/gaps.md @@ -0,0 +1,168 @@ +# XCE 调度器现存问题清单(gaps 分析) + +> 生成时间:2026-10-16;来源:t1/t2/t3 集群实测 + 调度器源码逐模块审查(feature/x11-forwarding 分支视角)。 +> 背景:t1 亲和性根因已确认(first-fit × 插入序槽位,见 memory xce-firstfit-t1-affinity),本文记录**除 t1 亲和外的**调度器问题。 +> 约定:本文档只做记录,未做任何代码改动。 +> +> **2026-10-20 增补**:openmpi 回归(OS openmpi 4.1.6 跨机跑通,见 memory xce-mpi-regression)与全框架评审后新增"五、架构层改进项"(11–17)与"六、构建/分发系统",原有 1–10 维持不变。 + +--- + +## 一、策略缺失类(功能"看起来有、实际没生效") + +### 1. 作业级优先级全链路断裂 ⭐ 最严重 +这条链路上每一环都是断的: + +| 环节 | 现状 | 位置 | +|---|---|---| +| wire schema | `JobSubmitData` 没有 priority 字段,提交时无法携带 | src/schema/controller.capnp:583 | +| scheduler 入口 | `job->priority = 0; /* FIXME */` 硬编码 | core_events.c:353、schedobj.c:214 | +| 排序器 | builtin_fcfs 的 `job->priority` 降序比较器因恒为 0 而成死代码 | plugins/builtin_fcfs.c:190-215 | +| Go API 层 | apiserver 的 UserPriority/JobPriority 模型字段没映射到 wire | apiserver Go models | + +**实际效果**:只有队列优先级在起作用,同队列内提交顺序即调度顺序,用户无法插队/降级。 +**修复面**:wire schema 加字段(注意 master/worker/controller/scheduler 同版本 ABI 约束)+ core_events/schedobj 填充 + Go API 提交路径映射。改动面中等,对用户价值最高。 + +### 2. 抢占(preemption)不存在 +`make_preempt_decision`(src/scheduler/src/decision.c:35)已完整实现,但全库只有 testsuite 调用——没有任何 live 路径会触发它。高优先队列来了也只会排着,不会踢低优先作业。 + +### 3. 无 fairshare +只有静态配额(user/queue/host 的 slot、mem 上限)。多用户共享集群时,先来的人可以连续吃满配额,没有按用户/组的份额均摊或历史使用量惩罚机制。builtin_fcfs 排序维度只有:队列优先级 →(死的)作业优先级 → 提交时间。 + +### 4. 队列 sched_delay / accept_interval 是死配置 +这两个字段被复制进 scheduler 的 queue 结构,但没有任何代码路径消费它们(仅一个 controller 测试 fixture 引用)。管理员配了也不生效,属于会误导人的配置项。 + +--- + +## 二、吞吐 / 时延类 + +### 5. 轮次节奏 + 容量 1 的管道 = 吞吐下限 +派发链路是三级串行管道: + +- **主循环 sleep(1)**:每轮间隔 ≥1s(src/scheduler/src/main.c:552); +- **jbuf 容量 1**:picker 每轮只递给 allocator 一个作业,allocator 消化完才能拿下一个(src/scheduler/src/core.c:151); +- **decisions 容量 5 硬编码**:`int ndecisions = 5; /* FIXME: make this configurable */`(src/scheduler/src/core.c:87)。 + +**实际效果**:即使所有资源充足,派发速率也被压在 ~1 作业/秒量级;大量 PEND 作业排队时这个下限直接可见(也是 `-I --tty` 首输出延迟问题中我们只能优化 CLI 轮询退避、改不了调度侧的原因)。 +**修复面**:sleep 与容量参数化,低风险高收益。 + +--- + +## 三、健壮性类 + +### 6. alloc_rc < 0(内部错误)时作业"失踪"一轮 +sched_election.c:365-370:allocator 内部错误时**不下发任何 decision**(既不派发也不回 PEND-with-reason)。作业要等下一轮 session 重新被捡起来,且用户看不到任何 reason。对照 bug-1512 的教训(派发失败必须有明确语义),这条内部错误路径的语义是缺失的。 + +### 7. ALTER 作业的 PEND reason 只取一个 child +src/scheduler/src/scheduler.c:491 `/* FIXME: merge pend reason from all children */`——多备选作业挂在某个备选上时,report 出去的 reason 未必是"主"原因。与 PEND reason 全链路补全(ac6131d)的精神相悖,是漏网之鱼。 + +### 8. 多机作业内存用量无法对账 +sched_reconcile_job_resource_usage(src/scheduler/src/resource.c:965):rusage 上报的 wire 格式没有 host 归属,所以只对单机作业做 mem 释放对账,多机作业永远停留在按 host 摊派的初始预留值。长期运行会造成幽灵占用 → 影响后续 fit 判断(当前 t1 亲和恰好掩盖了它)。 + +### 9. 90 秒心跳窗口内向死 worker 派发 +worker 掉线要 `heartbeat_interval(30s) × inactive_heartbeat_count(3) = 90s`(src/configs/xce.yaml)才被标 UNAVAIL(src/controller/cluster.c:2215 check_worker_timeout_)。这期间 allocator 照常往它派发,作业进 worker 后要么 IPC 失败回 PEND,要么挂着没响应。且 UNAVAIL 触发时**没有作业重排机制**——挂在它上面的作业要靠 dispatch-fail ack(src/scheduler/src/handler.c:384)或看门狗兜底。 + +### 10. resource.c:602 空 FIXME +错误路径上是空的 `/* FIXME: */`——具体失败场景无注释,值得单独看一眼。 + +--- + +## 四、运维 / 历史类 + +| 项 | 说明 | +|---|---| +| **notifyAcked opcode-45 版本偏差** | t1 新 worker(a8c3e91)发 `OPCode_notifyAcked`(bug-1741),运行中的 controller(c3acd62)不认识,日志刷 "Unknown opcode: 45"。升级 controller 即消。与调度无关但污染告警 | +| **历史 "free(): invalid pointer"** | t1 /opt/xce/logs/xce_scheduler.out 有 3 条(Sep 1 时代)。与 bug-1513(已修)时代吻合,建议确认现版本二进制无同类残留 | +| **legacy fcfs 插件仍注册** | fcfs.c 走 deprecated `job_elect_fn` 钩子,启动 WARN "deprecated job_elect_fn hook"。与 builtin_fcfs 两条路径并存增加维护面 | +| **jobs kvmgr nslots=5381 硬编码** | src/scheduler/src/core.c:94 FIXME,与 ndecisions=5 同源 | +| **kvmgr 槽位序 = 派发序** | 即已确认的 t1 亲和根因:worker 遍历顺序无策略介入,sched_claim_bucket_ 取第一个过 filter 的候选(alloc_runner.c:219),槽位序继承自 snapshot restore 链(controller/worker.c:564 restore_host_state → wobj.c:220 key_add EEXIST 保序) | + +--- + +## 优先级建议(如果要动手) + +1. **t1 亲和**(已确认根因,改 start 策略即可见效)→ +2. **作业级优先级**(wire schema + core_events + Go API 三处,改动面中等但对用户价值最高)→ +3. **轮次节奏/容量参数化**(低风险高收益)→ +4. **alloc_rc<0 decision 语义补全** → +5. 其余按需。 + +(2026-10-20 补:架构层评审新增 #11–#17 与构建/分发系统一节,动手顺序见文末"架构层动手顺序建议"——共享复制层第一,TSAN/写者规则第二。) + +--- + +## 五、架构层改进项(2026-10-20 全框架评审新增) + +> 来源:feature/scheduler-advisor 分支视角的整框架评审;每条都对应一次实际故障或 2026-10-20 openmpi 回归现场。 + +### 11. 一致性路径每子系统各造一套,ack 语义无统一定义 +config push(config_repl.c WAL/committed-marker/hash-verify)、scheduler 状态同步、worker resync 各自实现复制与 ack。已知的直接后果: +- **ackedCount==0 误报**(2026-10-20 现场复现两次):无 standby 集群里 `do_upgrade_config_with_bytes` 提交成功(majority=primary 单机),但 reply 的 `acked_count` 只计 standby ack,xceadmin 误报 "push rejected (ackedCount == 0)"(config_repl.c:1863-1892)。majority 是否含自身没有统一定义。 +- **config-push 屏障 stale-ack 缺陷**:E2E 确定性红,修复已知(repl.c 等值判断 + 2 个测试点)但长期未修——长红的测试等于没有测试。 +- **rejoin 三连崩溃**(bug-1513):共享串 raw-free、limit key_add EEXIST double-free、config-vs-job 竞态——rejoin 状态重同步是第三套手工一致性代码。 +**建议**:把 config_repl 那套 WAL/marker/hash-verify 抽成共享复制层,ack 语义定义一次(majority 含自身),三个 bespoke 路径全部收编。一个动作同时消灭至少三个已知缺陷类别。 + +### 12. 核心组件状态变更不传播,靠 join 快照 + 重启兜底 +- `xcesched_push_configs`(sched.c:139)唯一调用点是 `on_scheduler_join`(sched.c:768-793)——config push 到达不了运行中的 scheduler,limit 改动必须重启 scheduler(2026-10-20 现场两次重启)。`config_activate_committed` 只刷新 controller 自身 `c->myconf`,`reconcile_config_queues` 只建新队列。 +- worker 重连后的状态补报靠透明 failover 协议手工补(9d7628e)+ bug-1522(xcecli_start 清 rejoin_cb 使 reconnect_cb 成死代码)这类补丁。 +- EventBroker/SSE 只加在 API 层(advisor findings 推送),没进控制面。 +**建议**:controller 发布带版本号的 jobs/hosts/configgen 增量流,daemon 订阅而非 join 快照。config 传播是它的第一个收益(顺带消灭"改 limit 要重启 scheduler")。 + +### 13. 共享可变状态无单一写者纪律(随机堆损坏的根因类别) +- bug-1521:fcfs picker 线程写 `job->schedobj->reason`,allocator 线程对同一字段 MOVE_PTR——堆损坏随机崩溃,#17 绕开(不 attach)但未修。 +- PEND reason 需要"全链路补全"(ac6131d)逐段手工穿线,说明 reason 的归属权从未定义。 +- 这类竞态现有单测抓不到(union 变异测试无效的教训)。 +**建议**:job 结构每字段标注唯一写者(或 reason 改 owned/RCU 归属),**TSAN 进 CI**。1513+1521 两次各耗数天的排查成本远超预防成本。 + +### 14. 契约无文档,合并丢逻辑 +main_reason 契约在两个代码库各自演化,scheduler-framework 合并时丢 PEND-reason P1(见 memory xce-merge-drop-audit)。job 状态机 + reason 来源枚举应落成一页文档 + 共享头文件;合并审计时对照的"契约清单"应存在 repo 里而不是人脑里。 + +### 15. 调度策略与容量检查耦合,跨机拆分只做均分(2026-10-20 实测) +- 布局 t2:5/t3:2 空闲时 `-n 6`/`-n 7` PEND——总量够但不均分拆分不走(t2:4,t3:2 理论可行);均分 3+3 放不下即 PEND。`-host t2:2,t3:2`(-n4)、`t2:3,t3:3`(-n6)、`t2:4,t3:4`(-n8)实测均分拆分正常。 +- 拆分成功的先决条件是"每台都放不下整个作业",first-fit + 插入序槽位(见 t1 亲和条目)共同导致放置结果依赖 worker 遍历序。 +- PEND 时 `pending_reason` 依旧显示 '-',用户无从知道"总量够但拆分策略不放"。 +**建议**:placement 抽成策略层(pack/spread/fairshare 可插拔 + span[nodes]/每节点最少 rank 旋钮,对齐 LSF/SGE 用户词汇);PEND reason 对"策略性拒绝"给出诚实文案。 + +### 16. IPC 协议卫生:手工 union 与 capnp 并存、定长缓冲、jobid 位打包 +- `ipc_message_t` 手工二进制 union 与 capnp 并存:bug-1936/1957 的 ABI skew 要求 daemon 成对替换(见 memory xce-ipc-abi-skew),无法滚动升级。建议控制面消息全面迁 capnp + 版本协商,加 `xceadmin preflight` 检查节点版本偏斜。 +- 定长缓冲:`job_assignment_t.cmd` 4096 截断(COMMAND_LENGTH 系列)——长 MPI 命令行(PRTE_PREFIX+LD_LIBRARY_PATH 前缀的 prted 命令实测逼近上限)随时可截断。 +- jobid 位打包(20 位 sequence / 32 位 timestamp 会绕回)同时当主键、systemd 单元名、分片路由键:stale unit "already loaded"(2026-10-20 现场撞到)与截断解码出垃圾 ID 都与之相关。ID 内部可打包,对外应是不透明字符串 + epoch。 + +### 17. 作业执行上下文无显式契约(MPI 类环境敏感负载的隐患源) +2026-10-20 nix prted 崩溃调查的整条链都源于此: +- systemd 瞬态单元不设 `Environment=`(xcecd_cgroups.c start_systemd_job);任务继承 worker env(uv_proc.c:205 `options.env = NULL`)。 +- xrun 依赖 `XCE_JOBID` 这个从未写进文档的继承契约(worker apply_env_vars → mpirun → xrun env 继承),传错粒度(timestamp 而非全 uint64)只在 master 日志 DEBUG 里报。 +- cwd 无权限时静默 fallback 到 /tmp 只打 WARN(uv_proc.c:522)。 +- master daemon 日志 INFO 级看不到 remote-start 回执,排查只能靠副作用。 +**建议**:定义显式 JobExecutionContext(env 白名单、cwd 解析规则、用户映射、limits),所有启动路径(本地/systemd/remote-start/interactive/MPI relay)共用并校验,失败大声报错。 + +--- + +## 六、构建 / 分发系统(2026-10-20,用户提出重构意向) + +背景:nix 是个别同事未经商定替换原 makefile 系统引入的。EDA 客户及潜在客户无人用 NixOS 当 server;nix 的配置逻辑诡异、使用反人类(`nix develop` + click/pycapnp 仅存在于该 shell、`--option sandbox false` 咒语、未 git-add 的新文件不进构建)。openmpi 回归中 nix openmpi 5.0.11 的 prted 在 XCE relay 启动环境必崩(OS openmpi 4.1.6 正常),进一步印证 nix 工具链在非常规启动环境下的脆弱。 + +**建议方向:构建归构建、分发归分发,产品路径完全去 nix 化。** +- 构建:统一 CMake(或 meson);依赖用系统包管理器声明,裸 Ubuntu `apt install build-essential libuv-dev ...` 可出全部产物。 +- 分发:tarball + systemd unit + 安装脚本(/opt/xce 布局已接近该形态);需要自带依赖时用容器镜像(docker/podman),可理解性远高于 AppImage 解包 nix store 闭包(xce-appimage-cluster-script 里的坑)。 +- CI:标准 Ubuntu 容器内 apt install + build + test,与客户环境一致。 +- 迁移可渐进:nix 保留为 CI 内部多版本工具链矩阵,产品 build/分发不经过 nix。 +- 先行动作:现状盘点(哪些环节被 nix 锁死:build/测试/分发/集群部署各自依赖什么),输出迁移顺序草案。 + +--- + +## 架构层动手顺序建议(2026-10-20) + +1. **共享复制层(#11)**——同时消灭最多已知缺陷类别(ackedCount 误报、stale-ack 红测试、rejoin 崩溃类); +2. **TSAN + 写者规则(#13)**——随机堆崩溃排查成本(1513、1521 各耗数天)远超预防成本; +3. **状态传播(#12)**——顺带解决"改 limit 要重启 scheduler"; +4. **placement 策略层(#15)**——EDA 客户最先撞上的墙; +5. 其余(#14、#16、#17)与构建系统重构("六")并行推进。 + +--- + +## 附:排查方法论备忘(可复用) + +- **gdb 活体结构遍历**:`static xce_scheduler_t sched`(main.c:202)二进制缺完整 DWARF 时,按裸地址 `x/64gx` dump,手工映射 kvmgr {key_type@0, nslots@4, kvtab@8, data@16} 与 xzarray_t {count@0, caps@8, delta@16, pos@24, data@32, killer@40}(zarray.c:392 实际布局,非 include/zarray.h 旧布局),用已知常量(queues nslots=59、workers 5381、delta=64)校验。 +- **ssh+gdb 引号**:外层单引号包整条 ssh 命令,内层用双引号。 +- **作业分布统计**:`grep -oE 't[0-9]+'` 数 hostname,避免 awk 按列切分被提交日期干扰。 diff --git a/scripts/ci-ubuntu.sh b/scripts/ci-ubuntu.sh new file mode 100755 index 00000000..148fb4ea --- /dev/null +++ b/scripts/ci-ubuntu.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# ci-ubuntu.sh -- CI entrypoint for the de-nix build path. +# +# Designed to run inside a bare Ubuntu 24.04 container (the same baseline +# customers use); the dependency install mirrors DEPS.md exactly. Local +# developers who already have the deps can skip straight to the build step. +# +# Usage: scripts/ci-ubuntu.sh [--deps-only | --build-only] +set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +DO_DEPS=1; DO_BUILD=1 +case "${1:-}" in + --deps-only) DO_BUILD=0 ;; + --build-only) DO_DEPS=0 ;; +esac + +if [ "$DO_DEPS" = 1 ]; then + echo "=== Installing build toolchain + system libraries (DEPS.md) ===" + export DEBIAN_FRONTEND=noninteractive + apt-get update -qq + # toolchain + apt-get install -y -qq build-essential pkg-config ninja-build python3 python3-pip python3-venv ca-certificates git + # meson >= 1.5 (Ubuntu 24.04's meson is 1.3 -- pip upgrades it in-place) + apt-get install -y -qq meson || true + meson --version 2>/dev/null | { read v; [ "${v%%.*}" -ge 1 ] && [ "${v#*.}" -ge 5 ] || pip3 install --break-system-packages 'meson>=1.5'; } || pip3 install --break-system-packages 'meson>=1.5' + # cap'n proto (schema compiler + C++ runtime for pycapnp) + apt-get install -y -qq capnproto libcapnp-dev + # C libraries (DEPS.md "apt 可直接安装" table) + apt-get install -y -qq libuv1-dev libssl-dev libedit-dev libsqlite3-dev \ + libhwloc-dev libcgroup-dev libtirpc-dev libcyaml-dev libyaml-dev \ + zlib1g-dev libsystemd-dev + # Go toolchain (Ubuntu golang-go is fine for the vendored modules) + command -v go >/dev/null 2>&1 || apt-get install -y -qq golang-go + echo "=== deps installed ===" +fi + +if [ "$DO_BUILD" = 1 ]; then + echo "=== Building all components (asan profile: build + unit tests) ===" + bash "$REPO_ROOT/src/tools/xce-build.sh" all asan + echo "=== Building release profile (packaging prerequisite) ===" + bash "$REPO_ROOT/src/tools/xce-build.sh" all release + echo "=== Smoke: package a tarball ===" + bash "$REPO_ROOT/src/tools/xce-package.sh" "$REPO_ROOT/src/build.release" "$REPO_ROOT/src/dist" + echo "=== CI OK ===" +fi diff --git a/src/controller/config_repl.c b/src/controller/config_repl.c index 072c3c2b..5b01a45f 100644 --- a/src/controller/config_repl.c +++ b/src/controller/config_repl.c @@ -1644,6 +1644,13 @@ int push_config_to_standbys(cluster_t *c, const uint8_t *bytes, size_t blen, * to CONF_PUSH_TIMEOUT_MS — iomgr-reachable callers must use * push_config_transport_only instead (see config_repl.h). */ int n = 0; + /* Clear stale config acks BEFORE the fan-out: config tags are + * SHA-256-derived, not monotonic — without this, a previous push's + * ack (e.g. the election-bootstrap sync's tag) can numerically exceed + * this push's tag and the barrier below would fabricate a quorum from + * acks that never covered these bytes (standbys not even contacted + * yet). repl.h: repl_reset_config_acks. */ + repl_reset_config_acks(&c->persist.repl); int acked = push_config_transport_only(c, bytes, blen, sha256, new_tag, &n); if (acked_out) diff --git a/src/controller/meson.build b/src/controller/meson.build index 71495ac8..cfaf4469 100644 --- a/src/controller/meson.build +++ b/src/controller/meson.build @@ -37,7 +37,7 @@ incdir = include_directories('.', '../include', '../lib', # cc = meson.get_compiler('c') # math_dep = cc.find_library('m', required : false) -zlib_dep = dependency('zlib') +zlib_dep = dependency('zlib', version: '>=1.2.11') controller_deps = [ libxce_dep, @@ -206,7 +206,7 @@ controller_unit_test_src = [ 'resync.c', ] -ssl_dep = dependency('openssl') +ssl_dep = dependency('openssl', version: '>=3.0') controller_unit_test_deps = [ libxce_dep, @@ -242,9 +242,6 @@ mkdtemp_clean_lib = static_library( join_paths(meson.source_root(), 'testsuite_support', 'mkdtemp_clean.c'), join_paths(meson.source_root(), 'testsuite_support', 'case_scratch_sweep.c'), - include_directories: [ - include_directories(unity_dep.get_variable('includedir')), - ], dependencies: [unity_dep]) controller_unit_test_deps += declare_dependency(link_with: mkdtemp_clean_lib) diff --git a/src/controller/repl.c b/src/controller/repl.c index df906111..d595702d 100644 --- a/src/controller/repl.c +++ b/src/controller/repl.c @@ -565,6 +565,21 @@ void repl_on_config_ack(replicator_t *r, repl_ep_t ep, uint64_t acked_config_lsn pthread_mutex_unlock(&r->ack_lock); } +void repl_reset_config_acks(replicator_t *r) +{ + if (r == NULL) + return; + + mylock_lock(&r->lock); + for (int i = 0; i < MAX_STANDBYS; i++) { + standby_conn_t *s = &r->standbys[i]; + if (s->ep == NULL) + continue; + atomic_store_explicit(&s->acked_config_lsn, 0, memory_order_release); + } + mylock_unlock(&r->lock); +} + /* ============================================================ * Majority-quorum ACK wait (task 7.3; walAck track rebased onto the * commit engine by ha-commit-barrier-rollout task 2.2) diff --git a/src/controller/testsuite/test_commit_barrier_rollout.c b/src/controller/testsuite/test_commit_barrier_rollout.c index fa172d0b..ecd088ed 100644 --- a/src/controller/testsuite/test_commit_barrier_rollout.c +++ b/src/controller/testsuite/test_commit_barrier_rollout.c @@ -1480,6 +1480,36 @@ static void cb5_arrange_upgrade_req(uint8_t *blob, size_t blen, /* ── push_config_to_standbys: barrier result + push count (Req 4.2, 4.3) ── */ +/* Concurrent-ACK injector: since repl_reset_config_acks (config-push + * quorum hardening) clears every standby's acked_config_lsn at the START + * of each push, a pre-ack installed before push_config_to_standbys no + * longer counts -- matching production, where a standby can only ever ack + * bytes it has already received. These tests therefore inject their ACKs + * from a helper thread while the main thread sits inside the barrier wait + * (same pattern as test_config_ack_wire_path_completes_barrier and the + * bug-1914 late-ACK test above). */ +typedef struct { + cluster_t *c; + endpoint_t*eps[2]; + uint64_t tag; + unsigned delay_ms; +} cb5_ack_inject_args_t; + +static void *cb5_ack_inject_thread(void *arg) +{ + cb5_ack_inject_args_t *a = (cb5_ack_inject_args_t *)arg; + + usleep(a->delay_ms * 1000); + for (int i = 0; i < 2; i++) { + if (a->eps[i] != NULL) + repl_on_config_ack(&a->c->persist.repl, a->eps[i], a->tag); + } + return NULL; +} + +/* statics survive Unity longjmp */ +static cb5_ack_inject_args_t g_cb5_ack_inject; + /* ACKs withheld: the push barrier must report -ETIMEDOUT (return value), * the transport push count via acked_out, and the tag must never commit. * RED: the current return value IS the push count (2), and the internal @@ -1516,22 +1546,33 @@ static void test_push_config_withheld_acks_returns_etimedout(void) /* Majority acks (self + 1 covering standby of n_peers=3): the push must * return 0 and commit the tag. RED twice over: the return value is the * push count (2 != 0), and the legacy internal wait (quorum 2 over - * n_active, no self-count) times out so the tag never advances. */ + * n_active, no self-count) times out so the tag never advances. + * The covering ACK is injected from a helper thread mid-barrier: the + * push's own repl_reset_config_acks clears pre-installed acks (see the + * injector comment above). */ static void test_push_config_majority_acks_returns_zero_and_commits(void) { static const uint8_t blob[] = "cb5-push-blob"; uint8_t sha[32]; int pushed = -1; int rc; + pthread_t th; - /* Arrange: one standby has already acked the in-flight tag */ + /* Arrange: one standby acks the in-flight tag while the barrier waits */ cb5_setup(); SHA256(blob, sizeof(blob) - 1, sha); - repl_on_config_ack(&g_cb5_c.persist.repl, &g_cb5_sb_ep[0], 0xAB12); + g_cb5_ack_inject.c = &g_cb5_c; + g_cb5_ack_inject.eps[0] = &g_cb5_sb_ep[0]; + g_cb5_ack_inject.eps[1] = NULL; + g_cb5_ack_inject.tag = 0xAB12; + g_cb5_ack_inject.delay_ms = 700; + TEST_ASSERT_EQUAL_INT(0, pthread_create(&th, NULL, cb5_ack_inject_thread, + &g_cb5_ack_inject)); /* Act */ rc = push_config_to_standbys(&g_cb5_c, blob, sizeof(blob) - 1, sha, 0xAB12, &pushed); + pthread_join(th, NULL); /* Assert */ TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, @@ -1599,10 +1640,11 @@ static void test_upgrade_config_barrier_failure_error_reply_no_restart(void) * restart_requested (Req 1.2/1.3/1.4/2.2/5.4). Materialization is now * driven entirely by the marker-apply trigger (apply_committed_entry's * WAL_CONFIG_MARKER case, persist.c, task 5), decoupled from this - * request-handling path. Both standbys pre-ack UINT64_MAX (covers any tag - * — the new tag is only known after conf_save_config hashes the re-encoded - * blob), so the case is green under both the legacy counting and the - * per-push arithmetic. */ + * request-handling path. Both standbys ack UINT64_MAX from a helper thread + * mid-barrier (covers any tag — the new tag is only known after + * conf_save_config hashes the re-encoded blob, and the push's own + * repl_reset_config_acks clears pre-installed acks; see the injector + * comment above). */ static void test_upgrade_config_majority_ack_success_no_restart(void) { uint8_t *blob; @@ -1610,17 +1652,24 @@ static void test_upgrade_config_majority_ack_success_no_restart(void) uint8_t sha[32]; int rc; cb5_reply_obs_t obs = { 0 }; + pthread_t th; - /* Arrange: full covering pre-ack from both standbys */ + /* Arrange: full covering ACKs from both standbys, injected mid-barrier */ cb5_setup_upgrade(); blob = cb5_make_config_blob(&blen); SHA256(blob, blen, sha); cb5_arrange_upgrade_req(blob, blen, sha); - repl_on_config_ack(&g_cb5_c.persist.repl, &g_cb5_sb_ep[0], UINT64_MAX); - repl_on_config_ack(&g_cb5_c.persist.repl, &g_cb5_sb_ep[1], UINT64_MAX); + g_cb5_ack_inject.c = &g_cb5_c; + g_cb5_ack_inject.eps[0] = &g_cb5_sb_ep[0]; + g_cb5_ack_inject.eps[1] = &g_cb5_sb_ep[1]; + g_cb5_ack_inject.tag = UINT64_MAX; + g_cb5_ack_inject.delay_ms = 700; + TEST_ASSERT_EQUAL_INT(0, pthread_create(&th, NULL, cb5_ack_inject_thread, + &g_cb5_ack_inject)); /* Act */ rc = handle_upgrade_config(&g_cb5_c, &g_cb5_req_ep, &g_cb5_req); + pthread_join(th, NULL); /* Assert: existing success reply unchanged; restart is NOT requested */ TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, @@ -1682,16 +1731,22 @@ static void test_upgrade_config_marker_committed_hook_fires_once_after_commit(vo uint8_t sha[32]; int rc; cb5_reply_obs_t obs = { 0 }; + pthread_t th; extern int (*xce_upgrade_marker_committed_hook)(cluster_t *, uint64_t); - /* Arrange: full covering pre-ack from both standbys (same fixture as - * the no-restart success-path test) */ + /* Arrange: full covering ACKs from both standbys injected mid-barrier + * (same fixture as the no-restart success-path test) */ cb5_setup_upgrade(); blob = cb5_make_config_blob(&blen); SHA256(blob, blen, sha); cb5_arrange_upgrade_req(blob, blen, sha); - repl_on_config_ack(&g_cb5_c.persist.repl, &g_cb5_sb_ep[0], UINT64_MAX); - repl_on_config_ack(&g_cb5_c.persist.repl, &g_cb5_sb_ep[1], UINT64_MAX); + g_cb5_ack_inject.c = &g_cb5_c; + g_cb5_ack_inject.eps[0] = &g_cb5_sb_ep[0]; + g_cb5_ack_inject.eps[1] = &g_cb5_sb_ep[1]; + g_cb5_ack_inject.tag = UINT64_MAX; + g_cb5_ack_inject.delay_ms = 700; + TEST_ASSERT_EQUAL_INT(0, pthread_create(&th, NULL, cb5_ack_inject_thread, + &g_cb5_ack_inject)); g_cb5_hook_calls = 0; g_cb5_hook_last_tag = 0; @@ -1700,6 +1755,7 @@ static void test_upgrade_config_marker_committed_hook_fires_once_after_commit(vo /* Act */ rc = handle_upgrade_config(&g_cb5_c, &g_cb5_req_ep, &g_cb5_req); + pthread_join(th, NULL); /* Assert: fired exactly once, with the just-committed tag, and only * after ha.committed_config_tag already reflects that same tag. */ diff --git a/src/frontend/apiserver/meson.build b/src/frontend/apiserver/meson.build index 41806114..5b3d927b 100644 --- a/src/frontend/apiserver/meson.build +++ b/src/frontend/apiserver/meson.build @@ -17,6 +17,14 @@ if with_debug endif # Deps whose cflags/ldflags must be passed into CGO (transitive libxce deps). +# Nix-world these were all pkg-config resolved, so pkgconfig --cflags/--libs +# per dep name sufficed. In the de-nix wrap-subproject world an internal +# dep has no .pc file -- pkg-config silently no-ops and the flags never +# reach cgo (symptom: fatal error: rtti.h: No such file or directory inside +# go build). Each subproject therefore also exports a '-raw' override +# carrying the same flags the nix pc exposed as raw strings via +# declare_dependency(variables:) -- read them here first, falling back to +# pkg-config for external deps (openssl, math, rt) that have no raw form. apiserver_cgo_deps = [ librtti_dep, c_capnproto_dep, @@ -27,13 +35,20 @@ apiserver_cgo_deps = [ ] foreach dep : apiserver_cgo_deps - cf = run_command(pkgconfig, '--cflags', dep.name(), check: false) - if cf.returncode() == 0 - cgo_cflags += ' ' + cf.stdout().strip() - endif - lf = run_command(pkgconfig, '--libs', dep.name(), check: false) - if lf.returncode() == 0 - cgo_ldflags += ' ' + lf.stdout().strip() + raw_dep_name = dep.name() + '-raw' + raw_dep = dependency(raw_dep_name, required: false) + if raw_dep.found() + cgo_cflags += ' ' + raw_dep.get_variable('cflags') + cgo_ldflags += ' ' + raw_dep.get_variable('ldflags') + else + cf = run_command(pkgconfig, '--cflags', dep.name(), check: false) + if cf.returncode() == 0 + cgo_cflags += ' ' + cf.stdout().strip() + endif + lf = run_command(pkgconfig, '--libs', dep.name(), check: false) + if lf.returncode() == 0 + cgo_ldflags += ' ' + lf.stdout().strip() + endif endif endforeach diff --git a/src/harness/meson.build b/src/harness/meson.build index f1afbf7f..0c939e43 100644 --- a/src/harness/meson.build +++ b/src/harness/meson.build @@ -1,15 +1,15 @@ incdir = include_directories('.', '../include', '../lib', 'include', '../testsuite_support') # case_scratch_sweep.h (bug-924 follow-up) -zlib_dep = dependency('zlib') +zlib_dep = dependency('zlib', version: '>=1.2.11') # BSD-licensed readline replacement (scheduler-core spec, task 12.1 review # finding): GNU readline is GPL; xce_test's REPL only needs readline()/ # add_history(), both provided by libedit's editline/readline.h emulation # header under a permissive license. Single dependency, no separate # ncurses/history split (libedit's own .pc pulls ncurses in privately). -libedit_dep = dependency('libedit') -ssl_dep = dependency('openssl') # also needed by configcompare.c (SHA256()) +libedit_dep = dependency('libedit', version: '>=3.1') +ssl_dep = dependency('openssl', version: '>=3.0') # also needed by configcompare.c (SHA256()) xce_test_src = [ 'test.c', @@ -130,9 +130,6 @@ mkdtemp_clean_lib = static_library( join_paths(meson.source_root(), 'testsuite_support', 'mkdtemp_clean.c'), join_paths(meson.source_root(), 'testsuite_support', 'case_scratch_sweep.c'), - include_directories: [ - include_directories(unity_dep.get_variable('includedir')), - ], dependencies: [unity_dep]) harness_unit_test_deps += declare_dependency(link_with: mkdtemp_clean_lib) diff --git a/src/harness/testsuite/harness_test.c b/src/harness/testsuite/harness_test.c index eb00dda5..939e5760 100644 --- a/src/harness/testsuite/harness_test.c +++ b/src/harness/testsuite/harness_test.c @@ -1,7 +1,11 @@ +#include #include +#include #include #include #include +#include +#include #include @@ -38,6 +42,33 @@ void setUp(void) * the shim's atexit sweep alone leaks every passed case's dirs until * exit; see case_scratch_sweep.h. */ case_scratch_sweep_begin(); + + /* These suites spawn real xce_test processes whose `masters` setting + * defaults to localhost:9990 -- and its CLI-error tests assert the + * no-controller failure path ("xcecli_queuectrl: Invalid argument", + * "xce_reslist: ...") exactly as designed. On a dev box running a live + * cluster on 9990 those RPCs SUCCEED and the assertions fail on + * environment, not code. Pin the env fallback (test.c: + * masters_default_from_env) to a bound-then-closed loopback port: the + * kernel RSTs every connection to it deterministically, and an explicit + * `set masters` in a test still overrides this default. */ + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd >= 0) { + struct sockaddr_in addr; + int deadport = 19999; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons((uint16_t)deadport); + + if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { + char val[32]; + snprintf(val, sizeof(val), "127.0.0.1:%d", deadport); + setenv("XCE_CONTROLLER_PEERS", val, /*overwrite=*/1); + } + close(fd); /* the port is now free with no listener: ECONNREFUSED */ + } } void tearDown(void) diff --git a/src/harness/testsuite/test_test_cli.c b/src/harness/testsuite/test_test_cli.c index bd6f4b72..fbd62bed 100644 --- a/src/harness/testsuite/test_test_cli.c +++ b/src/harness/testsuite/test_test_cli.c @@ -371,6 +371,18 @@ static int clitest_spawn_ex(clitest_session_t* sess, const char* path, close(errpipe[1]); } + /* Own process group. libedit's readline() installs process-wide + * signal handlers and, when a signal lands on ANY thread (here: + * the io_worker mid-SSL-handshake after a failed reconnect), its + * sig_handler restores the saved disposition and RE-RAISES via + * kill(0, sig) -- the whole process GROUP (NetBSD libedit sig.c). + * Without setpgid the child shares our pgrp, so a re-raised + * SIGINT kills this harness process (observed: suite exits 130 + * mid-test). A real terminal gives each interactive job its own + * pgrp for exactly this reason; mirror that. clitest_send_signal() + * addresses the child by pid, so delivery is unaffected. */ + setpgid(0, 0); + execv(path, argv); _exit(127); /* only reached if execv() itself failed */ } diff --git a/src/include/repl.h b/src/include/repl.h index c767e3db..83d3a91f 100644 --- a/src/include/repl.h +++ b/src/include/repl.h @@ -109,6 +109,16 @@ void repl_on_ack(replicator_t *r, repl_ep_t ep, uint64_t acked_lsn); /* Config ACK handling — call from io_worker read callback ONLY (task 8.1) */ void repl_on_config_ack(replicator_t *r, repl_ep_t ep, uint64_t acked_config_lsn); +/* Clear every standby's acked_config_lsn (all slots, under r->lock). Call + * immediately BEFORE fanning out a new config push: config tags are + * SHA-256-derived, NOT monotonic, so a previous push's ack can numerically + * exceed the new push tag and repl_wait_majority_ack's + * acked_config_lsn >= push_tag coverage test would fabricate a quorum from + * stale acks before the new bytes even reach the standbys (observed live: + * bootstrap tag 0x8928... numerically > upgrade tag 0x0dd1... — the + * barrier returned success with zero standbys having seen the new bytes). */ +void repl_reset_config_acks(replicator_t *r); + /* Sync replication (stub in P2-1; wired in P2-3) */ int repl_wait_ack(replicator_t *r, uint64_t target_lsn, uint32_t timeout_ms); diff --git a/src/lib/meson.build b/src/lib/meson.build index adb972d8..e103c724 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -1,13 +1,23 @@ +fs = import('fs') + capnp = find_program('capnp') packcc = find_program('packcc') +# capnp's `-o c:` plugin lookup execs 'capnpc-c' via PATH -- the meson +# program override (wrap subproject) does not extend PATH, so wrap the +# command with env and prepend the overridden binary's directory. Listing +# capnpc_c in the command (as a no-op first token via env's PATH arg) is not +# enough for ordering; the custom target below also depends on it. +capnpc_c = find_program('capnpc-c') schema_dir = meson.current_source_dir() / '..' / 'schema' gen_srcs = custom_target( 'controllercapnp.[ch]', output:['controller.capnp.c', 'controller.capnp.h'], - input: '../schema/controller.capnp', - command: [capnp, 'compile','-o' ,'c:lib', '-I', schema_dir, '--src-prefix', schema_dir, '@INPUT@'] + input: ['../schema/controller.capnp', capnpc_c], + command: [env_program, 'PATH=' + fs.parent(capnpc_c.full_path()) + ':/usr/bin:/bin', + capnp, 'compile','-o' ,'c:lib', '-I', schema_dir, '--src-prefix', schema_dir, + '@INPUT0@'] ) section_parser = custom_target( @@ -144,7 +154,7 @@ thread_dep = dependency('threads') c_capnproto_dep = dependency('c-capnproto') tinylog_dep = dependency('tinylog') unity_dep = dependency('unity') -ssl_dep = dependency('openssl') +ssl_dep = dependency('openssl', version: '>=3.0') libxce_deps = [c_capnproto_dep, ssl_dep, tinylog_dep, thread_dep, librtti_dep] @@ -171,7 +181,8 @@ libxce = static_library('xce', # for consumers OUTSIDE the libxce target itself. link_with alone does not # propagate this: it only orders the LINK step after libxce is built, not # a consumer's own COMPILE steps against a header libxce never installs. -libxce_dep = declare_dependency(link_with: libxce, sources: [gen_srcs]) +libxce_dep = declare_dependency(link_with: libxce, sources: [gen_srcs], + dependencies: libxce_deps) # libxce_shared_dep = declare_dependency(link_with: libxce_shared) libxce_test_src = ['testsuite/test.c', @@ -241,12 +252,11 @@ libxce_test_src = ['testsuite/test.c', libxce_test_deps = [libxce_deps, librtti_dep, unity_dep, libxce_dep] libxce_test = executable('xcelib_test', libxce_test_src, - # unity.pc's Cflags only adds -I${includedir}/unity, so - # resolves but (used by several - # suites) does not — add the parent includedir as well. - include_directories: [incdir, build_inc, - include_directories( - unity_dep.get_variable('includedir'))], + # and both resolve through + # unity_dep itself: the wrap-path override (or the nix + # pc under the legacy build) carries the include roots + # for both layouts. + include_directories: [incdir, build_inc], dependencies: libxce_test_deps, c_args: ['-DXCE_TESTING'], install: true) diff --git a/src/lib/raft/raft.c b/src/lib/raft/raft.c index deeb8e08..0c1b4c8f 100644 --- a/src/lib/raft/raft.c +++ b/src/lib/raft/raft.c @@ -74,6 +74,18 @@ int raft_init(raft_state_t *s, const raft_config_t *cfg) * first election (mirrors pre_vote_replies). raft_start_election re-clears * them, but zero here so a never-elected node has a clean array. */ memset(s->vote_replies, 0, sizeof(s->vote_replies)); + /* Pre-vote tally state too: raft_init deliberately initializes only the + * real-vote fields above, so a fresh node's pre_vote_in_progress / + * pre_vote_replies[] / pre_votes_granted were previously left at whatever + * the caller's storage happened to hold. raft_on_pre_vote_reply's no-round + * guard keys on pre_vote_in_progress and the tally reads pre_vote_replies + * directly -- uninitialized values there made "reply without a round" a + * noop only when the stack garbage was zero (observed as a deterministic + * test failure once the stack layout changed). Zero them so the documented + * "no round in progress" behavior is unconditional. */ + s->pre_vote_in_progress = 0; + s->pre_votes_granted = 0; + memset(s->pre_vote_replies, 0, sizeof(s->pre_vote_replies)); s->election_decided = 0; s->election_timeout_ms = cfg->election_timeout_ms ? cfg->election_timeout_ms : 2000; s->my_priority = cfg->my_priority; diff --git a/src/meson.build b/src/meson.build index 62075ed5..675fbc3e 100644 --- a/src/meson.build +++ b/src/meson.build @@ -37,6 +37,10 @@ go_build = files('tools/go_build') go_build_program = find_program('go_build', go_build) env_program = find_program('env') +# System-library floors shared across components (DEPS.md "C 库依赖" table). +libuv_dep = dependency('libuv', version: '>=1.44') +ssl_dep = dependency('openssl', version: '>=3.0') + if component != 'xcecli' c_compiler_id = meson.get_compiler('c').get_id() if c_compiler_id == 'gcc' or c_compiler_id == 'clang' @@ -52,11 +56,14 @@ if component != 'xcecli' math_dep = cc.find_library('m', required: false) rt_dep = cc.find_library('rt', required: false) - struct2json_dep = dependency('struct2json') - libcyaml_dep = dependency('libcyaml') - libyaml_dep = dependency('yaml-0.1') - libtirpc_dep = dependency('libtirpc') - librtti_dep = dependency('librtti') + # Version floors mirror DEPS.md (Ubuntu 24.04 LTS baseline). Subproject + # deps (librtti, struct2json, tinylog, c-capnproto, unity) resolve via + # src/subprojects/*.wrap when not found on the host. + struct2json_dep = dependency('struct2json', version: '>=1.0.0') + libcyaml_dep = dependency('libcyaml', version: '>=1.2') + libyaml_dep = dependency('yaml-0.1', version: '>=0.2.5') + libtirpc_dep = dependency('libtirpc', version: '>=1.3') + librtti_dep = dependency('librtti', version: '>=0.0.2') yaml_deps = [ libcyaml_dep, diff --git a/src/meson.options b/src/meson.options index ba1bd525..0b785274 100644 --- a/src/meson.options +++ b/src/meson.options @@ -6,3 +6,5 @@ option('component', type: 'combo', choices: ['all', 'xcecore', 'xcecli'], value: 'all', description: 'Which component(s) to build: all (default, for dev), xcecore (C stack + apiserver), xcecli (CLI only)') +option('use_elogind', type: 'boolean', value: false, + description: 'Link libelogind instead of libsystemd for sd-bus (non-systemd platforms)') diff --git a/src/scheduler/meson.build b/src/scheduler/meson.build index 51658d06..f5d3f2ff 100644 --- a/src/scheduler/meson.build +++ b/src/scheduler/meson.build @@ -65,7 +65,7 @@ incdir = include_directories('src', # emulation header provides the same two calls under a permissive license; # src/controller/meson.build (xce_test's own REPL) uses the identical dep # for the same reason, kept consistent project-wide. -libedit_dep = dependency('libedit') +libedit_dep = dependency('libedit', version: '>=3.1') scheduler_deps = [ libxce_dep, diff --git a/src/scheduler/testsuite/meson.build b/src/scheduler/testsuite/meson.build index ff61641d..c90a240e 100644 --- a/src/scheduler/testsuite/meson.build +++ b/src/scheduler/testsuite/meson.build @@ -26,11 +26,10 @@ mkdtemp_clean_lib = static_library( join_paths(meson.source_root(), 'testsuite_support', 'mkdtemp_clean.c')) scheduler_test_deps += declare_dependency(link_with: mkdtemp_clean_lib) -# unity.pc's Cflags only adds -I${includedir}/unity, so resolves -# but (used by every suite) does not — add the parent -# includedir as well (same fix as src/lib/meson.build). -incdir = include_directories('../include', '../../include', '.', '../src', '../../lib', - unity_dep.get_variable('includedir')) +# and both resolve through unity_dep itself: the +# wrap-path override (or the nix pc under the legacy build) carries the +# include roots for both layouts (same change as src/lib/meson.build). +incdir = include_directories('../include', '../../include', '.', '../src', '../../lib') scheduler_test = executable('sched_test', scheduler_test_src, diff --git a/src/subprojects/c-capnproto.wrap b/src/subprojects/c-capnproto.wrap new file mode 100644 index 00000000..23b2f132 --- /dev/null +++ b/src/subprojects/c-capnproto.wrap @@ -0,0 +1,11 @@ +[wrap-git] +directory = c-capnproto +url = ssh://forgejo@gitea.shenrs.eu/rshen/c-capnproto +revision = 368511ace77cc833c6b5b1f7d225a9b87e3f4687 +depth = 1 +patch_directory = c-capnproto +diff_files = c-capnproto.patch + +[provide] +dependency_names = c-capnproto, c-capnproto-raw +program_names = capnpc-c diff --git a/src/subprojects/c-capnproto/.github/workflows/ci.yml b/src/subprojects/c-capnproto/.github/workflows/ci.yml new file mode 100644 index 00000000..e73d312f --- /dev/null +++ b/src/subprojects/c-capnproto/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: "CI Unit Tests" + +on: + push: + branches: + - master + pull_request: + +jobs: + Normal: + runs-on: ubuntu-20.04 + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install meson and ninja + run: pip3 install --user meson ninja + - name: Run Unit Tests + run: | + export PATH=${HOME}/.local/bin:${PATH} + meson setup -Dbuildtype=release build + meson compile -C build + build/capn-test + + Sanitizers: + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install meson and ninja + run: pip3 install --user meson ninja + - name: Run Unit Tests with ASAN + env: + ASAN_OPTIONS: detect_leaks=0,detect_odr_violation=0,allocator_may_return_null=1 + run: | + export PATH=${HOME}/.local/bin:${PATH} + meson setup -Dbuildtype=debugoptimized -Db_sanitize=address,undefined build + meson compile -C build + build/capn-test diff --git a/src/subprojects/c-capnproto/.gitignore b/src/subprojects/c-capnproto/.gitignore new file mode 100644 index 00000000..aaf63f21 --- /dev/null +++ b/src/subprojects/c-capnproto/.gitignore @@ -0,0 +1,41 @@ +aclocal.m4 +autom4te*.cache +configure +config.h* +confdefs.h +config.status +libtool +stamp-h* + +Makefile +Makefile.in +.deps +.libs +.dirstamp + +test-driver +*.log +*.trs + +tests/*.out + +*.o +*.a +*.so +*.lo +*.la + +capn-test +capnpc-c +c-capnproto.pc + +*.tar.gz + +subprojects/googletest-* +subprojects/packagecache + +/build/ +/build_dev/ +/.ci/ + +/CMakeUserPresets.json diff --git a/src/subprojects/c-capnproto/.gitlab-ci.yml b/src/subprojects/c-capnproto/.gitlab-ci.yml new file mode 100644 index 00000000..05efd644 --- /dev/null +++ b/src/subprojects/c-capnproto/.gitlab-ci.yml @@ -0,0 +1,67 @@ +.conda-c-cmake:before: + # Use: + # docker run -it --platform linux/amd64 continuumio/miniconda3:22.11.1 + # to test out on a local developer machine (including macOS/ARM64 Silicon) + image: continuumio/miniconda3:22.11.1 + variables: + CONDA_PKGS_DIRS: "$CI_PROJECT_DIR/.conda-pkgs-cache" + PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" + DEBIAN_FRONTEND: noninteractive + + cache: + key: + files: + - environment.yml + prefix: cachebust1 + paths: + - .ci + # Technique explained at https://damiankula.com/using_conda_cache_in_gitlabci.html + - $CONDA_PKGS_DIRS/*.conda + - $CONDA_PKGS_DIRS/*.tar.bz2 + - $CONDA_PKGS_DIRS/urls* + - $CONDA_PKGS_DIRS/cache + # yay, we don't use pip: - $PIP_CACHE_DIR + + before_script: + # Update/install system pkgs first, so conda can use latest system pkgs. + - apt-get update + # Install Ninja + rsync. + # ninja: CMake configure + # build-essential: CMake project(LANGUAGES C) + - apt-get install -qq -o=Dpkg::Use-Pty=0 ninja-build build-essential > /dev/null + # Install CMake + - ./dk dksdk.cmake.link + + # Install Python + - conda env create --quiet -f environment.yml + +.c-cmake-debian:before: + image: debian:stable-slim + variables: + DEBIAN_FRONTEND: noninteractive # for apt-get + before_script: + # Update/install system pkgs first, so conda can use latest system pkgs. + - apt-get update + # Install Ninja and C compiler + # ninja: CMake configure + # clang-tidy: CMake -D BUILD_HYGIENE=ENABLED (or the unset default) + # wget: ci/install-cmake.sh + # build-essential: CMake project(LANGUAGES C) + # git: CMake FetchContent() + # valgrind: ctest -T memcheck + - apt-get install -qq -o=Dpkg::Use-Pty=0 ninja-build clang-tidy wget build-essential git valgrind > /dev/null + # Install CMake + - ./dk dksdk.cmake.link + +.c-cmake-windows:before: + tags: [shared-windows, windows, windows-1809] + variables: + VSDIR: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools + DKSDK_NINJA_PROGRAM: "$CI_PROJECT_DIR\\.ci\\ninja\\bin\\ninja.exe" + before_script: + # https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/main/cookbooks/preinstalled-software/README.md + # CMake is already present on GitLab CI/CD. No 'choco install -y cmake' (choco frequents gets HTTP 403) or './dk dksdk.cmake.link' needed + - ./dk dksdk.ninja.link + +include: + - local: ci/gitlab/test.gitlab-ci.yml diff --git a/src/subprojects/c-capnproto/.gitmodules b/src/subprojects/c-capnproto/.gitmodules new file mode 100644 index 00000000..e69de29b diff --git a/src/subprojects/c-capnproto/.travis.yml b/src/subprojects/c-capnproto/.travis.yml new file mode 100644 index 00000000..4b87ba2c --- /dev/null +++ b/src/subprojects/c-capnproto/.travis.yml @@ -0,0 +1,20 @@ +language: cpp + +# need at least gcc 4.8 for -std=c++11 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.8 + - g++-4.8 + +# use gcc-4.8 +install: +- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi + +script: autoreconf -f -i -s && ./configure --without-gtest && make && make check + +compiler: +- clang +- gcc diff --git a/src/subprojects/c-capnproto/.vscode/settings.json b/src/subprojects/c-capnproto/.vscode/settings.json new file mode 100644 index 00000000..ff49149b --- /dev/null +++ b/src/subprojects/c-capnproto/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "cmake.configureOnOpen": false, + "sonarlint.pathToCompileCommands": "${workspaceFolder}/build_dev/compile_commands.json" +} \ No newline at end of file diff --git a/src/subprojects/c-capnproto/CHANGES.md b/src/subprojects/c-capnproto/CHANGES.md new file mode 100644 index 00000000..b1c21488 --- /dev/null +++ b/src/subprojects/c-capnproto/CHANGES.md @@ -0,0 +1,37 @@ +# Changes + +## 0.9.1 + +- (backwards incompatible) Add CMake cache variable `BUILD_SHARED_LIBS`. + The default is a static library for mobile (Android and iOS), and a + shared library otherwise; that is the same pattern followed by opencv. + The variable should be explicitly set to `ON` if a shared library must + be created, and `OFF` if a static library must be created. +- Use GoogleTest 1.14.0 and enable tests only when C++14 compiler available. +- Support building into shared libraries on Windows: +- `extraheader` attribute: Extra `#include ` or any other + preprocessor statements in auto-generated header file. +- `extendedattribute` attribute: Text in front of auto-generated functions, + like `__declspec(dllexport)` +- Add target variants `CapnC::Runtime-Shared`, `CapnC::Runtime-Static` and + `CapnC::Runtime-StaticExports` +- Hygiene only runs when the project is top-level. + +## 0.9.0 + +- Forked to the DkML repository on GitLab. +- Use binary mode when reading schemas on Windows +- Use SSIZE_T from `BaseTsd.h` to allow MSVC to compile with 32-bits +- Put alignment on segment fields, not just the structure. +- Avoids left shifts of signed integers, which is undefined C behavior. Passes + ASAN (not a false positive) +- Wrap macro parameters in the `capnp_use(x)` macro. Passes clang-tidy (not + a false positive) +- Add POSITION_INDEPENDENT_CODE to CapnC::Runtime +- Add C_CAPNPROTO_ENABLE_INSTALL with default ON to turn off and on + installation of targets and files in `cmake --install`, especially for when + this project is used within a FetchContent() command. + +## 0.3 (632f0d73a1f4a03026b5e4727386b9fe3ec6e00e) + +- Fork of `c-capnproto-0.3` plus several untagged commits from https://github.com/opensourcerouting/c-capnproto on Apr 23, 2023. Specifically: https://github.com/opensourcerouting/c-capnproto/commit/632f0d73a1f4a03026b5e4727386b9fe3ec6e00e diff --git a/src/subprojects/c-capnproto/CMakeLists.txt b/src/subprojects/c-capnproto/CMakeLists.txt new file mode 100644 index 00000000..a6c0313e --- /dev/null +++ b/src/subprojects/c-capnproto/CMakeLists.txt @@ -0,0 +1,181 @@ +cmake_minimum_required(VERSION 3.22) +if(BUILD_TESTING OR NOT DEFINED BUILD_TESTING) + # The tests are C++ + set(languages C CXX) +else() + set(languages C) +endif() +project(c-capnproto LANGUAGES ${languages}) + +configure_file(c-capnproto.pc.in c-capnproto.pc @ONLY) + +include(CTest) + +# set(CMAKE_C_STANDARD 11) +# set(CMAKE_C_EXTENSIONS NO) +if(BUILD_TESTING) + set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_EXTENSIONS NO) +endif() + +# Stop noise if CXX compiler is set. +set(ignoreAndAvoidCMakeUnusedWarning "${CMAKE_CXX_COMPILER}") + +# Boilerplate DK CMAKE PROJ 2023-05-17.1 +if(APPLE) + set(CMAKE_MACOSX_RPATH OFF) +endif() + +# Boilerplate DK CMAKE PROJ 2023-09-25.1 +set(default_build_shared) +if(NOT (ANDROID OR IOS)) + set(default_build_shared ON) +endif() +option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" ${default_build_shared}) + +# Build hygiene: Tools for keeping the source code clean. By default +# we try to enforce build hygiene. +# You can override with either BUILD_HYGIENE=DISABLED or +# BUILD_HYGIENE=ENABLED. +# Hygiene is only done if the project is top-level. +if(PROJECT_IS_TOP_LEVEL AND NOT BUILD_HYGIENE STREQUAL DISABLED) + if(BUILD_HYGIENE STREQUAL ENABLED) + set(find_program_args REQUIRED) + else() + set(find_program_args) + endif() + find_program(CLANG_TIDY_PROGRAM + NAMES clang-tidy + PATHS + # On macOS the easiest way to get clang-tidy is to install the + # keg-only (not installed into PATH) big `llvm` package. + /opt/homebrew/opt/llvm/bin + /usr/local/opt/llvm/bin + ${find_program_args}) +endif() + +# add_runtime_library( +# NAME_SUFFIX +# [EXCLUDE_FROM_ALL] +# [MODE STATIC|STATIC_EXPORTS|SHARED] +# ) +# +# Without a MODE the library is built according to CMake conventions (BUILD_SHARED_LIBS). +# +# NAME_SUFFIX +# A suffix added to the CMake names. +# +# The target will be named `CapnC_Runtime`. +# The alias will be named `CapnC::Runtime`. +# +# EXCLUDE_FROM_ALL +# +# Do not add the library to the ALL target. +# +# MODE STATIC|STATIC_EXPORTS|SHARED +# +# STATIC +# Build a static library without export symbols, regardless of BUILD_SHARED_LIBS. +# +# STATIC_EXPORTS +# Build a static library with export symbols, regardless of BUILD_SHARED_LIBS. +# +# SHARED +# Build a shared library, regardless of BUILD_SHARED_LIBS. +function(add_runtime_library) + set(noValues EXCLUDE_FROM_ALL) + set(singleValues NAME_SUFFIX MODE) + set(multiValues) + cmake_parse_arguments(PARSE_ARGV 0 ARG "${noValues}" "${singleValues}" "${multiValues}") + + # Nice names which can be used without shadowing even in add_subdirectory() + set(C_CAPNPROTO_ALIAS CapnC::Runtime${ARG_NAME_SUFFIX}) + set(C_CAPNPROTO_TARGET CapnC_Runtime${ARG_NAME_SUFFIX}) + set(C_CAPNPROTO_EXPORTS ${BUILD_SHARED_LIBS}) + set(C_CAPNPROTO_LINKAGE) + set(PROP_EXCLUDE_FROM_ALL) + if(ARG_EXCLUDE_FROM_ALL) + set(PROP_EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL) + endif() + if(NOT ARG_MODE) + elseif(ARG_MODE STREQUAL STATIC) + set(C_CAPNPROTO_EXPORTS OFF) + set(C_CAPNPROTO_LINKAGE STATIC) + elseif(ARG_MODE STREQUAL STATIC_EXPORTS) + set(C_CAPNPROTO_EXPORTS ON) + set(C_CAPNPROTO_LINKAGE STATIC) + elseif(ARG_MODE STREQUAL SHARED) + set(C_CAPNPROTO_EXPORTS ON) + set(C_CAPNPROTO_LINKAGE SHARED) + else() + message(FATAL_ERROR "No [MODE ${ARG_MODE}] is supported") + endif() + + add_library(${C_CAPNPROTO_TARGET} ${C_CAPNPROTO_LINKAGE} ${PROP_EXCLUDE_FROM_ALL} + lib/capn.c + lib/capn-malloc.c + lib/capn-stream.c + lib/capnp_c.h) + add_library(${C_CAPNPROTO_ALIAS} ALIAS ${C_CAPNPROTO_TARGET}) + set_target_properties(${C_CAPNPROTO_TARGET} PROPERTIES + EXPORT_NAME Runtime${ARG_NAME_SUFFIX} + POSITION_INDEPENDENT_CODE ON + WINDOWS_EXPORT_ALL_SYMBOLS ON) + target_include_directories(${C_CAPNPROTO_TARGET} + PUBLIC + $ + $ + $) + if(C_CAPNPROTO_EXPORTS) + set_target_properties(${C_CAPNPROTO_TARGET} PROPERTIES + WINDOWS_EXPORT_ALL_SYMBOLS ON) + endif() +endfunction() + +add_runtime_library() +add_runtime_library(NAME_SUFFIX -Shared EXCLUDE_FROM_ALL MODE SHARED) +add_runtime_library(NAME_SUFFIX -Static EXCLUDE_FROM_ALL MODE STATIC) +add_runtime_library(NAME_SUFFIX -StaticExports EXCLUDE_FROM_ALL MODE STATIC_EXPORTS) + +add_executable(capnpc-c + compiler/capnpc-c.c + compiler/schema.capnp.c + compiler/str.c) +target_link_libraries(capnpc-c CapnC::Runtime) +target_include_directories(capnpc-c + PRIVATE lib) + +# Boilerplate DK CMAKE PROJ 2023-05-17.3 +if(BUILD_SHARED_LIBS) + if(APPLE) + set(base @loader_path) + else() + set(base $ORIGIN) + endif() + file(RELATIVE_PATH relDir + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + set(CMAKE_INSTALL_RPATH + # best practice RPATH locations when installed + ${base} + ${base}/${relDir}) +endif() + +option(C_CAPNPROTO_ENABLE_INSTALL "Add instructions for 'cmake --install' of CapnC_Runtime library and capnpc-c executable" ON) +if(C_CAPNPROTO_ENABLE_INSTALL) + set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib) + install(TARGETS CapnC_Runtime capnpc-c + EXPORT CapnC) + install(EXPORT CapnC + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CapnC + NAMESPACE CapnC:: + FILE CapnCConfig.cmake) + install(FILES lib/capnp_c.h TYPE INCLUDE) + install(FILES build/c-capnproto.pc + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +endif() + +add_subdirectory(examples/book) +if(BUILD_TESTING AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + add_subdirectory(tests) +endif() diff --git a/src/subprojects/c-capnproto/CMakePresets.json b/src/subprojects/c-capnproto/CMakePresets.json new file mode 100644 index 00000000..9e75d487 --- /dev/null +++ b/src/subprojects/c-capnproto/CMakePresets.json @@ -0,0 +1,306 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 22 + }, + "configurePresets": [ + { + "name": "ci-agnostic-configure", + "binaryDir": "build", + "hidden": true, + "description": "ABI-agnostic CI configuration for build and test presets" + }, + { + "name": "ci-tests-configure", + "inherits": [ + "ci-agnostic-configure" + ], + "cacheVariables": { + "BUILD_TESTING": "ON" + } + }, + { + "name": "ci-clang_gcc-sanitizers-asan", + "description": "Address sanitizer for clang and GCC", + "cacheVariables": { + "BUILD_TESTING": "ON", + "CMAKE_C_FLAGS_INIT": "-fsanitize=address -fno-sanitize-recover=all", + "CMAKE_EXE_LINKER_FLAGS_INIT": "-fsanitize=address -fno-sanitize-recover=all", + "CMAKE_C_FLAGS_INIT_REASONS": "https://developers.redhat.com/blog/2021/05/05/memory-error-checking-in-c-and-c-comparing-sanitizers-and-valgrind. Because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94328 ASAN and UBSAN don't work together with [log_path] which is needed for CTest" + } + }, + { + "name": "ci-clang_gcc-sanitizers-ubsan", + "description": "Undefined behavior sanitizer for clang and GCC", + "cacheVariables": { + "BUILD_TESTING": "ON", + "CMAKE_C_FLAGS_INIT": "-fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment", + "CMAKE_EXE_LINKER_FLAGS_INIT": "-fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment", + "CMAKE_C_FLAGS_INIT_REASONS": "https://developers.redhat.com/blog/2021/05/05/memory-error-checking-in-c-and-c-comparing-sanitizers-and-valgrind. Because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94328 ASAN and UBSAN don't work together with [log_path] which is needed for CTest" + } + }, + { + "name": "ci-host-windows_x86", + "hidden": true, + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": "$env{DKSDK_NINJA_PROGRAM}", + "ENV-DKSDK_NINJA_PROGRAM": "Set the environment variable DKSDK_NINJA_PROGRAM to the path to ninja.exe" + } + }, + { + "name": "ci-target-windows_x86", + "hidden": true, + "generator": "Ninja", + "architecture": { + "value": "x86", + "strategy": "external" + } + }, + { + "name": "ci-host-windows_x86_64", + "hidden": true, + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": "$env{DKSDK_NINJA_PROGRAM}", + "ENV-DKSDK_NINJA_PROGRAM": "Set the environment variable DKSDK_NINJA_PROGRAM to the path to ninja.exe" + } + }, + { + "name": "ci-target-windows_x86_64", + "hidden": true, + "generator": "Ninja", + "architecture": { + "value": "x64", + "strategy": "external" + } + }, + { + "name": "ci-host-linux_x86", + "hidden": true + }, + { + "name": "ci-target-linux_x86", + "hidden": true + }, + { + "name": "ci-host-linux_x86_64", + "hidden": true + }, + { + "name": "ci-target-linux_x86_64", + "hidden": true + }, + { + "name": "ci-host-darwin_arm64", + "hidden": true, + "cacheVariables": { + "CMAKE_APPLE_SILICON_PROCESSOR": "arm64" + } + }, + { + "name": "ci-target-darwin_arm64", + "hidden": true, + "cacheVariables": { + "CMAKE_OSX_ARCHITECTURES": "arm64", + "CMAKE_EXE_LINKER_FLAGS": "-arch arm64", + "CMAKE_MODULE_LINKER_FLAGS": "-arch arm64", + "CMAKE_SHARED_LINKER_FLAGS": "-arch arm64", + "CMAKE_C_COMPILER": "/usr/bin/clang", + "CMAKE_CXX_COMPILER": "/usr/bin/clang++" + }, + "environment": { + "CMAKE_x_LINKER_FLAGS_REASON": "DkSDK OCaml uses a single target architecture", + "CMAKE_x_COMPILER_REASON": "Direct use of /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc (14.0.0) will fail to link with -lm, -lSystem, etc." + } + }, + { + "name": "ci-host-darwin_x86_64", + "hidden": true, + "cacheVariables": { + "CMAKE_APPLE_SILICON_PROCESSOR": "x86_64" + } + }, + { + "name": "ci-target-darwin_x86_64", + "hidden": true, + "cacheVariables": { + "CMAKE_OSX_ARCHITECTURES": "x86_64", + "CMAKE_EXE_LINKER_FLAGS": "-arch x86_64", + "CMAKE_MODULE_LINKER_FLAGS": "-arch x86_64", + "CMAKE_SHARED_LINKER_FLAGS": "-arch x86_64", + "CMAKE_C_COMPILER": "/usr/bin/clang", + "CMAKE_CXX_COMPILER": "/usr/bin/clang++" + }, + "environment": { + "CMAKE_x_LINKER_FLAGS_REASON": "DkSDK OCaml uses a single target architecture", + "CMAKE_x_COMPILER_REASON": "Direct use of /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc (14.0.0) will fail to link with -lm, -lSystem, etc." + } + }, + { + "name": "ci-darwin_x86_64", + "inherits": [ + "ci-tests-configure", + "ci-host-darwin_x86_64", + "ci-target-darwin_x86_64" + ], + "displayName": "darwin_x86_64", + "description": "Test builds for darwin_x86_64", + "generator": "Ninja" + }, + { + "name": "ci-linux_x86_64", + "inherits": [ + "ci-tests-configure", + "ci-host-linux_x86_64", + "ci-target-linux_x86_64" + ], + "displayName": "linux_x86_64", + "description": "Test builds for linux_x86_64", + "generator": "Ninja" + }, + { + "name": "ci-linux_x86_64-sanitizers-asan", + "inherits": [ + "ci-tests-configure", + "ci-host-linux_x86_64", + "ci-target-linux_x86_64", + "ci-clang_gcc-sanitizers-asan" + ], + "displayName": "linux_x86_64-sanitizers-asan", + "description": "Address Sanitizer builds for linux_x86_64", + "generator": "Ninja" + }, + { + "name": "ci-linux_x86_64-sanitizers-ubsan", + "inherits": [ + "ci-tests-configure", + "ci-host-linux_x86_64", + "ci-target-linux_x86_64", + "ci-clang_gcc-sanitizers-ubsan" + ], + "displayName": "linux_x86_64-sanitizers-ubsan", + "description": "Undefined Behavior Sanitizer builds for linux_x86_64", + "generator": "Ninja" + }, + { + "name": "ci-target-android", + "hidden": true, + "cacheVariables": { + "ANDROID_PLATFORM": "android-21", + "ANDROID_NDK": "$env{DKSDK_PROJECT_BASE}.ci/local/share/android-sdk/ndk/23.1.7779620", + "BUILD_HYGIENE": "DISABLED" + }, + "environment": { + "ANDROID_x_REASON": "https://developer.android.com/studio/projects/configure-cmake#call-cmake-cli", + "BUILD_HYGIENE_REASON": "Android has a stdlib.h that does not pass clang-tidy validation" + }, + "toolchainFile": "$env{DKSDK_PROJECT_BASE}.ci/local/share/android-sdk/ndk/23.1.7779620/build/cmake/android.toolchain.cmake" + }, + { + "name": "ci-target-android_arm32v7a", + "hidden": true, + "inherits": [ "ci-target-android" ], + "cacheVariables": { + "ANDROID_ABI": "armeabi-v7a" + } + }, + { + "name": "ci-target-android_arm64v8a", + "hidden": true, + "inherits": [ "ci-target-android" ], + "cacheVariables": { + "ANDROID_ABI": "arm64-v8a" + } + }, + { + "name": "ci-target-android_x86", + "hidden": true, + "inherits": [ "ci-target-android" ], + "cacheVariables": { + "ANDROID_ABI": "x86" + } + }, + { + "name": "ci-target-android_x86_64", + "hidden": true, + "inherits": [ "ci-target-android" ], + "cacheVariables": { + "ANDROID_ABI": "x86_64" + } + }, + { + "name": "ci-linux_x86_X_android_x86", + "inherits": [ + "ci-tests-configure", + "ci-host-linux_x86", + "ci-target-android_x86" + ], + "displayName": "linux_x86 -> android_x86", + "description": "Cross-compiler of host linux_x86 to target android_x86", + "generator": "Ninja" + }, + { + "name": "ci-linux_x86_X_android_arm32v7a", + "inherits": [ + "ci-tests-configure", + "ci-host-linux_x86", + "ci-target-android_arm32v7a" + ], + "displayName": "linux_x86 -> android_arm32v7a", + "description": "Cross-compiler of host linux_x86 to target android_arm32v7a", + "generator": "Ninja" + }, + { + "name": "ci-linux_x86_64_X_android_x86_64", + "inherits": [ + "ci-tests-configure", + "ci-host-linux_x86_64", + "ci-target-android_x86_64" + ], + "displayName": "linux_x86_64 -> android_x86_64", + "description": "Cross-compiler of host linux_x86_64 to target android_x86_64", + "generator": "Ninja" + }, + { + "name": "ci-linux_x86_64_X_android_arm64v8a", + "inherits": [ + "ci-tests-configure", + "ci-host-linux_x86_64", + "ci-target-android_arm64v8a" + ], + "displayName": "linux_x86_64 -> android_arm64v8a", + "description": "Cross-compiler of host linux_x86_64 to target android_arm64v8a", + "generator": "Ninja" + }, + { + "name": "ci-windows_x86_64", + "inherits": [ + "ci-tests-configure", + "ci-host-windows_x86_64", + "ci-target-windows_x86_64" + ], + "displayName": "windows_x86_64", + "description": "Test builds for windows_x86_64", + "generator": "Ninja" + } + ], + "buildPresets": [ + { + "name": "ci-tests-build", + "hidden": true, + "configurePreset": "ci-tests-configure", + "configuration": "Release" + }, + { + "name": "ci-tests", + "inherits": "ci-tests-build", + "targets": ["all"] + } + ], + "testPresets": [ + { + "name": "ci-test", + "configurePreset": "ci-tests-configure" + } + ] +} diff --git a/src/subprojects/c-capnproto/CMakeUserPresets-SUGGESTED.json b/src/subprojects/c-capnproto/CMakeUserPresets-SUGGESTED.json new file mode 100644 index 00000000..9ed0c8eb --- /dev/null +++ b/src/subprojects/c-capnproto/CMakeUserPresets-SUGGESTED.json @@ -0,0 +1,86 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "dev-AppleSilicon", + "inherits": [ + "ci-host-darwin_arm64", + "ci-target-darwin_arm64" + ], + "displayName": "Dev Apple Silicon", + "generator": "Ninja", + "binaryDir": "build_dev", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "macOS" + ] + } + } + }, + { + "name": "dev-Linux-x86_64", + "inherits": [ + "ci-host-linux_x86_64", + "ci-target-linux_x86_64" + ], + "displayName": "Dev Linux x86_64", + "generator": "Ninja", + "binaryDir": "build_dev", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Linux" + ] + } + } + }, + { + "name": "dev-Windows64", + "inherits": [ + "ci-host-windows_x86_64", + "ci-target-windows_x86_64" + ], + "binaryDir": "build_dev", + "displayName": "Dev Windows 64-bit", + "generator": "Ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Windows" + ] + } + } + }, + { + "name": "dev-Windows64-with-env-ninja", + "inherits": [ + "dev-Windows64" + ], + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": "$env{DKSDK_NINJA_PROGRAM}", + "CMAKE_MAKE_PROGRAM_REASON": "Set DKSDK_NINJA_PROGRAM environment variable to specify ninja.exe" + }, + "displayName": "Dev Windows 64-bit + env DKSDK_NINJA_PROGRAM", + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": [ + "Windows" + ] + } + } + } + ] +} diff --git a/src/subprojects/c-capnproto/COPYING b/src/subprojects/c-capnproto/COPYING new file mode 100644 index 00000000..5c039547 --- /dev/null +++ b/src/subprojects/c-capnproto/COPYING @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 James McKaskill + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/subprojects/c-capnproto/CTestConfig.cmake b/src/subprojects/c-capnproto/CTestConfig.cmake new file mode 100644 index 00000000..6f9ade1e --- /dev/null +++ b/src/subprojects/c-capnproto/CTestConfig.cmake @@ -0,0 +1 @@ +set(VALGRIND_COMMAND_OPTIONS "--error-exitcode=109 --leak-check=full") diff --git a/src/subprojects/c-capnproto/Makefile.am b/src/subprojects/c-capnproto/Makefile.am new file mode 100644 index 00000000..6fa4b95f --- /dev/null +++ b/src/subprojects/c-capnproto/Makefile.am @@ -0,0 +1,94 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = foreign subdir-objects + +lib_LTLIBRARIES = +bin_PROGRAMS = +check_PROGRAMS = +EXTRA_DIST = +noinst_HEADERS = +include_HEADERS = + + +EXTRA_DIST += README.md + +EXTRA_DIST += c-capnproto.pc.in +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = c-capnproto.pc + +EXTRA_DIST += compiler/c.capnp +capnp_DATA = compiler/c.capnp +AM_CPPFLAGS = \ + -I${srcdir}/compiler \ + -I${srcdir}/lib + +lib_LTLIBRARIES += libcapnp_c.la +libcapnp_c_la_LDFLAGS = -version-info 0:0:0 +libcapnp_c_la_SOURCES = \ + lib/capn-malloc.c \ + lib/capn-stream.c \ + lib/capn.c +EXTRA_DIST += \ + lib/capn-list.inc + +bin_PROGRAMS += capnpc-c +capnpc_c_SOURCES = \ + compiler/capnpc-c.c \ + compiler/schema.capnp.c \ + compiler/str.c +capnpc_c_LDADD = libcapnp_c.la +include_HEADERS += \ + lib/capnp_c.h + +noinst_HEADERS += \ + lib/capnp_priv.h \ + compiler/str.h \ + compiler/schema.capnp.h \ + compiler/c.capnp.h \ + compiler/c++.capnp.h + +# Don't try to generate any *.capnp files. Otherwise make wants to compile them +# from *.capnp.c and fails. +%.capnp: ; + +# googletest +GTEST_LDADD = gtest/googletest/lib/libgtest.la +gtest/googletest/lib/libgtest.la: + make -C gtest/googletest lib/libgtest.la +GTEST_CPPFLAGS = -I${srcdir}/gtest/googletest/include +DIST_SUBDIRS = gtest/googletest + +# Tests +check_PROGRAMS += \ + capn-test +capn_test_SOURCES = \ + tests/capn-test.cpp \ + tests/capn-stream-test.cpp \ + tests/example-test.cpp \ + tests/addressbook.capnp.c \ + compiler/test.capnp.c \ + compiler/schema-test.cpp \ + compiler/schema.capnp.c +noinst_HEADERS += \ + compiler/test.capnp.h \ + tests/addressbook.capnp.h +EXTRA_DIST += \ + compiler/c.capnp \ + compiler/c++.capnp \ + compiler/schema.capnp \ + compiler/test.capnp \ + tests/addressbook.capnp +capn_test_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_CPPFLAGS) +capn_test_CXXFLAGS = -std=gnu++11 -pthread +capn_test_LDADD = libcapnp_c.la $(GTEST_LDADD) +capn_test_LDFLAGS = -pthread +TESTS = capn-test + +CAPNP_SCHEMA_FILES := $(shell find . -type f -name \*.capnp) + +CAPNP ?= capnp +.PHONY: capnp-compile +capnp-compile: + $(CAPNP) compile \ + --output=./capnpc-c \ + -Icompiler \ + $(CAPNP_SCHEMA_FILES) diff --git a/src/subprojects/c-capnproto/README.md b/src/subprojects/c-capnproto/README.md new file mode 100644 index 00000000..439de1ba --- /dev/null +++ b/src/subprojects/c-capnproto/README.md @@ -0,0 +1,166 @@ +# capnpc-c + +This is a C plugin for [Cap'n Proto](http://kentonv.github.io/capnproto), an +efficient protocol for sharing data and capabilities. + +This is a fork of with support +for CMake and Windows, a build matrix that includes Android and Windows, and +fixes several bugs that start with the [CHANGES for version 0.9.0](./CHANGES.md#090). + +The fork is maintained as part of [DkML](https://diskuv.com/dkmlbook/) +and [DkSDK](https://diskuv.com/cmake/help/latest/), but PRs are welcome from +anybody. If you are looking for your first PR, fixing the false positive +memory leaks in the test code would be great! + +## Security warning + +> The generated code assumes all input to be trusted. Do NOT use with +> untrusted input! There is currently no code in place to check if +> structures/pointers are within bounds. + +This is only the code generator plugin, to properly make use of it you +need to download, build and install capnpc and then build and install +this project and then you can utilize it as: + +```sh +capnpc compiler/test.capnp -oc +``` + +## Building on Linux + +```sh +git clone https://gitlab.com/dkml/ext/c-capnproto.git +cd c-capnproto +cmake --preset=ci-linux_x86_64 +cmake --build --preset=ci-tests +``` + +## Building on Windows + +You will need Visual Studio 2019 installed. Other versions of Visual Studio may work; they simply haven't been tested. + +Once you have Visual Studio, run the `x64 Native Tools Command Prompt for VS 2019` and type the following: + +```sh +git clone https://gitlab.com/dkml/ext/c-capnproto.git +cd c-capnproto +cmake --preset=ci-windows_x86_64 +cmake --build --preset=ci-tests +``` + +## Usage + +### Generating C code from a `.capnp` schema file + +The `compiler` directory contains the C language plugin (`capnpc-c`) for use with the `capnp` tool: . + +`capnp` will by default search `$PATH` for `capnpc-c` - if it's on your PATH, you can generate code for your schema as follows: + +```sh +capnp compile -o c myschema.capnp +``` + +Otherwise, you can specify the path to the c plugin: + +```sh +capnp compile -o ./capnpc-c myschema.capnp +``` + +`capnp` generates a C struct that corresponds to each capn proto struct, along with read/write functions that convert to/from capn proto form. + +#### fieldgetset + +If you want accessor functions for struct members, use the attribute `fieldgetset` in your `.capnp` file as follows: + +```capnp +using C = import "${c-capnproto}/compiler/c.capnp"; + +$C.fieldgetset; + +struct MyStruct {} +``` + +#### extraheader + +If you want to add `#include <...>` or any other preprocessor statements in your generated C file, use the attribute `extraheader` in your `.capnp` file as follows: + +```capnp +using C = import "${c-capnproto}/compiler/c.capnp"; + +$C.extraheader("include "); + +struct MyStruct {} +``` + +#### extendedattribute + +If you want to add an `__declspec(dllexport)` or some other extended attribute to your generated C functions and structs, use the attribute `extendedattribute` in your `.capnp` file as follows: + +```capnp +using C = import "${c-capnproto}/compiler/c.capnp"; + +$C.extendedattribute("__declspec(dllexport)"); + +struct MyStruct {} +``` + +### Example C code + +See the unit tests in [`tests/example-test.cpp`](tests/example-test.cpp). +The example schema file is [`tests/addressbook.capnp`](tests/addressbook.capnp). +The tests are written in C++, but only use C features. + +You need to compile these runtime library files and link them into your own project's binaries: + +* [`lib/capn.c`](lib/capn.c) +* [`lib/capn-malloc.c`](lib/capn-malloc.c) +* [`lib/capn-stream.c`](lib/capn-stream.c) + +Your include path must contain the runtime library directory +[`lib`](lib). Header file [`lib/capnp_c.h`](lib/capnp_c.h) contains +the public interfaces of the library. + +Using make-based builds, make may try to compile `${x}.capnp` from +`${x}.capnp.c` using its built-in rule for compiling `${y}` from +`${y}.c`. You can either disable make's built-in compile rules or just +this specific case with the no-op rule: `%.capnp: ;`. + +For further reference, please see the other unit tests in [`tests`](tests), and header file [`lib/capnp_c.h`](lib/capnp_c.h). + +The project [`quagga-capnproto`](https://github.com/opensourcerouting/quagga-capnproto) uses `c-capnproto` and contains some good examples, as found with [this github repository search](https://github.com/opensourcerouting/quagga-capnproto/search?utf8=%E2%9C%93&q=capn&type=): + +* Serialization in function [`bgp_notify_send()`](https://github.com/opensourcerouting/quagga-capnproto/blob/27061648f3418fac0d217b16a46add534343e841/bgpd/bgp_zmq.c#L81-L96) in file `quagga-capnproto/bgpd/bgp_zmq.c` +* Deserialization in function [`qzc_callback()`](https://github.com/opensourcerouting/quagga-capnproto/blob/27061648f3418fac0d217b16a46add534343e841/lib/qzc.c#L249-L257) in file `quagga-capnproto/lib/qzc.c` + +### Example CMake Usage + +The minimum CMake version is 3.22. *The true CMake minimum version could be lower; you are welcome to test and submit a PR to [CMakeLists.txt](./CMakeLists.txt).* + +```cmake +FetchContent_Declare(c-capnproto + GIT_REPOSITORY https://gitlab.com/dkml/ext/c-capnproto.git + # For reproducibility use a commit id rather than a tag + GIT_TAG f07596dbb516329d27ea95060a758f5d48d26366) +FetchContent_MakeAvailable(c-capnproto) + +# Creating an executable or library that uses c-capnproto? +# -------------------------------------------------------- + +# filename: yourcode.c +# +# #include "capnp_c.h" +# ... + +add_executable(YourExecutable ... yourcode.c) +target_link_libraries(YourExecutable PRIVATE CapnC::Runtime) +``` + +## Status + + was a merge of 3 forks of [James McKaskill's great +work](https://github.com/jmckaskill/c-capnproto), which had been untouched for +a while: + +* [liamstask's fork](https://github.com/liamstask/c-capnproto) +* [baruch's fork](https://github.com/baruch/c-capnproto) +* [kylemanna's fork](https://github.com/kylemanna/c-capnproto) diff --git a/src/subprojects/c-capnproto/ac/.gitignore b/src/subprojects/c-capnproto/ac/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/src/subprojects/c-capnproto/ac/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/src/subprojects/c-capnproto/c-capnproto.pc.in b/src/subprojects/c-capnproto/c-capnproto.pc.in new file mode 100644 index 00000000..c5409b56 --- /dev/null +++ b/src/subprojects/c-capnproto/c-capnproto.pc.in @@ -0,0 +1,12 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/lib +bindir=${prefix}/bin +includedir=${prefix}/include +codegen=${bindir}/capnpc-c + +Name: c-capnproto +Description: Cap'n Proto C bindings +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lCapnC_Runtime +Cflags: -I${includedir} diff --git a/src/subprojects/c-capnproto/ci/ctest/Sanitizers-ASAN-CTest.cmake b/src/subprojects/c-capnproto/ci/ctest/Sanitizers-ASAN-CTest.cmake new file mode 100644 index 00000000..9bbfdbae --- /dev/null +++ b/src/subprojects/c-capnproto/ci/ctest/Sanitizers-ASAN-CTest.cmake @@ -0,0 +1,66 @@ +# Run locally the -asanSanitizer with: +# rm -rf build/ +# ./dk dksdk.cmake.link +# .ci/cmake/bin/cmake --preset=ci-linux_x86_64-sanitizers-asan +# .ci/cmake/bin/ctest -S ci/ctest/Sanitizers-ASAN-CTest.cmake --extra-verbose + +# Determine project directories +set(OUR_PROJECT_SOURCE_DIR "${CTEST_SCRIPT_DIRECTORY}/../..") +cmake_path(NORMAL_PATH OUR_PROJECT_SOURCE_DIR) +cmake_path(APPEND OUR_PROJECT_SOURCE_DIR build OUTPUT_VARIABLE OUR_PROJECT_BINARY_DIR) + +# Re-use test details +include(${OUR_PROJECT_SOURCE_DIR}/CTestConfig.cmake) + +# Read the CI generated CMakeCache.txt +load_cache("${OUR_PROJECT_BINARY_DIR}" + READ_WITH_PREFIX CACHED_ + CMAKE_BUILD_TYPE) + +# Basic information every run should set +site_name(CTEST_SITE) +set(CTEST_BUILD_NAME ${CMAKE_HOST_SYSTEM_NAME}) +set(CTEST_SOURCE_DIRECTORY "${OUR_PROJECT_SOURCE_DIR}") +set(CTEST_BINARY_DIRECTORY "${OUR_PROJECT_BINARY_DIR}") +set(CTEST_CMAKE_GENERATOR Ninja) +if(CACHED_CMAKE_BUILD_TYPE) + set(CTEST_CONFIGURATION_TYPE ${CACHED_CMAKE_BUILD_TYPE}) +else() + set(CTEST_CONFIGURATION_TYPE Debug) +endif() + +set(CTEST_MEMORYCHECK_TYPE AddressSanitizer) + +# ASAN_OPTIONS +# -------- +# +# Even if we have [ASAN_OPTIONS] defined in CMakePresets.json, +# that will not impact this script which is invoked by `ctest` not +# `cmake`, and [CTEST_MEMORYCHECK_TYPE] will overwrite it anyway. +# +# Valgrind makes ASAN memory leaks redundant. And the unforked +# c-capnproto code disabled memory leaks anyway. So we use the +# same options. +set(extra_OPTIONS detect_leaks=0,detect_odr_violation=0,allocator_may_return_null=1) +# Apply to ctest_memcheck() +set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS ${extra_OPTIONS}) +# Apply to ctest_build() +if(extra_OPTIONS) + if(ENV{ASAN_OPTIONS}) + set(ENV{ASAN_OPTIONS} ${extra_OPTIONS}:$ENV{ASAN_OPTIONS}) + else() + set(ENV{ASAN_OPTIONS} ${extra_OPTIONS}) + endif() +endif() + +ctest_start(Experimental) + +ctest_build(RETURN_VALUE err) +if(err) + message(FATAL_ERROR "CTest build error ${err}") +endif() + +ctest_memcheck(RETURN_VALUE err) +if(err) + message(FATAL_ERROR "CTest memcheck error ${err}") +endif() diff --git a/src/subprojects/c-capnproto/ci/ctest/Sanitizers-UBSAN-CTest.cmake b/src/subprojects/c-capnproto/ci/ctest/Sanitizers-UBSAN-CTest.cmake new file mode 100644 index 00000000..cca10d41 --- /dev/null +++ b/src/subprojects/c-capnproto/ci/ctest/Sanitizers-UBSAN-CTest.cmake @@ -0,0 +1,69 @@ +# Run locally the -ubsan Sanitizer with: +# rm -rf build/ +# ./dk dksdk.cmake.link +# .ci/cmake/bin/cmake --preset=ci-linux_x86_64-sanitizers-ubsan +# .ci/cmake/bin/ctest -S ci/ctest/Sanitizers-UBSAN-CTest.cmake --extra-verbose + +# Determine project directories +if(NOT OUR_PROJECT_SOURCE_DIR) + set(OUR_PROJECT_SOURCE_DIR "${CTEST_SCRIPT_DIRECTORY}/../..") + cmake_path(NORMAL_PATH OUR_PROJECT_SOURCE_DIR) +endif() +if(NOT OUR_PROJECT_BINARY_DIR) + cmake_path(APPEND OUR_PROJECT_SOURCE_DIR build OUTPUT_VARIABLE OUR_PROJECT_BINARY_DIR) +endif() + +# Re-use test details +include(${OUR_PROJECT_SOURCE_DIR}/CTestConfig.cmake) + +# Read the CI generated CMakeCache.txt +load_cache("${OUR_PROJECT_BINARY_DIR}" + READ_WITH_PREFIX CACHED_ + CMAKE_BUILD_TYPE) + +# Basic information every run should set +site_name(CTEST_SITE) +set(CTEST_BUILD_NAME ${CMAKE_HOST_SYSTEM_NAME}) +set(CTEST_SOURCE_DIRECTORY "${OUR_PROJECT_SOURCE_DIR}") +set(CTEST_BINARY_DIRECTORY "${OUR_PROJECT_BINARY_DIR}") +set(CTEST_CMAKE_GENERATOR Ninja) +if(CACHED_CMAKE_BUILD_TYPE) + set(CTEST_CONFIGURATION_TYPE ${CACHED_CMAKE_BUILD_TYPE}) +else() + set(CTEST_CONFIGURATION_TYPE Debug) +endif() + +# Tell CTest to add to UBSAN_OPTIONS to capture its logs +set(CTEST_MEMORYCHECK_TYPE UndefinedBehaviorSanitizer) + +# UBSAN_OPTIONS +# -------- +# +# Even if we have [UBSAN_OPTIONS] defined in CMakePresets.json, +# that will not impact this script which is invoked by `ctest` not +# `cmake`, and [CTEST_MEMORYCHECK_TYPE] will overwrite it anyway. +# +# Enable stack traces +set(extra_OPTIONS print_stacktrace=1) +# Apply to ctest_memcheck() +set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS ${extra_OPTIONS}) +# Apply to ctest_build() +if(extra_OPTIONS) + if(ENV{UBSAN_OPTIONS}) + set(ENV{UBSAN_OPTIONS} ${extra_OPTIONS}:$ENV{UBSAN_OPTIONS}) + else() + set(ENV{UBSAN_OPTIONS} ${extra_OPTIONS}) + endif() +endif() + +ctest_start(Experimental) + +ctest_build(RETURN_VALUE err) +if(err) + message(FATAL_ERROR "CTest build error ${err}") +endif() + +ctest_memcheck(RETURN_VALUE err) +if(err) + message(FATAL_ERROR "CTest memcheck error ${err}") +endif() diff --git a/src/subprojects/c-capnproto/ci/gitlab/test.gitlab-ci.yml b/src/subprojects/c-capnproto/ci/gitlab/test.gitlab-ci.yml new file mode 100644 index 00000000..39181dc2 --- /dev/null +++ b/src/subprojects/c-capnproto/ci/gitlab/test.gitlab-ci.yml @@ -0,0 +1,155 @@ +.unit-test: + rules: + - if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "next"' + artifacts: + paths: + - build/Testing/Temporary/LastBuild_*.log + - build/Testing/Temporary/LastTest.log + - build/Testing/Temporary/LastTests_*.log + - build/Testing/Temporary/MemoryChecker.*.log + reports: + junit: + - build/cmakespec.xml + - build/tests/*-Results.xml + when: always + +unit-test-debian: + stage: test + # The original c-capnproto unit tests were full of memory leaks (not closing test + # structures). Sigh. Until those are fixed, we can't detect real memory leaks. + allow_failure: true + extends: + - .c-cmake-debian:before + - .unit-test + script: + - export PATH="$PWD/.ci/cmake/bin:$PATH" + + - echo -e "\e[0Ksection_start:`date +%s`:configure[collapsed=true]\r\e[0KConfiguring build scripts" + - rm -rf build/ + - cmake --preset=ci-linux_x86_64 -D BUILD_HYGIENE=ENABLED + - echo -e "\e[0Ksection_end:`date +%s`:configure\r\e[0K" + + - echo -e "\e[0Ksection_start:`date +%s`:build[collapsed=true]\r\e[0KBuilding test targets" + - cmake --build --preset=ci-tests + - echo -e "\e[0Ksection_end:`date +%s`:build\r\e[0K" + + - echo -e "\e[0Ksection_start:`date +%s`:unittest[collapsed=true]\r\e[0KUnit Testing" + - ctest --output-junit cmakespec.xml --verbose --preset=ci-test + - echo -e "\e[0Ksection_end:`date +%s`:unittest\r\e[0K" + + - echo -e "\e[0Ksection_start:`date +%s`:memcheck[collapsed=true]\r\e[0KMemory Testing" + - ctest -T memcheck --test-dir build --verbose + - echo -e "\e[0Ksection_end:`date +%s`:memcheck\r\e[0K" + +unit-test-android_x86_64: + stage: test + extends: + - .c-cmake-debian:before + - .unit-test + script: + - export PATH="$PWD/.ci/cmake/bin:$PATH" + + - echo -e "\e[0Ksection_start:`date +%s`:installandroid[collapsed=true]\r\e[0KInstalling Android NDK" + - ./dk dksdk.android.ndk.download + - echo -e "\e[0Ksection_end:`date +%s`:installandroid\r\e[0K" + + - echo -e "\e[0Ksection_start:`date +%s`:configure[collapsed=true]\r\e[0KConfiguring build scripts" + - rm -rf build/ + - cmake --preset=ci-linux_x86_64_X_android_x86_64 + - echo -e "\e[0Ksection_end:`date +%s`:configure\r\e[0K" + + - echo -e "\e[0Ksection_start:`date +%s`:build[collapsed=true]\r\e[0KBuilding test targets" + - cmake --build --preset=ci-tests + - echo -e "\e[0Ksection_end:`date +%s`:build\r\e[0K" + + - echo 'No unit tests and no memory tests for a cross-compiled target' + +unit-test-windows: + stage: test + extends: + - .c-cmake-windows:before + - .unit-test + script: + - $env:Path += ';C:\Program Files\CMake\bin' + + - $esc="$([char]27)"; $cr="$([char]13)"; $TXT_SECTION="${esc}[36m"; $TXT_CLEAR="${esc}[0m" + - | + function Get-CurrentEpochSecs { + [long]$timestamp = [math]::Round((([datetime]::UtcNow) - (Get-Date -Date '1/1/1970')).TotalMilliseconds) + [math]::Round($timestamp / 1000) + } + + - Write-Host "${esc}[0Ksection_start:$(Get-CurrentEpochSecs):configure[collapsed=true]${cr}${esc}[0K"$TXT_SECTION"Configuring build scripts" + - if (Test-Path build) { Remove-Item -Recurse -Force build } + # Linux can test with BUILD_HYGIENE=ENABLED. Don't want to install clang-tidy through + # Chocolatey because huge LLVM download (`choco install llvm`). + - ci/run-with-msvc.cmd cmake --preset=ci-windows_x86_64 -D BUILD_HYGIENE=DISABLED + - Write-Host "${esc}[0Ksection_end:$(Get-CurrentEpochSecs):configure${cr}${esc}[0K" + + - Write-Host "${esc}[0Ksection_start:$(Get-CurrentEpochSecs):build[collapsed=true]${cr}${esc}[0K"$TXT_SECTION"Building test targets" + - ci/run-with-msvc.cmd cmake --build --preset=ci-tests + - Write-Host "${esc}[0Ksection_end:$(Get-CurrentEpochSecs):build${cr}${esc}[0K" + + - Write-Host "${esc}[0Ksection_start:$(Get-CurrentEpochSecs):unittest[collapsed=true]${cr}${esc}[0K"$TXT_SECTION"Unit Testing" + - ci/run-with-msvc.cmd ctest --output-junit cmakespec.xml --verbose --preset=ci-test + - Write-Host "${esc}[0Ksection_end:$(Get-CurrentEpochSecs):unittest${cr}${esc}[0K" + +sanitizers-debian-asan: + stage: test + extends: + - .c-cmake-debian:before + rules: + - if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "next"' + artifacts: + paths: + - build/Testing/Temporary/LastBuild_*.log + - build/Testing/Temporary/LastDynamicAnalysis_*.log + - build/Testing/Temporary/LastTest.log + - build/Testing/Temporary/LastTests_*.log + - build/Testing/Temporary/MemoryChecker.*.log + reports: + junit: + - build/cmakespec.xml + - build/tests/*-Results.xml + when: always + script: + - export PATH="$PWD/.ci/cmake/bin:$PATH" + + - echo -e "\e[0Ksection_start:`date +%s`:configure[collapsed=true]\r\e[0KConfiguring build scripts" + - rm -rf build/ + - cmake --preset=ci-linux_x86_64-sanitizers-asan + - echo -e "\e[0Ksection_end:`date +%s`:configure\r\e[0K" + + - echo -e "\e[0Ksection_start:`date +%s`:build[collapsed=true]\r\e[0KRunning ASAN sanitizers build and check" + - ctest -S ci/ctest/Sanitizers-ASAN-CTest.cmake + - echo -e "\e[0Ksection_end:`date +%s`:build\r\e[0K" + +sanitizers-debian-ubsan: + stage: test + extends: + - .c-cmake-debian:before + rules: + - if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "next"' + artifacts: + paths: + - build/Testing/Temporary/LastBuild_*.log + - build/Testing/Temporary/LastDynamicAnalysis_*.log + - build/Testing/Temporary/LastTest.log + - build/Testing/Temporary/LastTests_*.log + - build/Testing/Temporary/MemoryChecker.*.log + reports: + junit: + - build/cmakespec.xml + - build/tests/*-Results.xml + when: always + script: + - export PATH="$PWD/.ci/cmake/bin:$PATH" + + - echo -e "\e[0Ksection_start:`date +%s`:configure[collapsed=true]\r\e[0KConfiguring build scripts" + - rm -rf build/ + - cmake --preset=ci-linux_x86_64-sanitizers-ubsan + - echo -e "\e[0Ksection_end:`date +%s`:configure\r\e[0K" + + - echo -e "\e[0Ksection_start:`date +%s`:build[collapsed=true]\r\e[0KRunning UBSAN sanitizers build and check" + - ctest -S ci/ctest/Sanitizers-UBSAN-CTest.cmake + - echo -e "\e[0Ksection_end:`date +%s`:build\r\e[0K" diff --git a/src/subprojects/c-capnproto/ci/run-with-msvc.cmd b/src/subprojects/c-capnproto/ci/run-with-msvc.cmd new file mode 100644 index 00000000..25c3c059 --- /dev/null +++ b/src/subprojects/c-capnproto/ci/run-with-msvc.cmd @@ -0,0 +1,3 @@ +CALL "%VSDIR%\VC\Auxiliary\Build\vcvars64.bat" +ECHO ON +%* \ No newline at end of file diff --git a/src/subprojects/c-capnproto/cmake/FindDkToolScripts.cmake b/src/subprojects/c-capnproto/cmake/FindDkToolScripts.cmake new file mode 100644 index 00000000..88ff3910 --- /dev/null +++ b/src/subprojects/c-capnproto/cmake/FindDkToolScripts.cmake @@ -0,0 +1,187 @@ +# Recommendation: Place this file in source control. +# Auto-generated by `./dk dksdk.project.new` of dktool. + +include(FetchContent) + +function(parse_dktool_command_line) + # The first argument is . All dots will be replaced with a + # triple underscore as a convenience and to be pretty for the user. + if(ARGC EQUAL 0) + message(FATAL_ERROR "Missing . Usage: ./dk [args]") + endif() + set(command ${ARGV0}) + string(REPLACE "." "___" expected_function_name ${command}) + message(VERBOSE "Searching for ${expected_function_name}") + + # Set policies (we are in a new EVAL CODE context) + # Included scripts do automatic cmake_policy PUSH and POP + if(POLICY CMP0011) + cmake_policy(SET CMP0011 NEW) + endif() + + # Parse the remainder of the arguments [args] + # * Use technique from [Professional CMake: A Practical Guide - Forwarding Command Arguments] + # to be able to forward arguments correctly to an inner function (the function). + cmake_parse_arguments(PARSE_ARGV 1 FWD "" "" "") + set(quotedArgs "") + foreach(arg IN LISTS FWD_UNPARSED_ARGUMENTS) + string(APPEND quotedArgs " [===[${arg}]===]") + endforeach() + + # Setup the binary directory + if(NOT DKTOOL_WORKDIR) + message(FATAL_ERROR "Illegal state. Expecting DKTOOL_WORKDIR") + endif() + set(CMAKE_BINARY_DIR ${DKTOOL_WORKDIR}) + set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_BINARY_DIR}) + + # Search in all the user scripts + set(dot_function_names) + file(GLOB_RECURSE command_files + LIST_DIRECTORIES FALSE + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts + cmake/scripts/*.cmake) + foreach(command_file IN LISTS command_files) + # Normalize and lowercase + cmake_path(NORMAL_PATH command_file) + string(TOLOWER "${command_file}" command_file) + cmake_path(REMOVE_EXTENSION command_file OUTPUT_VARIABLE command_file_no_ext) + + # Convert to list + string(REPLACE "/" ";" command_stems_no_namespace ${command_file_no_ext}) + + # Make a pretty description only for validation + set(pretty_stems ${command_stems_no_namespace}) + list(TRANSFORM pretty_stems PREPEND "'") + list(TRANSFORM pretty_stems APPEND "'") + string(JOIN ", " pretty_stems_str ${pretty_stems}) + string(REGEX REPLACE ",([^,]*)" " and \\1" pretty_stems_str "${pretty_stems_str}") + + # Validate that only alphanumeric with underscores (but not the reserved three underscores) + string(REGEX MATCH "[/a-z0-9_]*" only_alphanum_and_underscores "${command_file_no_ext}") + if(NOT only_alphanum_and_underscores STREQUAL "${command_file_no_ext}") + message(WARNING "Ignoring user script ${CMAKE_CURRENT_SOURCE_DIR}/${command_file}. +The stems of the user script (${pretty_stems_str}) must only contain letters, numbers and underscores.") + continue() + endif() + string(FIND "${command_file_no_ext}" "___" reserved_underscores) + if(reserved_underscores GREATER_EQUAL 0) + message(WARNING "Ignoring user script ${CMAKE_CURRENT_SOURCE_DIR}/${command_file}. +No stem of the user script (${pretty_stems_str}) can contain a triple underscore ('___').") + continue() + endif() + + # Translate dev/xxx.cmake to the "user" namespaced function name + # `user__dev__xxx` and `user.dev.xxx`. + set(command_stems ${command_stems_no_namespace}) + list(PREPEND command_stems "user") + string(JOIN "___" command_function_name ${command_stems}) + string(JOIN "." dot_function_name ${command_stems}) + list(APPEND dot_function_names ${dot_function_name}) + + # In a new scope (to avoid a global, leaky namespace) register the function. + message(VERBOSE "Shimming ${command_function_name}") + cmake_language(EVAL CODE " +function(${command_function_name}) + include(\"${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts/${command_file}\") + if(COMMAND run) + run(${quotedArgs}) + else() + message(FATAL_ERROR [[The user script ${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts/${command_file} was missing: + function(run) + # Your user code + endfunction() +]]) + endif() +endfunction() +") + endforeach() + + # Include all the system scripts. + # - Since the system scripts come after the user scripts, the user scripts + # don't override the system scripts unless the user scripts use deferred + # hooks or redefine CMake built-in functions. Regardless, the user + # scripts are namespaced with `user__` prefix + if(NOT IS_DIRECTORY cmake/scripts/dksdk) + # If this project (ex. dktool) has the system scripts, it must + # have all of them. Otherwise we download the system scripts. + FetchContent_Populate(dktool + QUIET + GIT_REPOSITORY https://gitlab.com/diskuv/dktool.git + GIT_TAG 1.0 + ) + file(GLOB_RECURSE system_command_files + LIST_DIRECTORIES FALSE + RELATIVE ${dktool_SOURCE_DIR}/cmake/scripts + ${dktool_SOURCE_DIR}/cmake/scripts/dkml/*.cmake + ${dktool_SOURCE_DIR}/cmake/scripts/dksdk/*.cmake) + foreach(command_file IN LISTS system_command_files) + # Normalize and lowercase + cmake_path(NORMAL_PATH command_file) + string(TOLOWER "${command_file}" command_file) + cmake_path(REMOVE_EXTENSION command_file OUTPUT_VARIABLE command_file_no_ext) + + # Convert to list + string(REPLACE "/" ";" command_stems_no_namespace ${command_file_no_ext}) + + # Translate dksdk/xxx.cmake to the function name `dksdk__xxx` and `dksdk.xxx` + set(command_stems ${command_stems_no_namespace}) + string(JOIN "___" command_function_name ${command_stems}) + string(JOIN "." dot_function_name ${command_stems}) + list(APPEND dot_function_names ${dot_function_name}) + + # In a new scope (to avoid a global, leaky namespace) register the function. + message(VERBOSE "Shimming ${command_function_name}") + cmake_language(EVAL CODE " +function(${command_function_name}) + include(\"${dktool_SOURCE_DIR}/cmake/scripts/${command_file}\") + if(COMMAND run) + run(${quotedArgs}) + else() + message(FATAL_ERROR [[The system script ${dktool_SOURCE_DIR}/cmake/scripts/${command_file} was missing: + function(run) + # The system code + endfunction() +]]) + endif() +endfunction() +") + + endforeach() + endif() + + # Validate the exists + if(NOT COMMAND ${expected_function_name}) + set(pretty_function_names ${dot_function_names}) + list(TRANSFORM pretty_function_names PREPEND " ") + list(TRANSFORM pretty_function_names APPEND "\n") + string(JOIN "" str_pretty_function_names ${pretty_function_names}) + message(FATAL_ERROR "No command '${command}' exists. The following commands are available: +${str_pretty_function_names}") + message(FATAL_ERROR "No command '${command}' exists") + endif() + + # Call the function + cmake_language(EVAL CODE "${expected_function_name}()") +endfunction() + +# DkML data home +if(WIN32) + set(DKML_DATA_HOME "$ENV{LOCALAPPDATA}/Programs/DiskuvOCaml") +elseif(DEFINED ENV{XDG_DATA_HOME}) + set(DKML_DATA_HOME "$ENV{XDG_DATA_HOME}/diskuv-ocaml") +else() + set(DKML_DATA_HOME "$ENV{HOME}/.local/share/diskuv-ocaml") +endif() + +# DkSDK data home +if(WIN32) + set(DKSDK_DATA_HOME "$ENV{LOCALAPPDATA}/Programs/DkSDK") +elseif(DEFINED ENV{XDG_DATA_HOME}) + set(DKSDK_DATA_HOME "$ENV{XDG_DATA_HOME}/dksdk") +else() + set(DKSDK_DATA_HOME "$ENV{HOME}/.local/share/dksdk") +endif() + +# Splat DKTOOL_CMDLINE +cmake_language(EVAL CODE "parse_dktool_command_line(${DKTOOL_CMDLINE})") diff --git a/src/subprojects/c-capnproto/compiler/c++.capnp b/src/subprojects/c-capnproto/compiler/c++.capnp new file mode 100644 index 00000000..2bda5471 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/c++.capnp @@ -0,0 +1,26 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xbdf87d7bb8304e81; +$namespace("capnp::annotations"); + +annotation namespace(file): Text; +annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text; diff --git a/src/subprojects/c-capnproto/compiler/c++.capnp.c b/src/subprojects/c-capnproto/compiler/c++.capnp.c new file mode 100644 index 00000000..f088ac4b --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/c++.capnp.c @@ -0,0 +1,10 @@ +#include "c++.capnp.h" +/* AUTO GENERATED - DO NOT EDIT */ +#ifdef __GNUC__ +# define capnp_unused __attribute__((unused)) +# define capnp_use(x) (void) (x); +#else +# define capnp_unused +# define capnp_use(x) +#endif + diff --git a/src/subprojects/c-capnproto/compiler/c++.capnp.h b/src/subprojects/c-capnproto/compiler/c++.capnp.h new file mode 100644 index 00000000..1bdbe0f0 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/c++.capnp.h @@ -0,0 +1,35 @@ +#ifndef CAPN_BDF87D7BB8304E81 +#define CAPN_BDF87D7BB8304E81 +/* AUTO GENERATED - DO NOT EDIT */ +#include + +#if CAPN_VERSION != 1 +#error "version mismatch between capnp_c.h and generated code" +#endif + +#ifndef capnp_nowarn +# ifdef __GNUC__ +# define capnp_nowarn __extension__ +# else +# define capnp_nowarn +# endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + + + + + + + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/subprojects/c-capnproto/compiler/c.capnp b/src/subprojects/c-capnproto/compiler/c.capnp new file mode 100644 index 00000000..7dcc53b5 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/c.capnp @@ -0,0 +1,69 @@ +# Copyright (c) 2016 NetDEF, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xc0183dd65ffef0f3; + +annotation nameinfix @0x85a8d86d736ba637 (file): Text; +# add an infix (middle insert) for output file names +# +# "make" generally has implicit rules for compiling "foo.c" => "foo". This +# is very annoying with capnp since the rule will be "foo" => "foo.c", leading +# to a loop. $nameinfix (recommended parameter: "-gen") inserts its parameter +# before the ".c", so the filename becomes "foo-gen.c" +# +# Alternatively, add this Makefile rule to disable compiling "foo.capnp.c" -> "foo.capnp": +# %.capnp: ; +# +# +# ("foo" is really "foo.capnp", so it's foo.capnp-gen.c) + +annotation fieldgetset @0xf72bc690355d66de (file): Void; +# generate getter & setter functions for accessing fields +# +# allows grabbing/putting values without de-/encoding the entire struct. + +annotation donotinclude @0x8c99797357b357e9 (file): UInt64; +# do not generate an include directive for an import statement for the file with +# the given ID + +annotation typedefto @0xcefaf27713042144 (struct, enum): Text; +# generate a typedef for the annotated struct or enum declaration + +annotation namespace @0xf2c035025fec7c2b (file): Text; +# prefix structs with a name space string + +annotation extraheader @0xbadb496d09cf4612 (file): Text; +# add extra preprocessor directives to the header + +annotation extendedattribute @0xd187bca5c6844c24 (file): Text; +# add an extended attribute to each generated function + +annotation codecgen @0xcccaac86283e2609 (file): Void; +# generate codec(encode/decode) to each type + +annotation mapname @0xb9edf6fc2d8972b8 (*): Text; +# the mapped type name which will be encoded + +annotation maplistcount @0xb6ea49eb8a9b0f9e (field): Text; +# the mapped list count field which will be encoded + +annotation mapuniontag @0xdce06d41858f91ac (union, struct): Text; +# the mapped tag (which) of union diff --git a/src/subprojects/c-capnproto/compiler/c.capnp.c b/src/subprojects/c-capnproto/compiler/c.capnp.c new file mode 100644 index 00000000..c94af4c0 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/c.capnp.c @@ -0,0 +1,10 @@ +#include "c.capnp.h" +/* AUTO GENERATED - DO NOT EDIT */ +#ifdef __GNUC__ +# define capnp_unused __attribute__((unused)) +# define capnp_use(x) (void) (x); +#else +# define capnp_unused +# define capnp_use(x) +#endif + diff --git a/src/subprojects/c-capnproto/compiler/c.capnp.h b/src/subprojects/c-capnproto/compiler/c.capnp.h new file mode 100644 index 00000000..18213388 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/c.capnp.h @@ -0,0 +1,35 @@ +#ifndef CAPN_C0183DD65FFEF0F3 +#define CAPN_C0183DD65FFEF0F3 +/* AUTO GENERATED - DO NOT EDIT */ +#include + +#if CAPN_VERSION != 1 +#error "version mismatch between capnp_c.h and generated code" +#endif + +#ifndef capnp_nowarn +# ifdef __GNUC__ +# define capnp_nowarn __extension__ +# else +# define capnp_nowarn +# endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + + + + + + + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/subprojects/c-capnproto/compiler/capnpc-c.c b/src/subprojects/c-capnproto/compiler/capnpc-c.c new file mode 100644 index 00000000..d72bc9ab --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/capnpc-c.c @@ -0,0 +1,2875 @@ +/* capnpc-c.c + * + * Copyright (C) 2013 James McKaskill + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ +#define _POSIX_C_SOURCE 200809L + +#include "schema.capnp.h" +#include "str.h" +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#include +#endif + +#if defined(__linux) +#define _fileno fileno +#endif + +#define ANNOTATION_NAMESPACE 0xf2c035025fec7c2bUL +#define ANNOTATION_FIELDGETSET 0xf72bc690355d66deUL +#define ANNOTATION_DONOTINCLUDE 0x8c99797357b357e9UL +#define ANNOTATION_TYPEDEFTO 0xcefaf27713042144UL +#define ANNOTATION_EXTRAHEADER 0xbadb496d09cf4612UL +#define ANNOTATION_EXTENDEDATTRIBUTE 0xd187bca5c6844c24UL +#define ANNOTATION_CODECGEN 0xcccaac86283e2609UL +#define ANNOTATION_MAPNAME 0xb9edf6fc2d8972b8UL +#define ANNOTATION_NAMEINFIX 0x85a8d86d736ba637UL +#define ANNOTATION_MAPLISTCOUNT 0xb6ea49eb8a9b0f9eUL +#define ANNOTATION_MAPUNIONTAG 0xdce06d41858f91acUL + +struct value { + struct Type t; + const char *tname; + struct str tname_buf; + struct Value v; + capn_ptr ptrval; + int64_t intval; +}; + +struct field { + struct Field f; + struct value v; + struct node *group; +}; + +struct node { + struct capn_tree hdr; + struct Node n; + struct node *next; + struct node *file_nodes, *next_file_node; + struct str name; + struct field *fields; +}; + +struct id_bst { + uint64_t id; + struct id_bst *left; + struct id_bst *right; +}; + +struct string_list { + const char *string; + struct string_list *prev; + struct string_list *next; +}; + +typedef struct { + struct capn capn; + struct str HDR; + struct str SRC; + struct capn_segment g_valseg; + struct capn g_valcapn; + int g_valc; + int g_val0used, g_nullused; + int g_fieldgetset; + int g_codecgen; + struct capn_tree *g_node_tree; + CodeGeneratorRequest_ptr root; + struct CodeGeneratorRequest req; + struct node *file_node; + struct node *all_files; + struct node *all_structs; + struct id_bst *used_import_ids; +} capnp_ctx_t; + +static void fail(int code, char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(code); +} + +static struct node *find_node_mayfail(capnp_ctx_t *ctx, uint64_t id) { + struct node *s = (struct node *)ctx->g_node_tree; + while (s && s->n.id != id) { + s = (struct node *)s->hdr.link[s->n.id < id]; + } + return s; +} + +static struct node *find_node(capnp_ctx_t *ctx, uint64_t id) { + struct node *s = find_node_mayfail(ctx, id); + if (s == NULL) { + fail(2, "cant find node with id 0x%x%x\n", (uint32_t)(id >> 32), + (uint32_t)id); + } + return s; +} + +static void insert_node(capnp_ctx_t *ctx, struct node *s) { + struct capn_tree **x = &(ctx->g_node_tree); + while (*x) { + s->hdr.parent = *x; + x = &(*x)->link[((struct node *)*x)->n.id < s->n.id]; + } + *x = &s->hdr; + ctx->g_node_tree = capn_tree_insert(ctx->g_node_tree, &s->hdr); +} + +/* id_bst implementation */ + +static struct id_bst *insert_id(struct id_bst *bst, uint64_t id) { + struct id_bst **current = &bst; + + while (*current) { + if (id > (*current)->id) { + current = &(*current)->right; + } else if (id < (*current)->id) { + current = &(*current)->left; + } else { + return bst; + } + } + + *current = malloc(sizeof **current); + (*current)->id = id; + (*current)->left = NULL; + (*current)->right = NULL; + + return bst; +} + +static bool contains_id(struct id_bst *bst, uint64_t id) { + struct id_bst *current = bst; + + while (current) { + if (id == current->id) { + return true; + } else if (id < current->id) { + current = current->left; + } else { + current = current->right; + } + } + + return false; +} + +static void free_id_bst(struct id_bst *bst) { + if (bst) { + free_id_bst(bst->left); + free_id_bst(bst->right); + free(bst); + } +} + +/* string_list implementation */ + +static struct string_list *insert_file(struct string_list *list, + const char *string) { + struct string_list **current = &list; + struct string_list **prev = NULL; + + while (*current) { + prev = current; + current = &(*current)->next; + } + + *current = malloc(sizeof **current); + (*current)->string = string; + (*current)->prev = prev == NULL ? NULL : *prev; + (*current)->next = NULL; + + return list; +} + +static void free_string_list(struct string_list *list) { + if (list) { + free_string_list(list->next); + free(list); + } +} + +static const char *get_text_annotation(Annotation_list l, unsigned long id) { + int i; + + for (i = capn_len(l) - 1; i >= 0; i--) { + struct Annotation a; + struct Value v; + + get_Annotation(&a, l, i); + read_Value(&v, a.value); + + if (a.id == id) { + if (v.which != Value_text) { + fail(2, "annotation is not string"); + } + + return v.text.str; + } + } + + return NULL; +} + +static const char *get_mapname(Annotation_list l) { + return get_text_annotation(l, ANNOTATION_MAPNAME); +} + +static const char *get_maplistcount(Annotation_list l) { + return get_text_annotation(l, ANNOTATION_MAPLISTCOUNT); +} + +static const char *get_mapuniontag(Annotation_list l) { + return get_text_annotation(l, ANNOTATION_MAPUNIONTAG); +} + +/* resolve_names recursively follows the nestedNodes tree in order to + * set node->name. + * It also builds up the list of nodes within a file (file_nodes and + * next_file_node). */ +static void resolve_names(capnp_ctx_t *ctx, struct str *b, struct node *n, + capn_text name, struct node *file, + const char *namespace) { + int i, sz = b->len; + str_add(b, namespace, -1); + str_add(b, name.str, name.len); + str_add(&n->name, b->str, b->len); + str_add(b, "_", 1); + + for (i = capn_len(n->n.nestedNodes) - 1; i >= 0; i--) { + struct Node_NestedNode nest; + get_Node_NestedNode(&nest, n->n.nestedNodes, i); + struct node *nn = find_node(ctx, nest.id); + if (nn != NULL) { + resolve_names(ctx, b, nn, nest.name, file, namespace); + } + } + + if (n->n.which == Node__struct) { + for (i = capn_len(n->n._struct.fields) - 1; i >= 0; i--) { + if (n->fields[i].group) { + resolve_names(ctx, b, n->fields[i].group, n->fields[i].f.name, file, + namespace); + } + } + } + + if (n->n.which != Node__struct || !n->n._struct.isGroup) { + n->next_file_node = file->file_nodes; + file->file_nodes = n; + } + + str_setlen(b, sz); +} + +static void define_enum(capnp_ctx_t *ctx, struct node *n) { + int i; + + str_addf(&(ctx->HDR), "\nenum %s {", n->name.str); + for (i = 0; i < capn_len(n->n._enum.enumerants); i++) { + struct Enumerant e; + get_Enumerant(&e, n->n._enum.enumerants, i); + if (i) { + str_addf(&(ctx->HDR), ","); + } + str_addf(&(ctx->HDR), "\n\t%s_%s = %d", n->name.str, e.name.str, i); + } + str_addf(&(ctx->HDR), "\n};\n"); + + for (i = capn_len(n->n.annotations) - 1; i >= 0; i--) { + struct Annotation a; + struct Value v; + get_Annotation(&a, n->n.annotations, i); + read_Value(&v, a.value); + + switch (a.id) { + case ANNOTATION_TYPEDEFTO: + if (v.which != Value_text) { + fail(2, "schema breakage on $C::typedefto annotation\n"); + } + + str_addf(&(ctx->HDR), "\ntypedef enum %s %s;\n", n->name.str, v.text.str); + break; + } + } +} + +static void decode_value(capnp_ctx_t *ctx, struct value *v, Type_ptr type, + Value_ptr value, const char *symbol) { + struct Type list_type; + memset(v, 0, sizeof(*v)); + read_Type(&v->t, type); + read_Value(&v->v, value); + + switch (v->t.which) { + case Type__void: + v->tname = "void"; + break; + case Type__bool: + v->tname = "unsigned"; + break; + case Type_int8: + v->tname = "int8_t"; + break; + case Type_int16: + v->tname = "int16_t"; + break; + case Type_int32: + v->tname = "int32_t"; + break; + case Type_int64: + v->tname = "int64_t"; + break; + case Type_uint8: + v->tname = "uint8_t"; + break; + case Type_uint16: + v->tname = "uint16_t"; + break; + case Type_uint32: + v->tname = "uint32_t"; + break; + case Type_uint64: + v->tname = "uint64_t"; + break; + case Type_float32: + v->tname = "float"; + break; + case Type_float64: + v->tname = "double"; + break; + case Type_text: + v->tname = "capn_text"; + break; + case Type_data: + v->tname = "capn_data"; + break; + case Type__enum: + v->tname = strf(&v->tname_buf, "enum %s", + find_node(ctx, v->t._enum.typeId)->name.str); + break; + case Type__struct: + case Type__interface: + v->tname = strf(&v->tname_buf, "%s_ptr", + find_node(ctx, v->t._struct.typeId)->name.str); + break; + case Type_anyPointer: + v->tname = "capn_ptr"; + break; + case Type__list: + read_Type(&list_type, v->t._list.elementType); + + switch (list_type.which) { + case Type__void: + v->tname = "capn_ptr"; + break; + case Type__bool: + v->tname = "capn_list1"; + break; + case Type_int8: + case Type_uint8: + v->tname = "capn_list8"; + break; + case Type_int16: + case Type_uint16: + case Type__enum: + v->tname = "capn_list16"; + break; + case Type_int32: + case Type_uint32: + case Type_float32: + v->tname = "capn_list32"; + break; + case Type_int64: + case Type_uint64: + case Type_float64: + v->tname = "capn_list64"; + break; + case Type_text: + case Type_data: + case Type_anyPointer: + case Type__list: + v->tname = "capn_ptr"; + break; + case Type__struct: + case Type__interface: + v->tname = strf(&v->tname_buf, "%s_list", + find_node(ctx, list_type._struct.typeId)->name.str); + break; + } + } + + switch (v->v.which) { + case Value__bool: + v->intval = v->v._bool; + break; + case Value_int8: + case Value_uint8: + v->intval = v->v.int8; + break; + case Value_int16: + case Value_uint16: + v->intval = v->v.int16; + break; + case Value__enum: + v->intval = v->v._enum; + break; + case Value_int32: + case Value_uint32: + case Value_float32: + v->intval = v->v.int32; + break; + case Value_int64: + case Value_float64: + case Value_uint64: + v->intval = v->v.int64; + break; + case Value_text: + if (v->v.text.len) { + capn_ptr p = capn_root(&(ctx->g_valcapn)); + if (capn_set_text(p, 0, v->v.text)) { + fail(2, "fail to copy text\n"); + } + p = capn_getp(p, 0, 1); + if (!p.type) + break; + + v->ptrval = p; + + bool symbol_provided = symbol; + if (!symbol) { + static struct str buf = STR_INIT; + v->intval = ++(ctx->g_valc); + symbol = strf(&buf, "capn_val%d", (int)v->intval); + } + + str_addf(&(ctx->SRC), + "%scapn_text %s = {%d,(char*)&capn_buf[%d],(struct " + "capn_segment*)&capn_seg};\n", + symbol_provided ? "" : "static ", symbol, p.len - 1, + (int)(p.data - p.seg->data - 8)); + } + break; + + case Value_data: + case Value__struct: + case Value_anyPointer: + case Value__list: + if (v->v.anyPointer.type) { + capn_ptr p = capn_root(&(ctx->g_valcapn)); + if (capn_setp(p, 0, v->v.anyPointer)) { + fail(2, "failed to copy object\n"); + } + p = capn_getp(p, 0, 1); + if (!p.type) + break; + + v->ptrval = p; + + bool symbol_provided = symbol; + if (!symbol) { + static struct str buf = STR_INIT; + v->intval = ++(ctx->g_valc); + symbol = strf(&buf, "capn_val%d", (int)v->intval); + } + + str_addf(&(ctx->SRC), "%s%s %s = {", symbol_provided ? "" : "static ", + v->tname, symbol); + if (strcmp(v->tname, "capn_ptr")) + str_addf(&(ctx->SRC), "{"); + + str_addf(&(ctx->SRC), + "%d,%d,%d,%d,%d,%d,%d,(char*)&capn_buf[%d],(struct " + "capn_segment*)&capn_seg", + p.type, p.has_ptr_tag, p.is_list_member, p.is_composite_list, + p.datasz, p.ptrs, p.len, (int)(p.data - p.seg->data - 8)); + + if (strcmp(v->tname, "capn_ptr")) + str_addf(&(ctx->SRC), "}"); + + str_addf(&(ctx->SRC), "};\n"); + } + break; + + case Value__interface: + case Value__void: + break; + } +} + +static void define_const(capnp_ctx_t *ctx, struct node *n) { + struct value v; + decode_value(ctx, &v, n->n._const.type, n->n._const.value, n->name.str); + + switch (v.v.which) { + case Value__bool: + case Value_int8: + case Value_int16: + case Value_int32: + str_addf(&(ctx->HDR), "extern %s %s;\n", v.tname, n->name.str); + str_addf(&(ctx->SRC), "%s %s = %d;\n", v.tname, n->name.str, (int)v.intval); + break; + + case Value_uint8: + str_addf(&(ctx->HDR), "extern %s %s;\n", v.tname, n->name.str); + str_addf(&(ctx->SRC), "%s %s = %u;\n", v.tname, n->name.str, + (uint8_t)v.intval); + break; + + case Value_uint16: + str_addf(&(ctx->HDR), "extern %s %s;\n", v.tname, n->name.str); + str_addf(&(ctx->SRC), "%s %s = %u;\n", v.tname, n->name.str, + (uint16_t)v.intval); + break; + + case Value_uint32: + str_addf(&(ctx->HDR), "extern %s %s;\n", v.tname, n->name.str); + str_addf(&(ctx->SRC), "%s %s = %uu;\n", v.tname, n->name.str, + (uint32_t)v.intval); + break; + + case Value__enum: + str_addf(&(ctx->HDR), "extern %s %s;\n", v.tname, n->name.str); + str_addf(&(ctx->SRC), "%s %s = (%s) %uu;\n", v.tname, n->name.str, v.tname, + (uint32_t)v.intval); + break; + + case Value_int64: + case Value_uint64: + str_addf(&(ctx->HDR), "extern %s %s;\n", v.tname, n->name.str); + str_addf(&(ctx->SRC), "%s %s = ((uint64_t) %#xu << 32) | %#xu;\n", v.tname, + n->name.str, (uint32_t)(v.intval >> 32), (uint32_t)v.intval); + break; + + case Value_float32: + str_addf(&(ctx->HDR), "extern union capn_conv_f32 %s;\n", n->name.str); + str_addf(&(ctx->SRC), "union capn_conv_f32 %s = {%#xu};\n", n->name.str, + (uint32_t)v.intval); + break; + + case Value_float64: + str_addf(&(ctx->HDR), "extern union capn_conv_f64 %s;\n", n->name.str); + str_addf(&(ctx->SRC), + "union capn_conv_f64 %s = {((uint64_t) %#xu << 32) | %#xu};\n", + n->name.str, (uint32_t)(v.intval >> 32), (uint32_t)v.intval); + break; + + case Value_text: + case Value_data: + case Value__struct: + case Value_anyPointer: + case Value__list: + str_addf(&(ctx->HDR), "extern %s %s;\n", v.tname, n->name.str); + if (!v.ptrval.type) { + str_addf(&(ctx->SRC), "%s %s;\n", v.tname, n->name.str); + } + break; + + case Value__interface: + case Value__void: + break; + } + + str_release(&v.tname_buf); +} + +static void decode_field(capnp_ctx_t *ctx, struct field *fields, Field_list l, + int i) { + struct field f; + memset(&f, 0, sizeof(f)); + get_Field(&f.f, l, i); + + if (f.f.codeOrder >= capn_len(l)) { + fail(3, "unexpectedly large code order %d >= %d\n", f.f.codeOrder, + capn_len(l)); + } + + if (f.f.which == Field_group) { + f.group = find_node(ctx, f.f.group.typeId); + } + + memcpy(&fields[f.f.codeOrder], &f, sizeof(f)); +} + +static const char *xor_member(struct field *f) { + static struct str buf = STR_INIT; + + if (f->v.intval) { + switch (f->v.v.which) { + case Value_int8: + case Value_int16: + case Value_int32: + return strf(&buf, " ^ %d", (int32_t)f->v.intval); + + case Value_uint8: + return strf(&buf, " ^ %uu", (uint8_t)f->v.intval); + + case Value_uint16: + case Value__enum: + return strf(&buf, " ^ %uu", (uint16_t)f->v.intval); + + case Value_uint32: + return strf(&buf, " ^ %uu", (uint32_t)f->v.intval); + + case Value_float32: + return strf(&buf, " ^ %#xu", (uint32_t)f->v.intval); + + case Value_int64: + return strf(&buf, " ^ ((int64_t)((uint64_t) %#xu << 32) ^ %#xu)", + (uint32_t)(f->v.intval >> 32), (uint32_t)f->v.intval); + case Value_uint64: + case Value_float64: + return strf(&buf, " ^ ((uint64_t) %#xu << 32) ^ %#xu", + (uint32_t)(f->v.intval >> 32), (uint32_t)f->v.intval); + + default: + return ""; + } + } else { + return ""; + } +} + +static const char *ptr_member(struct field *f, const char *var) { + static struct str buf = STR_INIT; + if (!strcmp(f->v.tname, "capn_ptr")) { + return var; + } else if (var[0] == '*') { + return strf(&buf, "%s->p", var + 1); + } else { + return strf(&buf, "%s.p", var); + } +} + +static void set_member(capnp_ctx_t *ctx, struct str *func, struct field *f, + const char *ptr, const char *tab, const char *var) { + const char *xor = xor_member(f); + const char *pvar = ptr_member(f, var); + + if (f->v.t.which == Type__void) + return; + + str_add(func, tab, -1); + + switch (f->v.t.which) { + case Type__bool: + str_addf(func, "capn_write1(%s, %d, %s != %d);\n", ptr, f->f.slot.offset, + var, (int)f->v.intval); + break; + case Type_int8: + str_addf(func, "capn_write8(%s, %d, (uint8_t) (%s%s));\n", ptr, + f->f.slot.offset, var, xor); + break; + case Type_int16: + case Type__enum: + str_addf(func, "capn_write16(%s, %d, (uint16_t) (%s%s));\n", ptr, + 2 * f->f.slot.offset, var, xor); + break; + case Type_int32: + str_addf(func, "capn_write32(%s, %d, (uint32_t) (%s%s));\n", ptr, + 4 * f->f.slot.offset, var, xor); + break; + case Type_int64: + str_addf(func, "capn_write64(%s, %d, (uint64_t) (%s%s));\n", ptr, + 8 * f->f.slot.offset, var, xor); + break; + case Type_uint8: + str_addf(func, "capn_write8(%s, %d, %s%s);\n", ptr, f->f.slot.offset, var, + xor); + break; + case Type_uint16: + str_addf(func, "capn_write16(%s, %d, %s%s);\n", ptr, 2 * f->f.slot.offset, + var, xor); + break; + case Type_uint32: + str_addf(func, "capn_write32(%s, %d, %s%s);\n", ptr, 4 * f->f.slot.offset, + var, xor); + break; + case Type_float32: + str_addf(func, "capn_write32(%s, %d, capn_from_f32(%s)%s);\n", ptr, + 4 * f->f.slot.offset, var, xor); + break; + case Type_uint64: + str_addf(func, "capn_write64(%s, %d, %s%s);\n", ptr, 8 * f->f.slot.offset, + var, xor); + break; + case Type_float64: + str_addf(func, "capn_write64(%s, %d, capn_from_f64(%s)%s);\n", ptr, + 8 * f->f.slot.offset, var, xor); + break; + case Type_text: + if (f->v.ptrval.type) { + ctx->g_val0used = 1; + str_addf(func, + "capn_set_text(%s, %d, (%s.str != capn_val%d.str) ? %s : " + "capn_val0);\n", + ptr, f->f.slot.offset, var, (int)f->v.intval, var); + } else { + str_addf(func, "capn_set_text(%s, %d, %s);\n", ptr, f->f.slot.offset, + var); + } + break; + case Type_data: + case Type__struct: + case Type__interface: + case Type__list: + case Type_anyPointer: + if (!f->v.intval) { + str_addf(func, "capn_setp(%s, %d, %s);\n", ptr, f->f.slot.offset, pvar); + } else if (!strcmp(f->v.tname, "capn_ptr")) { + ctx->g_nullused = 1; + str_addf( + func, + "capn_setp(%s, %d, (%s.data != capn_val%d.data) ? %s : capn_null);\n", + ptr, f->f.slot.offset, pvar, (int)f->v.intval, pvar); + } else { + ctx->g_nullused = 1; + str_addf(func, + "capn_setp(%s, %d, (%s.data != capn_val%d.p.data) ? %s : " + "capn_null);\n", + ptr, f->f.slot.offset, pvar, (int)f->v.intval, pvar); + } + break; + default: + break; + } +} + +static void get_member(capnp_ctx_t *ctx, struct str *func, struct field *f, + const char *ptr, const char *tab, const char *var) { + const char *xor = xor_member(f); + const char *pvar = ptr_member(f, var); + + if (f->v.t.which == Type__void) + return; + + str_add(func, tab, -1); + + switch (f->v.t.which) { + case Type__bool: + str_addf(func, "%s = (capn_read8(%s, %d) & %d) != %d;\n", var, ptr, + f->f.slot.offset / 8, 1 << (f->f.slot.offset % 8), + ((int)f->v.intval) << (f->f.slot.offset % 8)); + return; + case Type_int8: + str_addf(func, "%s = (int8_t) ((int8_t)capn_read8(%s, %d))%s;\n", var, ptr, + f->f.slot.offset, xor); + return; + case Type_int16: + str_addf(func, "%s = (int16_t) ((int16_t)capn_read16(%s, %d))%s;\n", var, + ptr, 2 * f->f.slot.offset, xor); + return; + case Type_int32: + str_addf(func, "%s = (int32_t) ((int32_t)capn_read32(%s, %d))%s;\n", var, + ptr, 4 * f->f.slot.offset, xor); + return; + case Type_int64: + str_addf(func, "%s = (int64_t) ((int64_t)(capn_read64(%s, %d))%s);\n", var, + ptr, 8 * f->f.slot.offset, xor); + return; + case Type_uint8: + str_addf(func, "%s = capn_read8(%s, %d)%s;\n", var, ptr, f->f.slot.offset, + xor); + return; + case Type_uint16: + str_addf(func, "%s = capn_read16(%s, %d)%s;\n", var, ptr, + 2 * f->f.slot.offset, xor); + return; + case Type_uint32: + str_addf(func, "%s = capn_read32(%s, %d)%s;\n", var, ptr, + 4 * f->f.slot.offset, xor); + return; + case Type_uint64: + str_addf(func, "%s = capn_read64(%s, %d)%s;\n", var, ptr, + 8 * f->f.slot.offset, xor); + return; + case Type_float32: + str_addf(func, "%s = capn_to_f32(capn_read32(%s, %d)%s);\n", var, ptr, + 4 * f->f.slot.offset, xor); + return; + case Type_float64: + str_addf(func, "%s = capn_to_f64(capn_read64(%s, %d)%s);\n", var, ptr, + 8 * f->f.slot.offset, xor); + return; + case Type__enum: + str_addf(func, "%s = (%s)(int) capn_read16(%s, %d)%s;\n", var, f->v.tname, + ptr, 2 * f->f.slot.offset, xor); + return; + case Type_text: + if (!f->v.intval) + ctx->g_val0used = 1; + str_addf(func, "%s = capn_get_text(%s, %d, capn_val%d);\n", var, ptr, + f->f.slot.offset, (int)f->v.intval); + return; + + case Type_data: + str_addf(func, "%s = capn_get_data(%s, %d);\n", var, ptr, f->f.slot.offset); + break; + case Type__struct: + case Type__interface: + case Type_anyPointer: + case Type__list: + str_addf(func, "%s = capn_getp(%s, %d, 0);\n", pvar, ptr, f->f.slot.offset); + break; + default: + return; + } + + if (f->v.intval) { + str_addf(func, "%sif (!%s.type) {\n", tab, pvar); + str_addf(func, "%s\t%s = capn_val%d;\n", tab, var, (int)f->v.intval); + str_addf(func, "%s}\n", tab); + } +} + +static void mk_simple_list_encoder(struct str *func, const char *tab, + const char *list_type, const char *setf, + const char *dvar, const char *cvar, + const char *svar) { + str_add(func, tab, -1); + str_addf(func, "if (1) {\n"); + str_add(func, tab, -1); + str_addf(func, "\tint i_;\n"); + if (strcmp(list_type, "text") == 0) { + str_add(func, tab, -1); + str_addf(func, "\td->%s = capn_new_ptr_list(cs, s->%s);\n", dvar, cvar); + str_add(func, tab, -1); + str_addf(func, "\tfor(i_ = 0; i_ < s->%s; i_ ++) {\n", cvar); + str_add(func, tab, -1); + str_addf(func, + "\t\tcapn_text text_ = {.str = s->%s[i_], .len = " + "strlen(s->%s[i_]),.seg " + "= NULL};\n", + svar, svar); + str_add(func, tab, -1); + str_addf(func, "\t\tcapn_set_text(d->%s, i_, text_);\n", dvar); + str_add(func, tab, -1); + str_addf(func, "\t}\n"); + } else { + str_add(func, tab, -1); + str_addf(func, "\td->%s = capn_new_%s(cs, s->%s);\n", dvar, list_type, + cvar); + str_add(func, tab, -1); + str_addf(func, "\tfor(i_ = 0; i_ < s->%s; i_ ++) {\n", cvar); + str_add(func, tab, -1); + str_addf(func, "\t\tcapn_%s(d->%s, i_, s->%s[i_]);\n", setf, dvar, svar); + str_add(func, tab, -1); + str_addf(func, "\t}\n"); + } + str_add(func, tab, -1); + str_addf(func, "}\n"); +} + +static void mk_simple_list_decoder(struct str *func, const char *tab, + const char *list_type, const char *getf, + const char *dvar, const char *cvar, + const char *svar) { + str_add(func, tab, -1); + str_addf(func, "if (1) {\n"); + str_add(func, tab, -1); + str_addf(func, "\tint i_, nc_;\n"); + if (strcmp(list_type, "text") == 0) { + str_add(func, tab, -1); + str_addf(func, "\tcapn_resolve(&(s->%s));\n", svar); + str_add(func, tab, -1); + str_addf(func, "\tnc_ = s->%s.len;\n", svar); + str_add(func, tab, -1); + str_addf(func, "\tif (nc_ == 0) {\n"); + str_add(func, tab, -1); + str_addf(func, "\t\td->%s = NULL;\n", dvar); + str_add(func, tab, -1); + str_addf(func, "\t}\n"); + str_add(func, tab, -1); + str_addf(func, "\telse {\n"); + str_add(func, tab, -1); + str_addf(func, "\t\td->%s = (char **)calloc(nc_, sizeof(char *));\n", dvar); + str_add(func, tab, -1); + str_addf(func, "\t\tfor(i_ = 0; i_ < nc_; i_ ++) {\n"); + str_add(func, tab, -1); + str_addf(func, + "\t\t\tcapn_text text_ = capn_get_text(s->%s, i_, capn_val0);\n", + svar); + str_add(func, tab, -1); + str_addf(func, "\t\t\td->%s[i_] = STRING_DUP(text_.str);\n", dvar); + str_add(func, tab, -1); + str_addf(func, "\t\t}\n"); + str_add(func, tab, -1); + str_addf(func, "\t}\n"); + } else { + str_add(func, tab, -1); + str_addf(func, "\tcapn_resolve(&(s->%s.p));\n", svar); + str_add(func, tab, -1); + str_addf(func, "\tnc_ = s->%s.p.len;\n", svar); + str_add(func, tab, -1); + str_addf(func, "\tif (nc_ == 0) {\n"); + str_add(func, tab, -1); + str_addf(func, "\t\td->%s = NULL;\n", dvar); + str_add(func, tab, -1); + str_addf(func, "\t}\n"); + str_add(func, tab, -1); + str_addf(func, "\telse {\n"); + str_add(func, tab, -1); + str_addf(func, "\t\td->%s = (%s *)calloc(nc_, sizeof(%s));\n", dvar, + list_type, list_type); + str_add(func, tab, -1); + str_addf(func, "\t\tfor(i_ = 0; i_ < nc_; i_ ++) {\n"); + str_add(func, tab, -1); + str_addf(func, "\t\t\td->%s[i_] = capn_%s(s->%s, i_);\n", dvar, getf, svar); + str_add(func, tab, -1); + str_addf(func, "\t\t}\n"); + str_add(func, tab, -1); + str_addf(func, "\t}\n"); + } + + str_add(func, tab, -1); + str_addf(func, "d->%s = nc_;\n", cvar); + str_add(func, tab, -1); + str_addf(func, "}\n"); +} + +static void mk_simple_list_free(struct str *func, const char *tab, + const char *list_type, const char *getf, + const char *dvar, const char *cvar, + const char *svar) { + str_add(func, tab, -1); + str_addf(func, "if (1) {\n"); + str_add(func, tab, -1); + str_addf(func, "\tint i_, nc_ = d->%s;\n", cvar); + str_add(func, tab, -1); + str_addf(func, "\tcapnp_use(i_);capnp_use(nc_);\n"); + if (strcmp(list_type, "text") == 0) { + str_add(func, tab, -1); + str_addf(func, "\tfor(i_ = 0; i_ < nc_; i_ ++) {\n"); + str_add(func, tab, -1); + str_addf(func, "\t\tif (d->%s[i_] == NULL) continue;\n", dvar); + str_add(func, tab, -1); + str_addf(func, "\t\tfree(d->%s[i_]);\n", dvar); + str_add(func, tab, -1); + str_addf(func, "\t}\n"); + } + + str_add(func, tab, -1); + str_addf(func, "\tfree(d->%s);\n", dvar); + str_add(func, tab, -1); + str_addf(func, "}\n"); +} + +static void gen_call_list_encoder(capnp_ctx_t *ctx, struct str *func, + struct Type *type, const char *tab, + const char *var, const char *countvar, + const char *var2) { + struct node *n = NULL; + + str_add(func, tab, -1); + + switch (type->which) { + case Type__bool: + mk_simple_list_encoder(func, tab, "list1", "set1", var, countvar, var2); + break; + case Type_int8: + case Type_uint8: + mk_simple_list_encoder(func, tab, "list8", "set8", var, countvar, var2); + break; + case Type_int16: + case Type_uint16: + mk_simple_list_encoder(func, tab, "list16", "set16", var, countvar, var2); + break; + case Type_int32: + case Type_uint32: + case Type_float32: + mk_simple_list_encoder(func, tab, "list32", "set32", var, countvar, var2); + break; + case Type_int64: + case Type_uint64: + case Type_float64: + mk_simple_list_encoder(func, tab, "list64", "set64", var, countvar, var2); + break; + case Type_text: + mk_simple_list_encoder(func, tab, "text", NULL, var, countvar, var2); + break; + case Type__struct: + n = find_node(ctx, type->_struct.typeId); + + if (n != NULL) { + char *dtypename = n->name.str; + + str_addf(func, "encode_%s_list(cs, &(d->%s), s->%s, s->%s);\n", dtypename, + var, countvar, var2); + } + break; + } +} + +static void gen_call_list_decoder(capnp_ctx_t *ctx, struct str *func, + struct Type *type, const char *tab, + const char *var, const char *countvar, + const char *var2) { + char *t = NULL; + struct node *n = NULL; + + str_add(func, tab, -1); + + switch (type->which) { + case Type__bool: + t = "uint8_t"; + mk_simple_list_decoder(func, tab, t, "get1", var, countvar, var2); + break; + case Type_int8: + case Type_uint8: + if (type->which == Type_int8) { + t = "int8_t"; + } else { + t = "uint8_t"; + } + mk_simple_list_decoder(func, tab, t, "get8", var, countvar, var2); + break; + case Type_int16: + case Type_uint16: + if (type->which == Type_int16) { + t = "int16_t"; + } else { + t = "uint16_t"; + } + mk_simple_list_decoder(func, tab, t, "get16", var, countvar, var2); + break; + case Type_int32: + case Type_uint32: + case Type_float32: + if (type->which == Type_int32) { + t = "int32_t"; + } else if (type->which == Type_uint32) { + t = "uint32_t"; + } else { + t = "float"; + } + mk_simple_list_decoder(func, tab, t, "get32", var, countvar, var2); + break; + case Type_int64: + case Type_uint64: + case Type_float64: + if (type->which == Type_int64) { + t = "int64_t"; + } else if (type->which == Type_uint64) { + t = "uint64_t"; + } else { + t = "double"; + } + mk_simple_list_decoder(func, tab, t, "get64", var, countvar, var2); + break; + + case Type_text: + mk_simple_list_decoder(func, tab, "text", NULL, var, countvar, var2); + break; + case Type__struct: + n = find_node(ctx, type->_struct.typeId); + if (n != NULL) { + char *dtypename = n->name.str; + + str_addf(func, "decode_%s_list(&(d->%s), &(d->%s), s->%s);\n", dtypename, + countvar, var, var2); + } + break; + } +} + +static void gen_call_list_free(capnp_ctx_t *ctx, struct str *func, + struct Type *type, const char *tab, + const char *var, const char *countvar, + const char *var2) { + char *t = NULL; + struct node *n = NULL; + + str_add(func, tab, -1); + + switch (type->which) { + case Type__bool: + t = "uint8_t"; + mk_simple_list_free(func, tab, t, "get1", var, countvar, var2); + break; + case Type_int8: + case Type_uint8: + if (type->which == Type_int8) { + t = "int8_t"; + } else { + t = "uint8_t"; + } + mk_simple_list_free(func, tab, t, "get8", var, countvar, var2); + break; + case Type_int16: + case Type_uint16: + if (type->which == Type_int16) { + t = "int16_t"; + } else { + t = "uint16_t"; + } + mk_simple_list_free(func, tab, t, "get16", var, countvar, var2); + break; + case Type_int32: + case Type_uint32: + case Type_float32: + if (type->which == Type_int32) { + t = "int32_t"; + } else if (type->which == Type_uint32) { + t = "uint32_t"; + } else { + t = "float"; + } + mk_simple_list_free(func, tab, t, "get32", var, countvar, var2); + break; + case Type_int64: + case Type_uint64: + case Type_float64: + if (type->which == Type_int64) { + t = "int64_t"; + } else if (type->which == Type_uint64) { + t = "uint64_t"; + } else { + t = "double"; + } + mk_simple_list_free(func, tab, t, "get64", var, countvar, var2); + break; + + case Type_text: + mk_simple_list_free(func, tab, "text", NULL, var, countvar, var2); + break; + case Type__struct: + n = find_node(ctx, type->_struct.typeId); + if (n != NULL) { + char *dtypename = n->name.str; + + str_addf(func, "free_%s_list(d->%s, d->%s);\n", dtypename, countvar, var); + } + break; + } +} + +static void encode_member(capnp_ctx_t *ctx, struct str *func, struct field *f, + const char *tab, const char *var, const char *var2) { + struct Type list_type; + struct node *n = NULL; + + if (f->v.t.which == Type__void) { + return; + } + + if (var2 == NULL) { + var2 = var; + } + + switch (f->v.t.which) { + case Type__bool: + case Type_int8: + case Type_int16: + case Type_int32: + case Type_int64: + case Type_uint8: + case Type_uint16: + case Type_uint32: + case Type_uint64: + case Type_float32: + case Type_float64: + case Type__enum: + str_add(func, tab, -1); + str_addf(func, "d->%s = s->%s;\n", var, var2); + break; + case Type_text: + str_add(func, tab, -1); + str_addf(func, "if (s->%s != NULL) {\n", var2); + str_add(func, tab, -1); + str_addf(func, "\td->%s.str = s->%s;\n", var, var2); + str_add(func, tab, -1); + str_addf(func, "\td->%s.len = strlen(s->%s);\n", var, var2); + str_add(func, tab, -1); + str_addf(func, "}\n"); + str_add(func, tab, -1); + str_addf(func, "else{\n"); + str_add(func, tab, -1); + str_addf(func, "\td->%s.str = \"\";\n", var); + str_add(func, tab, -1); + str_addf(func, "\td->%s.len = 0;\n", var); + str_add(func, tab, -1); + str_addf(func, "}\n"); + str_add(func, tab, -1); + str_addf(func, "d->%s.seg = NULL;\n", var); + break; + case Type__struct: + n = find_node(ctx, f->v.t._struct.typeId); + + if (n != NULL) { + str_add(func, tab, -1); + str_addf(func, "encode_%s_ptr(cs, &(d->%s), s->%s);\n", n->name.str, var, + var2); + } + break; + case Type__list: + read_Type(&list_type, f->v.t._list.elementType); + if (list_type.which != Type__void) { + char *name = NULL; + char *ncount = NULL; + char buf[256]; + + name = (char *)get_mapname(f->f.annotations); + if (name == NULL) { + var2 = var; + } else { + var2 = name; + } + + ncount = (char *)get_maplistcount(f->f.annotations); + if (ncount != NULL) { + sprintf(buf, "%s", ncount); + } else { + sprintf(buf, "n_%s", var2); + } + + gen_call_list_encoder(ctx, func, &list_type, tab, var, buf, var2); + } + break; + default: + str_add(func, tab, -1); + str_addf(func, "\t /* %s %s */\n", var, var2); + break; + } +} + +static void decode_member(capnp_ctx_t *ctx, struct str *func, struct field *f, + const char *tab, const char *var, const char *var2) { + struct Type list_type; + struct node *n = NULL; + + if (f->v.t.which == Type__void) { + return; + } + + if (var2 == NULL) { + var2 = var; + } + + switch (f->v.t.which) { + case Type__bool: + case Type_int8: + case Type_int16: + case Type_int32: + case Type_int64: + case Type_uint8: + case Type_uint16: + case Type_uint32: + case Type_uint64: + case Type_float32: + case Type_float64: + case Type__enum: + str_add(func, tab, -1); + str_addf(func, "d->%s = s->%s;\n", var2, var); + break; + case Type_text: + str_add(func, tab, -1); + str_addf(func, "d->%s = STRING_DUP(s->%s.str);\n", var2, var); + break; + case Type__struct: + n = find_node(ctx, f->v.t._struct.typeId); + if (n != NULL) { + str_add(func, tab, -1); + str_addf(func, "decode_%s_ptr(&(d->%s), s->%s);\n", n->name.str, var2, + var); + } + break; + case Type__list: + read_Type(&list_type, f->v.t._list.elementType); + if (list_type.which != Type__void) { + char *name = NULL; + char *ncount = NULL; + char buf[256]; + + name = (char *)get_mapname(f->f.annotations); + if (name == NULL) { + var2 = var; + } else { + var2 = name; + } + + ncount = (char *)get_maplistcount(f->f.annotations); + if (ncount != NULL) { + sprintf(buf, "%s", ncount); + } else { + char buf2[256]; + char *p; + + strcpy(buf2, var2); + p = strchr(buf2, '.'); + if (p != NULL) { + *p = 0x0; + p++; + } + + strcpy(buf, buf2); + if (p != NULL) { + strcat(buf, "."); + sprintf(&buf[strlen(buf)], "n_%s", p); + } + } + + gen_call_list_decoder(ctx, func, &list_type, tab, var2, buf, var); + } + break; + default: + str_add(func, tab, -1); + str_addf(func, "\t /* %s %s */\n", var2, var); + break; + } +} + +static void free_member(capnp_ctx_t *ctx, struct str *func, struct field *f, + const char *tab, const char *var, const char *var2) { + struct Type list_type; + struct node *n = NULL; + + if (f->v.t.which == Type__void) { + return; + } + + if (var2 == NULL) { + var2 = var; + } + + switch (f->v.t.which) { + case Type__bool: + case Type_int8: + case Type_int16: + case Type_int32: + case Type_int64: + case Type_uint8: + case Type_uint16: + case Type_uint32: + case Type_uint64: + case Type_float32: + case Type_float64: + case Type__enum: + break; + case Type_text: + str_add(func, tab, -1); + str_addf(func, "if (d->%s != NULL) {\n", var2); + str_add(func, tab, -1); + str_addf(func, "\tfree(d->%s);\n", var2); + str_add(func, tab, -1); + str_addf(func, "}\n"); + break; + case Type__struct: + n = find_node(ctx, f->v.t._struct.typeId); + if (n != NULL) { + str_add(func, tab, -1); + str_addf(func, "free_%s_ptr(&(d->%s));\n", n->name.str, var2); + } + break; + case Type__list: + read_Type(&list_type, f->v.t._list.elementType); + if (list_type.which != Type__void) { + char *name = NULL; + char *ncount = NULL; + char buf[256]; + + name = (char *)get_mapname(f->f.annotations); + if (name == NULL) { + var2 = var; + } else { + var2 = name; + } + + ncount = (char *)get_maplistcount(f->f.annotations); + if (ncount != NULL) { + sprintf(buf, "%s", ncount); + } else { + char buf2[256]; + char *p; + + strcpy(buf2, var2); + p = strchr(buf2, '.'); + if (p != NULL) { + *p = 0x0; + p++; + } + + strcpy(buf, buf2); + if (p != NULL) { + strcat(buf, "."); + sprintf(&buf[strlen(buf)], "n_%s", p); + } + } + + gen_call_list_free(ctx, func, &list_type, tab, var2, buf, var); + } + break; + default: + str_add(func, tab, -1); + str_addf(func, "\t /* %s %s */\n", var2, var); + break; + } +} + +void mk_struct_list_encoder(capnp_ctx_t *ctx, struct node *n) { + if (n == NULL) { + return; + } + + if (1) { + char *mapname = (char *)get_mapname(n->n.annotations); + char buf[256]; + + if (mapname == NULL) { + sprintf(buf, "struct %s_", n->name.str); + } else { + strcpy(buf, mapname); + } + + str_addf(&(ctx->SRC), + "void encode_%s_list(struct capn_segment *cs, %s_list *l,int " + "count,%s **s) {\n", + n->name.str, n->name.str, buf); + str_addf(&(ctx->SRC), "\t%s_list lst;\n", n->name.str); + str_addf(&(ctx->SRC), "\tint i;\n"); + str_addf(&(ctx->SRC), "\tlst = new_%s_list(cs, count);\n", n->name.str); + str_addf(&(ctx->SRC), "\tfor(i = 0; i < count; i ++) {\n"); + str_addf(&(ctx->SRC), "\t\tstruct %s d;\n", n->name.str); + str_addf(&(ctx->SRC), "\t\tencode_%s(cs, &d, s[i]);\n", n->name.str); + str_addf(&(ctx->SRC), "\t\tset_%s(&d, lst, i);\n", n->name.str); + str_addf(&(ctx->SRC), "\t}\n"); + str_addf(&(ctx->SRC), "\t(*l) = lst;\n"); + str_addf(&(ctx->SRC), "}\n"); + } +} + +void mk_struct_ptr_encoder(capnp_ctx_t *ctx, struct node *n) { + char *mapname; + char buf[256]; + + if (n == NULL) { + return; + } + + mapname = (char *)get_mapname(n->n.annotations); + + if (mapname == NULL) { + sprintf(buf, "struct %s_", n->name.str); + } else { + strcpy(buf, mapname); + } + + str_addf(&(ctx->SRC), + "void encode_%s_ptr(struct capn_segment *cs, %s_ptr *p," + "%s *s) {\n", + n->name.str, n->name.str, buf); + str_addf(&(ctx->SRC), "\t%s_ptr ptr;\n", n->name.str); + str_addf(&(ctx->SRC), "\tstruct %s d;\n", n->name.str); + str_addf(&(ctx->SRC), "\tptr = new_%s(cs);\n", n->name.str); + str_addf(&(ctx->SRC), "\tif (s == NULL) {\n"); + str_addf(&(ctx->SRC), "\t\tptr.p = capn_null;\n"); + str_addf(&(ctx->SRC), "\t}\n"); + str_addf(&(ctx->SRC), "\telse{\n"); + str_addf(&(ctx->SRC), "\t\tencode_%s(cs, &d, s);\n", n->name.str); + str_addf(&(ctx->SRC), "\t\twrite_%s(&d, ptr);\n", n->name.str); + str_addf(&(ctx->SRC), "\t}\n"); + str_addf(&(ctx->SRC), "\t(*p) = ptr;\n"); + str_addf(&(ctx->SRC), "}\n"); + ctx->g_nullused = 1; +} + +void mk_struct_list_decoder(capnp_ctx_t *ctx, struct node *n) { + if (n == NULL) { + return; + } + + if (1) { + char *mapname = (char *)get_mapname(n->n.annotations); + char buf[256]; + + if (mapname == NULL) { + sprintf(buf, "struct %s_", n->name.str); + } else { + strcpy(buf, mapname); + } + + str_addf(&(ctx->SRC), + "void decode_%s_list(int *pcount, %s ***d, %s_list list) {\n", + n->name.str, buf, n->name.str); + str_addf(&(ctx->SRC), "\tint i;\n"); + str_addf(&(ctx->SRC), "\tint nc;\n"); + str_addf(&(ctx->SRC), "\t%s **ptr;\n", buf); + str_addf(&(ctx->SRC), "\tcapn_resolve(&(list.p));\n"); + str_addf(&(ctx->SRC), "\tnc = list.p.len;\n"); + str_addf(&(ctx->SRC), "\tif (nc == 0) {\n"); + str_addf(&(ctx->SRC), "\t\t(*d) = NULL;\n"); + str_addf(&(ctx->SRC), "\t\t(*pcount) = 0;\n"); + str_addf(&(ctx->SRC), "\t\treturn;\n"); + str_addf(&(ctx->SRC), "\t}\n"); + str_addf(&(ctx->SRC), "\tptr = (%s **)calloc(nc, sizeof(%s *));\n", buf, + buf); + str_addf(&(ctx->SRC), "\tfor(i = 0; i < nc; i ++) {\n"); + str_addf(&(ctx->SRC), "\t\tstruct %s s;\n", n->name.str); + str_addf(&(ctx->SRC), "\t\tget_%s(&s, list, i);\n", n->name.str); + str_addf(&(ctx->SRC), "\t\tptr[i] = (%s *)calloc(1, sizeof(%s));\n", buf, + buf); + str_addf(&(ctx->SRC), "\t\tdecode_%s(ptr[i], &s);\n", n->name.str); + str_addf(&(ctx->SRC), "\t}\n"); + str_addf(&(ctx->SRC), "\t(*d) = ptr;\n"); + str_addf(&(ctx->SRC), "\t(*pcount) = nc;\n"); + str_addf(&(ctx->SRC), "}\n"); + } +} + +void mk_struct_ptr_decoder(capnp_ctx_t *ctx, struct node *n) { + char *mapname; + char buf[256]; + + if (n == NULL) { + return; + } + + mapname = (char *)get_mapname(n->n.annotations); + + if (mapname == NULL) { + sprintf(buf, "struct %s_", n->name.str); + } else { + strcpy(buf, mapname); + } + + str_addf(&(ctx->SRC), + "void decode_%s_ptr(%s **d," + "%s_ptr p) {\n", + n->name.str, buf, n->name.str); + str_addf(&(ctx->SRC), "\tstruct %s s;\n", n->name.str); + str_addf(&(ctx->SRC), "\tcapn_resolve(&(p.p));\n"); + str_addf(&(ctx->SRC), "\tif (p.p.type == CAPN_NULL) {\n"); + str_addf(&(ctx->SRC), "\t\t(*d) = NULL;\n"); + str_addf(&(ctx->SRC), "\t\treturn;\n"); + str_addf(&(ctx->SRC), "\t}\n"); + str_addf(&(ctx->SRC), "\t*d = (%s *)calloc(1, sizeof(%s));\n", buf, buf); + str_addf(&(ctx->SRC), "\tread_%s(&s, p);\n", n->name.str); + str_addf(&(ctx->SRC), "\tdecode_%s(*d, &s);\n", n->name.str); + str_addf(&(ctx->SRC), "}\n"); + ctx->g_nullused = 1; +} + +void mk_struct_list_free(capnp_ctx_t *ctx, struct node *n) { + if (n == NULL) { + return; + } + + if (1) { + char *mapname = (char *)get_mapname(n->n.annotations); + char buf[256]; + + if (mapname == NULL) { + sprintf(buf, "struct %s_", n->name.str); + } else { + strcpy(buf, mapname); + } + + str_addf(&(ctx->SRC), "void free_%s_list(int pcount, %s **d) {\n", + n->name.str, buf); + str_addf(&(ctx->SRC), "\tint i;\n"); + str_addf(&(ctx->SRC), "\tint nc = pcount;\n"); + str_addf(&(ctx->SRC), "\t%s **ptr = d;\n", buf); + str_addf(&(ctx->SRC), "\tif (ptr == NULL) return;\n"); + str_addf(&(ctx->SRC), "\tfor(i = 0; i < nc; i ++) {\n"); + str_addf(&(ctx->SRC), "\t\tif(ptr[i] == NULL) continue;\n"); + str_addf(&(ctx->SRC), "\t\tfree_%s(ptr[i]);\n", n->name.str); + str_addf(&(ctx->SRC), "\t\tfree(ptr[i]);\n"); + str_addf(&(ctx->SRC), "\t}\n"); + str_addf(&(ctx->SRC), "\tfree(ptr);\n"); + str_addf(&(ctx->SRC), "}\n"); + } +} + +void mk_struct_ptr_free(capnp_ctx_t *ctx, struct node *n) { + char *mapname; + char buf[256]; + + if (n == NULL) { + return; + } + + mapname = (char *)get_mapname(n->n.annotations); + + if (mapname == NULL) { + sprintf(buf, "struct %s_", n->name.str); + } else { + strcpy(buf, mapname); + } + + str_addf(&(ctx->SRC), "void free_%s_ptr(%s **d){\n", n->name.str, buf); + str_addf(&(ctx->SRC), "\tif((*d) == NULL) return;\n"); + str_addf(&(ctx->SRC), "\tfree_%s(*d);\n", n->name.str); + str_addf(&(ctx->SRC), "\tfree(*d);\n"); + str_addf(&(ctx->SRC), "\t(*d) = NULL;\n"); + str_addf(&(ctx->SRC), "}\n"); +} + +struct strings { + struct str ftab; + struct str dtab; + struct str get; + struct str set; + struct str encoder; + struct str decoder; + struct str freeup; + struct str enums; + struct str decl; + struct str var; + struct str pub_get; + struct str pub_get_header; + struct str pub_set; + struct str pub_set_header; +}; + +static const char *field_name(struct field *f) { + static struct str buf = STR_INIT; + static const char *reserved[] = { + /* C++11 reserved words */ + "alignas", + "alignof", + "and", + "and_eq", + "asm", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char16_t", + "char32_t", + "class", + "compl", + "const", + "constexpr", + "const_cast", + "continue", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "inline", + "int", + "long", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq", + /* COM reserved words */ + "interface", + "module", + "import", + /* capn reserved otherwise Value_ptr enum and type collide */ + "ptr", + "list", + /* C11 keywords not reserved in C++ */ + "restrict", + "_Alignas", + "_Alignof", + "_Atomic", + "_Bool", + "_Complex", + "_Generic", + "_Imaginary", + "_Noreturn", + "_Static_assert", + "_Thread_local", + /* capn reserved for parameter names */ + "p", + }; + + size_t i; + const char *s = f->f.name.str; + for (i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++) { + if (!strcmp(s, reserved[i])) { + return strf(&buf, "_%s", s); + } + } + + return s; +} + +static void union_block(capnp_ctx_t *ctx, struct strings *s, struct field *f, + const char *u1, const char *u2) { + static struct str buf = STR_INIT; + str_add(&s->ftab, "\t", -1); + set_member(ctx, &s->set, f, "p.p", s->ftab.str, + strf(&buf, "%s%s", s->var.str, field_name(f))); + get_member(ctx, &s->get, f, "p.p", s->ftab.str, + strf(&buf, "%s%s", s->var.str, field_name(f))); + str_addf(&s->set, "%sbreak;\n", s->ftab.str); + str_addf(&s->get, "%sbreak;\n", s->ftab.str); + if (ctx->g_codecgen) { + char var1[256]; + char var2[256]; + char *mapname = (char *)get_mapname(f->f.annotations); + + if (u2 == NULL) { + u2 = u1; + } + + if (mapname == NULL) { + mapname = (char *)field_name(f); + } + + if (u1 != NULL) { + sprintf(var1, "%s.%s", u1, field_name(f)); + sprintf(var2, "%s.%s", u2, mapname); + } else { + strcpy(var1, field_name(f)); + strcpy(var2, mapname); + } + + encode_member(ctx, &s->encoder, f, s->ftab.str, var1, var2); + str_addf(&s->encoder, "%sbreak;\n", s->ftab.str); + decode_member(ctx, &s->decoder, f, s->ftab.str, var1, var2); + str_addf(&s->decoder, "%sbreak;\n", s->ftab.str); + free_member(ctx, &s->freeup, f, s->ftab.str, var1, var2); + str_addf(&s->freeup, "%sbreak;\n", s->ftab.str); + } + str_setlen(&s->ftab, s->ftab.len - 1); +} + +static int in_union(struct field *f) { + return f->f.discriminantValue != 0xFFFF; +} + +static void union_cases(capnp_ctx_t *ctx, struct strings *s, struct node *n, + struct field *first_field, int mask) { + struct field *f, *u = NULL; + + for (f = first_field; + f < n->fields + capn_len(n->n._struct.fields) && in_union(f); f++) { + + if (f->f.which != Field_slot) + continue; + if (f->v.ptrval.type || f->v.intval) + continue; + if ((mask & (1 << f->v.t.which)) == 0) + continue; + + u = f; + str_addf(&s->set, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + str_addf(&s->get, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + if (ctx->g_codecgen) { + str_addf(&s->encoder, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + str_addf(&s->decoder, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + str_addf(&s->freeup, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + } + + if (u) { + union_block(ctx, s, u, + &(n->n.displayName.str[n->n.displayNamePrefixLength]), NULL); + } + } +} + +static void declare_slot(struct strings *s, struct field *f) { + switch (f->v.t.which) { + case Type__void: + break; + case Type__bool: + str_addf(&s->decl, "%s%s %s : 1;\n", s->dtab.str, f->v.tname, + field_name(f)); + break; + default: + str_addf(&s->decl, "%s%s %s;\n", s->dtab.str, f->v.tname, field_name(f)); + break; + } +} + +static void define_group(capnp_ctx_t *ctx, struct strings *s, struct node *n, + const char *group_name, bool enclose_unions, + const char *extattr, const char *extattr_space, + const char *uniontag); + +static void do_union(capnp_ctx_t *ctx, struct strings *s, struct node *n, + struct field *first_field, const char *union_name, + const char *extattr, const char *extattr_space, + const char *uniontag) { + int tagoff = 2 * n->n._struct.discriminantOffset; + struct field *f; + static struct str tag = STR_INIT; + struct str enums = STR_INIT; + + str_reset(&tag); + + if (union_name) { + str_addf(&tag, "%.*s_which", s->var.len - 1, s->var.str); + str_addf(&enums, "enum %s_which {", n->name.str); + str_addf(&s->decl, "%senum %s_which %s_which;\n", s->dtab.str, n->name.str, + union_name); + str_addf(&s->get, "%s%s = (enum %s_which)(int) capn_read16(p.p, %d);\n", + s->ftab.str, tag.str, n->name.str, tagoff); + } else { + str_addf(&tag, "%swhich", s->var.str); + str_addf(&enums, "enum %s_which {", n->name.str); + str_addf(&s->decl, "%senum %s_which which;\n", s->dtab.str, n->name.str); + str_addf(&s->get, "%s%s = (enum %s_which)(int) capn_read16(p.p, %d);\n", + s->ftab.str, tag.str, n->name.str, tagoff); + } + + str_addf(&s->set, "%scapn_write16(p.p, %d, %s);\n", s->ftab.str, tagoff, + tag.str); + str_addf(&s->set, "%sswitch (%s) {\n", s->ftab.str, tag.str); + str_addf(&s->get, "%sswitch (%s) {\n", s->ftab.str, tag.str); + + if (ctx->g_codecgen) { + char var[256]; + char *p = strstr(tag.str, "->"); + + if (p == NULL) { + fail(2, "bad variable"); + } + + sprintf(var, "d%s", p); + + str_addf(&s->encoder, "%sswitch (%s) {\n", s->ftab.str, var); + str_addf(&s->decoder, "%sswitch (%s) {\n", s->ftab.str, tag.str); + str_addf(&s->freeup, "%sswitch (%s) {\n", s->ftab.str, uniontag); + } + + /* if we have a bunch of the same C type with zero defaults, we + * only need to emit one switch block as the layout will line up + * in the C union */ + union_cases(ctx, s, n, first_field, (1 << Type__bool)); + union_cases(ctx, s, n, first_field, (1 << Type__enum)); + union_cases(ctx, s, n, first_field, (1 << Type_int8) | (1 << Type_uint8)); + union_cases(ctx, s, n, first_field, (1 << Type_int16) | (1 << Type_uint16)); + union_cases(ctx, s, n, first_field, + (1 << Type_int32) | (1 << Type_uint32) | (1 << Type_float32)); + union_cases(ctx, s, n, first_field, + (1 << Type_int64) | (1 << Type_uint64) | (1 << Type_float64)); + union_cases(ctx, s, n, first_field, (1 << Type_text)); + union_cases(ctx, s, n, first_field, (1 << Type_data)); + union_cases(ctx, s, n, first_field, + (1 << Type__struct) | (1 << Type__interface) | + (1 << Type_anyPointer) | (1 << Type__list)); + + str_addf(&s->decl, "%scapnp_nowarn union {\n", s->dtab.str); + str_add(&s->dtab, "\t", -1); + + /* when we have defaults or groups we have to emit each case seperately */ + for (f = first_field; + f < n->fields + capn_len(n->n._struct.fields) && in_union(f); f++) { + if (f > first_field) { + str_addf(&enums, ","); + } + + str_addf(&enums, "\n\t%s_%s = %d", n->name.str, field_name(f), + f->f.discriminantValue); + + switch (f->f.which) { + case Field_group: + str_addf(&s->get, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + str_addf(&s->set, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + str_add(&s->ftab, "\t", -1); + // When we add a union inside a union, we need to enclose it in its + // own struct so that its members do not overwrite its own + // discriminant. + define_group(ctx, s, f->group, field_name(f), true, extattr, + extattr_space, uniontag); + str_addf(&s->get, "%sbreak;\n", s->ftab.str); + str_addf(&s->set, "%sbreak;\n", s->ftab.str); + if (ctx->g_codecgen) { + str_addf(&s->encoder, "%sbreak;\n", s->ftab.str); + str_addf(&s->decoder, "%sbreak;\n", s->ftab.str); + str_addf(&s->freeup, "%sbreak;\n", s->ftab.str); + } + str_setlen(&s->ftab, s->ftab.len - 1); + break; + + case Field_slot: + declare_slot(s, f); + if (f->v.ptrval.type || f->v.intval) { + str_addf(&s->get, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + str_addf(&s->set, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + if (ctx->g_codecgen) { + str_addf(&s->encoder, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + str_addf(&s->decoder, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + str_addf(&s->freeup, "%scase %s_%s:\n", s->ftab.str, n->name.str, + field_name(f)); + } + union_block( + ctx, s, f, + NULL /*&(n->n.displayName.str[n->n.displayNamePrefixLength]) */, + NULL); + } + break; + + default: + break; + } + } + + str_setlen(&s->dtab, s->dtab.len - 1); + + if (union_name) { + str_addf(&s->decl, "%s} %s;\n", s->dtab.str, union_name); + } else { + str_addf(&s->decl, "%s};\n", s->dtab.str); + } + + str_addf(&s->get, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str, s->ftab.str, + s->ftab.str); + str_addf(&s->set, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str, s->ftab.str, + s->ftab.str); + + if (ctx->g_codecgen) { + str_addf(&s->encoder, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str, + s->ftab.str, s->ftab.str); + str_addf(&s->decoder, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str, + s->ftab.str, s->ftab.str); + str_addf(&s->freeup, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str, + s->ftab.str, s->ftab.str); + } + + str_addf(&enums, "\n};\n"); + str_add(&s->enums, enums.str, enums.len); + str_release(&enums); +} + +static void define_field(capnp_ctx_t *ctx, struct strings *s, struct field *f, + const char *extattr, const char *extattr_space) { + static struct str buf = STR_INIT; + + switch (f->f.which) { + case Field_slot: + declare_slot(s, f); + set_member(ctx, &s->set, f, "p.p", s->ftab.str, + strf(&buf, "%s%s", s->var.str, field_name(f))); + get_member(ctx, &s->get, f, "p.p", s->ftab.str, + strf(&buf, "%s%s", s->var.str, field_name(f))); + if (ctx->g_codecgen) { + encode_member(ctx, &s->encoder, f, s->ftab.str, field_name(f), + get_mapname(f->f.annotations)); + decode_member(ctx, &s->decoder, f, s->ftab.str, field_name(f), + get_mapname(f->f.annotations)); + free_member(ctx, &s->freeup, f, s->ftab.str, field_name(f), + get_mapname(f->f.annotations)); + } + break; + + case Field_group: + if (ctx->g_codecgen) { + char uniontagvar[256]; + + memset(uniontagvar, 0x0, sizeof(uniontagvar)); + if (f->group != NULL) { + int flen = capn_len(f->group->n._struct.fields); + int ulen = f->group->n._struct.discriminantCount; + + if ((ulen == flen) && (ulen > 0)) { + if (field_name(f) != NULL) { + char *uniontag = (char *)get_mapuniontag(f->f.annotations); + char buf[256]; + + if (uniontag != NULL) { + strcpy(buf, uniontag); + } else { + sprintf(buf, "%s_which", field_name(f)); + } + + str_addf(&s->encoder, "\td->%s_which = s->%s;\n", field_name(f), + buf); + str_addf(&s->decoder, "\td->%s = s->%s_which;\n", buf, + field_name(f)); + sprintf(uniontagvar, "d->%s", buf); + } + } + } + define_group(ctx, s, f->group, field_name(f), false, extattr, + extattr_space, uniontagvar); + } else { + define_group(ctx, s, f->group, field_name(f), false, extattr, + extattr_space, NULL); + } + break; + } +} + +static void define_getter_functions(capnp_ctx_t *ctx, struct node *node, + struct field *field, struct strings *s, + const char *extattr, + const char *extattr_space) { + /** + * define getter + */ + str_addf(&s->pub_get_header, "\n%s%s%s %s_get_%s(%s_ptr p);\n", extattr, + extattr_space, field->v.tname, node->name.str, field_name(field), + node->name.str); + str_addf(&s->pub_get, "\n%s%s%s %s_get_%s(%s_ptr p)\n", extattr, + extattr_space, field->v.tname, node->name.str, field_name(field), + node->name.str); + struct str getter_body = STR_INIT; + get_member(ctx, &getter_body, field, "p.p", "", field_name(field)); + str_addf(&s->pub_get, "{\n"); + str_addf(&s->pub_get, "%s%s %s;\n", s->ftab.str, field->v.tname, + field_name(field)); + str_addf(&s->pub_get, "%s%s", s->ftab.str, getter_body.str); + str_release(&getter_body); + str_addf(&s->pub_get, "%sreturn %s;\n}\n", s->ftab.str, field_name(field)); +} + +static void define_setter_functions(capnp_ctx_t *ctx, struct node *node, + struct field *field, struct strings *s, + const char *extattr, + const char *extattr_space) { + str_addf(&s->pub_set_header, "\n%s%svoid %s_set_%s(%s_ptr p, %s %s);\n", + extattr, extattr_space, node->name.str, field_name(field), + node->name.str, field->v.tname, field_name(field)); + str_addf(&s->pub_set, "\n%s%svoid %s_set_%s(%s_ptr p, %s %s)\n", extattr, + extattr_space, node->name.str, field_name(field), node->name.str, + field->v.tname, field_name(field)); + struct str setter_body = STR_INIT; + set_member(ctx, &setter_body, field, "p.p", s->ftab.str, field_name(field)); + str_addf(&s->pub_set, "{\n%s}\n", setter_body.str); + str_release(&setter_body); +} + +static void define_encode_function(capnp_ctx_t *ctx, struct node *node, + struct strings *s, const char *extattr, + const char *extattr_space) {} +static void define_group(capnp_ctx_t *ctx, struct strings *s, struct node *n, + const char *group_name, bool enclose_unions, + const char *extattr, const char *extattr_space, + const char *uniontag) { + struct field *f; + int flen = capn_len(n->n._struct.fields); + int ulen = n->n._struct.discriminantCount; + /* named union is where all group members are in the union */ + int named_union = (group_name && ulen == flen && ulen > 0); + int named_struct = (group_name && !named_union); + int empty = 1; + + for (f = n->fields; f < n->fields + flen; f++) { + decode_value(ctx, &f->v, f->f.slot.type, f->f.slot.defaultValue, NULL); + if (f->v.t.which != Type__void) + empty = 0; + } + + if (named_struct && empty) { + str_addf(&s->decl, "%s/* struct { -empty- } %s; */\n", s->dtab.str, + group_name); + return; + } + + if (named_struct) { + str_addf(&s->decl, "%scapnp_nowarn struct {\n", s->dtab.str); + str_add(&s->dtab, "\t", 1); + } + + if (group_name) { + str_addf(&s->var, "%s.", group_name); + } + + /* fields before the union members */ + for (f = n->fields; f < n->fields + flen && !in_union(f); f++) { + define_field(ctx, s, f, extattr, extattr_space); + + if (!ctx->g_fieldgetset) { + continue; + } + + if ((n->n.which == Node__struct && n->n._struct.isGroup)) { + // Don't emit in-place getters and setters for groups because they + // are defined as anonymous structs inside their parent struct. + // We could do it, but nested structs shouldn't be accessed + // in-place anyway. + continue; + } + + if (f->v.t.which == Type__void) { + continue; + } + + define_getter_functions(ctx, n, f, s, extattr, extattr_space); + define_setter_functions(ctx, n, f, s, extattr, extattr_space); + } + + if (ulen > 0) { + if (enclose_unions) { + // When we are already inside a union, so we need to enclose the union + // with its disciminant. + str_addf(&s->decl, "%scapnp_nowarn struct {\n", s->dtab.str); + str_add(&s->dtab, "\t", 1); + } + + const bool keep_union_name = named_union && !enclose_unions; + + do_union(ctx, s, n, f, keep_union_name ? group_name : NULL, extattr, + extattr_space, uniontag); + + while (f < n->fields + flen && in_union(f)) + f++; + + /* fields after the unnamed union */ + for (; f < n->fields + flen; f++) { + define_field(ctx, s, f, extattr, extattr_space); + } + + if (enclose_unions) { + str_setlen(&s->dtab, s->dtab.len - 1); + str_addf(&s->decl, "%s} %s;\n", s->dtab.str, group_name); + } + } + + if (named_struct) { + str_setlen(&s->dtab, s->dtab.len - 1); + str_addf(&s->decl, "%s} %s;\n", s->dtab.str, group_name); + } + + if (group_name) { + str_setlen(&s->var, s->var.len - strlen(group_name) - 1); + } +} + +static void define_struct(capnp_ctx_t *ctx, struct node *n, const char *extattr, + const char *extattr_space) { + static struct strings s; + int i; + + str_reset(&s.dtab); + str_reset(&s.ftab); + str_reset(&s.get); + str_reset(&s.set); + str_reset(&s.encoder); + str_reset(&s.decoder); + str_reset(&s.freeup); + str_reset(&s.enums); + str_reset(&s.decl); + str_reset(&s.var); + str_reset(&s.pub_get); + str_reset(&s.pub_set); + str_reset(&s.pub_get_header); + str_reset(&s.pub_set_header); + + str_add(&s.dtab, "\t", -1); + str_add(&s.ftab, "\t", -1); + str_add(&s.var, "s->", -1); + + if (ctx->g_codecgen) { + if (n->n._struct.discriminantCount > 0) { + const char *uniontag = get_mapuniontag(n->n.annotations); + const char *tagname = "which"; + + if (uniontag != NULL) { + tagname = uniontag; + } + + str_addf(&s.encoder, "\td->which = s->%s;\n", tagname); + str_addf(&s.decoder, "\td->%s = s->which;\n", tagname); + } + } + + define_group(ctx, &s, n, NULL, false, extattr, extattr_space, NULL); + + str_add(&(ctx->HDR), s.enums.str, s.enums.len); + + str_addf(&(ctx->HDR), "\n%sstruct %s {\n", + s.decl.len == 0 ? "capnp_nowarn " : "", n->name.str); + str_add(&(ctx->HDR), s.decl.str, s.decl.len); + str_addf(&(ctx->HDR), "};\n"); + + for (i = capn_len(n->n.annotations) - 1; i >= 0; i--) { + struct Annotation a; + struct Value v; + get_Annotation(&a, n->n.annotations, i); + read_Value(&v, a.value); + + switch (a.id) { + case ANNOTATION_TYPEDEFTO: + if (v.which != Value_text) { + fail(2, "schema breakage on $C::typedefto annotation\n"); + } + + str_addf(&(ctx->HDR), "\ntypedef struct %s %s;\n", n->name.str, + v.text.str); + break; + } + } + + str_addf(&(ctx->SRC), "\n%s%s%s_ptr new_%s(struct capn_segment *s) {\n", + extattr, extattr_space, n->name.str, n->name.str); + str_addf(&(ctx->SRC), "\t%s_ptr p;\n", n->name.str); + str_addf(&(ctx->SRC), "\tp.p = capn_new_struct(s, %d, %d);\n", + 8 * n->n._struct.dataWordCount, n->n._struct.pointerCount); + str_addf(&(ctx->SRC), "\treturn p;\n"); + str_addf(&(ctx->SRC), "}\n"); + + // adding the ability to get the structure size + str_addf(&(ctx->HDR), "\nstatic const size_t %s_word_count = %d;\n", + n->name.str, n->n._struct.dataWordCount); + str_addf(&(ctx->HDR), "\nstatic const size_t %s_pointer_count = %d;\n", + n->name.str, n->n._struct.pointerCount); + str_addf(&(ctx->HDR), "\nstatic const size_t %s_struct_bytes_count = %d;\n\n", + n->name.str, + 8 * (n->n._struct.pointerCount + n->n._struct.dataWordCount)); + + str_addf(&(ctx->SRC), + "%s%s%s_list new_%s_list(struct capn_segment *s, int len) {\n", + extattr, extattr_space, n->name.str, n->name.str); + str_addf(&(ctx->SRC), "\t%s_list p;\n", n->name.str); + str_addf(&(ctx->SRC), "\tp.p = capn_new_list(s, len, %d, %d);\n", + 8 * n->n._struct.dataWordCount, n->n._struct.pointerCount); + str_addf(&(ctx->SRC), "\treturn p;\n"); + str_addf(&(ctx->SRC), "}\n"); + + str_addf(&(ctx->SRC), + "%s%svoid read_%s(struct %s *s capnp_unused, %s_ptr p) {\n", extattr, + extattr_space, n->name.str, n->name.str, n->name.str); + str_addf(&(ctx->SRC), "\tcapn_resolve(&p.p);\n\tcapnp_use(s);\n"); + str_add(&(ctx->SRC), s.get.str, s.get.len); + str_addf(&(ctx->SRC), "}\n"); + + str_addf(&(ctx->SRC), + "%s%svoid write_%s(const struct %s *s capnp_unused, %s_ptr p) {\n", + extattr, extattr_space, n->name.str, n->name.str, n->name.str); + str_addf(&(ctx->SRC), "\tcapn_resolve(&p.p);\n\tcapnp_use(s);\n"); + str_add(&(ctx->SRC), s.set.str, s.set.len); + str_addf(&(ctx->SRC), "}\n"); + + str_addf(&(ctx->SRC), "%s%svoid get_%s(struct %s *s, %s_list l, int i) {\n", + extattr, extattr_space, n->name.str, n->name.str, n->name.str); + str_addf(&(ctx->SRC), "\t%s_ptr p;\n", n->name.str); + str_addf(&(ctx->SRC), "\tp.p = capn_getp(l.p, i, 0);\n"); + str_addf(&(ctx->SRC), "\tread_%s(s, p);\n", n->name.str); + str_addf(&(ctx->SRC), "}\n"); + + str_addf(&(ctx->SRC), + "%s%svoid set_%s(const struct %s *s, %s_list l, int i) {\n", extattr, + extattr_space, n->name.str, n->name.str, n->name.str); + str_addf(&(ctx->SRC), "\t%s_ptr p;\n", n->name.str); + str_addf(&(ctx->SRC), "\tp.p = capn_getp(l.p, i, 0);\n"); + str_addf(&(ctx->SRC), "\twrite_%s(s, p);\n", n->name.str); + str_addf(&(ctx->SRC), "}\n"); + + if (ctx->g_codecgen) { + const char *mapname = get_mapname(n->n.annotations); + char buf[256]; + + if (mapname == NULL) { + sprintf(buf, "struct %s_", n->name.str); + } else { + strcpy(buf, mapname); + } + str_addf( + &(ctx->SRC), + "\nvoid encode_%s(struct capn_segment *cs,struct %s *d, %s *s) {\n", + n->name.str, n->name.str, buf); + /* Zero the destination first: encode_member skips fields the codec has + * no mapping for (Data fields land as a bare comment), while write_X + * unconditionally reads every member. Without this, d is a caller's + * uninitialized stack local and those skipped members feed garbage + * (e.g. a wild capn_ptr.seg) straight into capn_setp -- a SIGSEGV that + * only shows up when the stack layout changes. */ + str_addf(&(ctx->SRC), "\tmemset(d, 0, sizeof(*d));\n"); + str_addf(&(ctx->SRC), "%s\n", s.encoder.str); + str_addf(&(ctx->SRC), "}\n"); + str_addf(&(ctx->SRC), "\nvoid decode_%s(%s *d, struct %s *s) {\n", + n->name.str, buf, n->name.str); + str_addf(&(ctx->SRC), "%s\n", s.decoder.str); + str_addf(&(ctx->SRC), "}\n"); + str_addf(&(ctx->SRC), "\nvoid free_%s(%s *d) {\n", n->name.str, buf); + str_addf(&(ctx->SRC), "%s\n", s.freeup.str); + str_addf(&(ctx->SRC), "}\n"); + } + + str_add(&(ctx->SRC), s.pub_get.str, s.pub_get.len); + str_add(&(ctx->SRC), s.pub_set.str, s.pub_set.len); + + str_add(&(ctx->HDR), s.pub_get_header.str, s.pub_get_header.len); + str_add(&(ctx->HDR), s.pub_set_header.str, s.pub_set_header.len); +} + +static void declare(capnp_ctx_t *ctx, struct node *file_node, + const char *format, int num) { + struct node *n; + str_addf(&(ctx->HDR), "\n"); + for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) { + if (n->n.which == Node__struct && !n->n._struct.isGroup) { + switch (num) { + case 3: + str_addf(&(ctx->HDR), format, n->name.str, n->name.str, n->name.str); + break; + case 2: + str_addf(&(ctx->HDR), format, n->name.str, n->name.str); + break; + case 1: + str_addf(&(ctx->HDR), format, n->name.str); + break; + } + } + } +} + +static void declare_ext(capnp_ctx_t *ctx, struct node *file_node, + const char *format, int num, const char *extattr, + const char *extattr_space) { + struct node *n; + str_addf(&(ctx->HDR), "\n"); + for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) { + if (n->n.which == Node__struct && !n->n._struct.isGroup) { + switch (num) { + case 3: + str_addf(&(ctx->HDR), format, extattr, extattr_space, n->name.str, + n->name.str, n->name.str); + break; + case 2: + str_addf(&(ctx->HDR), format, extattr, extattr_space, n->name.str, + n->name.str); + break; + case 1: + str_addf(&(ctx->HDR), format, extattr, extattr_space, n->name.str); + break; + } + } + } +} + +static void mk_codec_declares(capnp_ctx_t *ctx, const char *n1, + const char *n2) { + str_addf(&(ctx->HDR), + "void encode_%s(struct capn_segment *,struct %s *, %s *);\n", n1, n1, + n2); + str_addf(&(ctx->HDR), "void decode_%s(%s *, struct %s *);\n", n1, n2, n1); + str_addf(&(ctx->HDR), "void free_%s(%s *);\n", n1, n2); + str_addf( + &(ctx->HDR), + "void encode_%s_list(struct capn_segment *,%s_list *, int, %s **);\n", n1, + n1, n2); + str_addf(&(ctx->HDR), "void decode_%s_list(int *, %s ***, %s_list);\n", n1, + n2, n1); + str_addf(&(ctx->HDR), "void free_%s_list(int, %s **);\n", n1, n2); + str_addf(&(ctx->HDR), + "void encode_%s_ptr(struct capn_segment*, %s_ptr *, %s *);\n", n1, + n1, n2); + str_addf(&(ctx->HDR), "void decode_%s_ptr(%s **, %s_ptr);\n", n1, n2, n1); + str_addf(&(ctx->HDR), "void free_%s_ptr(%s **);\n", n1, n2); +} +static void declare_codec(capnp_ctx_t *ctx, struct node *file_node) { + struct node *n; + str_addf(&(ctx->HDR), "\n"); + for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) { + if (n->n.which == Node__struct && !n->n._struct.isGroup) { + const char *mapname = get_mapname(n->n.annotations); + + if (mapname == NULL) { + mk_codec_declares(ctx, n->name.str, n->name.str); + } else { + mk_codec_declares(ctx, n->name.str, mapname); + } + str_addf(&(ctx->HDR), "\n"); + } + } +} +int ctx_init(capnp_ctx_t *ctx, FILE *fp) { + struct capn_segment *current_seg = NULL; + int total_len = 0; + int i; + struct node *n; + + memset(ctx, 0x0, sizeof(*ctx)); + if (capn_init_fp(&(ctx->capn), fp, 0) < 0) { + return -1; + } + + current_seg = ctx->capn.seglist; + while (current_seg != NULL) { + total_len += current_seg->len; + current_seg = current_seg->next; + } + + ctx->g_valseg.data = calloc(1, total_len); + ctx->g_valseg.cap = total_len; + + ctx->root.p = capn_getp(capn_root(&(ctx->capn)), 0, 1); + read_CodeGeneratorRequest(&(ctx->req), ctx->root); + + for (i = 0; i < capn_len(ctx->req.nodes); i++) { + n = calloc(1, sizeof(*n)); + get_Node(&n->n, ctx->req.nodes, i); + insert_node(ctx, n); + + switch (n->n.which) { + case Node_file: + n->next = ctx->all_files; + ctx->all_files = n; + break; + + case Node__struct: + n->next = ctx->all_structs; + ctx->all_structs = n; + break; + + default: + break; + } + } + + for (n = ctx->all_structs; n != NULL; n = n->next) { + int j; + + n->fields = calloc(capn_len(n->n._struct.fields), sizeof(n->fields[0])); + for (j = 0; j < capn_len(n->n._struct.fields); j++) { + decode_field(ctx, n->fields, n->n._struct.fields, j); + } + } + return 0; +} + +int ctx_resolve_names(capnp_ctx_t *ctx) { + struct node *n; + int i, j; + + for (n = ctx->all_files; n != NULL; n = n->next) { + struct str b = STR_INIT; + const char *namespace = NULL; + + /* apply name space if present */ + for (j = capn_len(n->n.annotations) - 1; j >= 0; j--) { + struct Annotation a; + struct Value v; + get_Annotation(&a, n->n.annotations, j); + read_Value(&v, a.value); + + if (a.id == ANNOTATION_NAMESPACE) { + if (v.which != Value_text) { + fail(2, "%s: schema breakage on $C::namespace annotation\n", + n->n.displayName.str); + } + if (namespace) { + fail(2, "%s: $C::namespace annotation appears more than once.\n", + n->n.displayName.str); + } + namespace = v.text.str ? v.text.str : ""; + } + } + + if (!namespace) + namespace = ""; + + for (i = capn_len(n->n.nestedNodes) - 1; i >= 0; i--) { + struct Node_NestedNode nest; + get_Node_NestedNode(&nest, n->n.nestedNodes, i); + struct node *nn = find_node_mayfail(ctx, nest.id); + if (nn) { + resolve_names(ctx, &b, nn, nest.name, n, namespace); + } + } + + str_release(&b); + } + + return 0; +} + +int ctx_mark_used_import(capnp_ctx_t *ctx) { + struct node *n; + struct node *f; + + /* find all the used imports */ + for (n = ctx->all_structs; n != NULL; n = n->next) { + char *display_name = strdup(n->n.displayName.str); + char *file_name = strtok(display_name, ":"); + + if (!file_name) { + fail(2, "Unable to determine file name for struct node: %s\n", + n->n.displayName.str); + } + + /* find the file node corresponding to the file name */ + for (f = ctx->all_files; f != NULL; f = f->next) { + if (!strcmp(file_name, f->n.displayName.str)) + break; + } + + if (!f) { + fail(2, "Unable to find file node with file name: %s\n", file_name); + } + + /* mark this import as used */ + if (!contains_id(ctx->used_import_ids, f->n.id)) + ctx->used_import_ids = insert_id(ctx->used_import_ids, f->n.id); + + free(display_name); + } + + return 0; +} + +int ctx_gen(capnp_ctx_t *ctx) { + int i, j; + struct node *file_node; + struct node *n; + + for (i = 0; i < capn_len(ctx->req.requestedFiles); i++) { + struct CodeGeneratorRequest_RequestedFile file_req; + static struct str b = STR_INIT; + char *p; + const char *nameinfix = NULL; + FILE *srcf, *hdrf; + struct id_bst *donotinclude_ids = NULL; + struct string_list *extraheader_strings = NULL; + const char *extattr = NULL; + const char *extattr_space = ""; + + ctx->g_valc = 0; + ctx->g_valseg.len = 0; + ctx->g_val0used = 0; + ctx->g_nullused = 0; + capn_init_malloc(&(ctx->g_valcapn)); + capn_append_segment(&(ctx->g_valcapn), &(ctx->g_valseg)); + + get_CodeGeneratorRequest_RequestedFile(&file_req, ctx->req.requestedFiles, + i); + file_node = find_node(ctx, file_req.id); + if (file_node == NULL) { + fail(2, "invalid file_node specified\n"); + } + + for (j = capn_len(file_node->n.annotations) - 1; j >= 0; j--) { + struct Annotation a; + struct Value v; + get_Annotation(&a, file_node->n.annotations, j); + read_Value(&v, a.value); + + switch (a.id) { + case ANNOTATION_NAMEINFIX: /* $C::nameinfix */ + if (v.which != Value_text) { + fail(2, "schema breakage on $C::nameinfix annotation\n"); + } + if (nameinfix) { + fail(2, "$C::nameinfix annotation appears more than once\n"); + } + nameinfix = v.text.str ? v.text.str : ""; + break; + case ANNOTATION_FIELDGETSET: /* $C::fieldgetset */ + ctx->g_fieldgetset = 1; + break; + case ANNOTATION_DONOTINCLUDE: /* $C::donotinclude */ + if (v.which != Value_uint64) { + fail(2, "schema breakage on $C::donotinclude annotation\n"); + } + donotinclude_ids = insert_id(donotinclude_ids, v.uint64); + break; + case ANNOTATION_EXTRAHEADER: /* $C::extraheader("...") */ + if (v.which != Value_text) { + fail(2, "schema breakage on $C::extraheader annotation\n"); + } + extraheader_strings = + insert_file(extraheader_strings, v.text.str ? v.text.str : ""); + break; + case ANNOTATION_EXTENDEDATTRIBUTE: /* $C::extendedattribute("...") */ + if (v.which != Value_text) { + fail(2, "schema breakage on $C::extendedattribute annotation\n"); + } + if (extattr) { + fail(2, "$C::extendedattribute annotation appears more than once\n"); + } + if (v.text.str && strlen(v.text.str)) { + extattr = v.text.str; + extattr_space = " "; + } + break; + case ANNOTATION_CODECGEN: + ctx->g_codecgen = 1; + break; + } + } + if (!nameinfix) + nameinfix = ""; + if (!extattr) + extattr = ""; + + str_reset(&(ctx->HDR)); + str_reset(&(ctx->SRC)); + + str_addf(&(ctx->HDR), "#ifndef CAPN_%X%X\n", + (uint32_t)(file_node->n.id >> 32), (uint32_t)file_node->n.id); + str_addf(&(ctx->HDR), "#define CAPN_%X%X\n", + (uint32_t)(file_node->n.id >> 32), (uint32_t)file_node->n.id); + str_addf(&(ctx->HDR), "/* AUTO GENERATED - DO NOT EDIT */\n"); + str_addf(&(ctx->HDR), "#include \n"); + /* Do [extraheader] in declaration order. */ + struct string_list **current = &extraheader_strings; + struct string_list **prev = &extraheader_strings; + while (*current) { + prev = current; + current = &(*current)->next; + } + current = prev; + while (*current) { + str_addf(&(ctx->HDR), "%s\n", (*current)->string); + current = &(*current)->prev; + } + str_addf(&(ctx->HDR), "\n"); + + str_addf(&(ctx->HDR), + "#ifndef STRING_DUP\n" + "#define STRING_DUP strdup\n" + "#endif\n\n"); + + str_addf(&(ctx->HDR), "#if CAPN_VERSION != 1\n"); + str_addf( + &(ctx->HDR), + "#error \"version mismatch between capnp_c.h and generated code\"\n"); + str_addf(&(ctx->HDR), "#endif\n\n"); + str_addf(&(ctx->HDR), "#ifndef capnp_nowarn\n" + "# ifdef __GNUC__\n" + "# define capnp_nowarn __extension__\n" + "# else\n" + "# define capnp_nowarn\n" + "# endif\n" + "#endif\n\n"); + + for (j = 0; j < capn_len(file_req.imports); j++) { + struct CodeGeneratorRequest_RequestedFile_Import im; + get_CodeGeneratorRequest_RequestedFile_Import(&im, file_req.imports, j); + + // Check if this import is in the "do not include" list. + if (contains_id(donotinclude_ids, im.id)) { + continue; + } + + // Check if this import is used at all. + if (!contains_id(ctx->used_import_ids, im.id)) { + continue; + } + + // Ignore leading slashes when generating C file #include's. + // This signifies an absolute import in a library directory. + const char *base_path = + im.name.str[0] == '/' ? &im.name.str[1] : im.name.str; + str_addf(&(ctx->HDR), "#include \"%s%s.h\"\n", base_path, nameinfix); + } + + free_id_bst(ctx->used_import_ids); + free_id_bst(donotinclude_ids); + free_string_list(extraheader_strings); + + str_addf(&(ctx->HDR), "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); + + declare(ctx, file_node, "struct %s;\n", 1); + declare(ctx, file_node, "typedef struct {capn_ptr p;} %s_ptr;\n", 1); + declare(ctx, file_node, "typedef struct {capn_ptr p;} %s_list;\n", 1); + + for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) { + if (n->n.which == Node__enum) { + define_enum(ctx, n); + } + } + + for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) { + if (n->n.which == Node__const) { + define_const(ctx, n); + } + } + + for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) { + if (n->n.which == Node__struct && !n->n._struct.isGroup) { + define_struct(ctx, n, extattr, extattr_space); + mk_struct_list_encoder(ctx, n); + mk_struct_ptr_encoder(ctx, n); + mk_struct_list_decoder(ctx, n); + mk_struct_ptr_decoder(ctx, n); + mk_struct_list_free(ctx, n); + mk_struct_ptr_free(ctx, n); + } + } + + declare_ext(ctx, file_node, "%s%s%s_ptr new_%s(struct capn_segment*);\n", 2, + extattr, extattr_space); + declare_ext(ctx, file_node, + "%s%s%s_list new_%s_list(struct capn_segment*, int len);\n", 2, + extattr, extattr_space); + declare_ext(ctx, file_node, "%s%svoid read_%s(struct %s*, %s_ptr);\n", 3, + extattr, extattr_space); + declare_ext(ctx, file_node, + "%s%svoid write_%s(const struct %s*, %s_ptr);\n", 3, extattr, + extattr_space); + declare_ext(ctx, file_node, + "%s%svoid get_%s(struct %s*, %s_list, int i);\n", 3, extattr, + extattr_space); + declare_ext(ctx, file_node, + "%s%svoid set_%s(const struct %s*, %s_list, int i);\n", 3, + extattr, extattr_space); + + if (ctx->g_codecgen) { + declare_codec(ctx, file_node); + } + + str_addf(&(ctx->HDR), "\n#ifdef __cplusplus\n}\n#endif\n#endif\n"); + + /* write out the header */ + + hdrf = + fopen(strf(&b, "%s%s.h", file_node->n.displayName.str, nameinfix), "w"); + if (!hdrf) { + fail(2, "failed to open %s: %s\n", b.str, strerror(errno)); + } + fwrite((ctx->HDR).str, 1, (ctx->HDR).len, hdrf); + fclose(hdrf); + + /* write out the source */ + + srcf = + fopen(strf(&b, "%s%s.c", file_node->n.displayName.str, nameinfix), "w"); + if (!srcf) { + fail(2, "failed to open %s: %s\n", b.str, strerror(errno)); + } + p = strrchr(file_node->n.displayName.str, '/'); + fprintf(srcf, "#include \"%s%s.h\"\n", + p ? p + 1 : file_node->n.displayName.str, nameinfix); + fprintf(srcf, "/* AUTO GENERATED - DO NOT EDIT */\n"); + fprintf(srcf, "#ifdef __GNUC__\n" + "# define capnp_unused __attribute__((unused))\n" + "# define capnp_use(x) (void) (x);\n" + "#else\n" + "# define capnp_unused\n" + "# define capnp_use(x)\n" + "#endif\n\n"); + + fprintf(srcf, "#include \n" + "#include \n"); + if (ctx->g_val0used) + fprintf(srcf, "static const capn_text capn_val0 = {0,\"\",0};\n"); + if (ctx->g_nullused) + fprintf(srcf, "static const capn_ptr capn_null = {CAPN_NULL};\n"); + + if (ctx->g_valseg.len > 8) { + size_t k; + fprintf(srcf, "static const uint8_t capn_buf[%zu] = {", + ctx->g_valseg.len - 8); + for (k = 8; k < ctx->g_valseg.len; k++) { + if (k > 8) + fprintf(srcf, ","); + if ((k % 8) == 0) + fprintf(srcf, "\n\t"); + fprintf(srcf, "%u", ((uint8_t *)ctx->g_valseg.data)[k]); + } + fprintf(srcf, "\n};\n"); + + fprintf(srcf, + "static const struct capn_segment capn_seg = " + "{{0},0,0,0,(char*)&capn_buf[0],%zu,%zu,0};\n", + ctx->g_valseg.len - 8, ctx->g_valseg.len - 8); + } + + fwrite((ctx->SRC).str, 1, (ctx->SRC).len, srcf); + fclose(srcf); + + capn_free(&(ctx->g_valcapn)); + } + + return 0; +} +int main(int argc, char *argv[]) { + capnp_ctx_t ctx; + FILE *fp = NULL; + + if (argc > 2) { + fail(2, "too many arguments\n"); + } else if (argc == 2) { + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + perror("fopen"); + return -1; + } + } else { + fp = stdin; + } + +#if defined(_WIN32) + if (_setmode(_fileno(fp), _O_BINARY) == -1) { + fail(-1, "fail to set stdin to binary mode\n"); + } +#endif + + ctx_init(&ctx, fp); + + ctx_resolve_names(&ctx); + + ctx_mark_used_import(&ctx); + + ctx_gen(&ctx); + + return 0; +} diff --git a/src/subprojects/c-capnproto/compiler/schema-test.cpp b/src/subprojects/c-capnproto/compiler/schema-test.cpp new file mode 100644 index 00000000..ef4d1c3c --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/schema-test.cpp @@ -0,0 +1,203 @@ +/* schema-test.cpp + * + * Copyright (C) 2013 James McKaskill + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include "schema.capnp.h" +#include + +static const uint8_t simple_schema[] = { + 0x00, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x6d, 0x05, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x73, 0x4d, 0xd2, 0x75, 0x6b, 0xff, 0xe1, 0xbe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x3d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x09, 0xb7, 0x71, 0x68, 0xc7, 0x34, 0xc8, 0xff, 0x73, 0x4d, 0xd2, 0x75, 0x6b, 0xff, 0xe1, 0xbe, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, + 0x41, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, + 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x70, 0x6e, 0x70, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x09, 0xb7, 0x71, 0x68, 0xc7, 0x34, 0xc8, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x46, 0x6f, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, + 0x2f, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x61, 0x70, 0x6e, 0x70, 0x3a, 0x46, 0x6f, + 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x62, 0x6f, 0x64, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x67, 0x02, 0x00, 0x00, + 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x29, 0x01, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x2c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x01, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x4d, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x4c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x69, 0x01, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x6d, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x6c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x89, 0x01, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x8c, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa9, 0x01, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xad, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xac, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc9, 0x01, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xcc, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe9, 0x01, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0xed, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xec, 0x01, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x02, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x29, 0x02, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x2d, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x2c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x02, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x4d, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x4c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x69, 0x02, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x6c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x89, 0x02, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x8d, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x8c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa9, 0x02, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xad, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xac, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc9, 0x02, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xcd, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xcc, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe9, 0x02, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0xed, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0xec, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x03, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x29, 0x03, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x2c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x12, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x03, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x4d, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x4c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x13, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x69, 0x03, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x6d, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x6c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x74, 0x38, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x6f, 0x69, 0x64, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x32, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x36, 0x34, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x4d, 0xd2, 0x75, 0x6b, 0xff, 0xe1, 0xbe, +}; + +TEST(Schema, ReadSimple) { + struct capn ctx; + ASSERT_EQ(0, capn_init_mem(&ctx, simple_schema, sizeof(simple_schema), 0)); + + CodeGeneratorRequest_ptr root = {capn_getp(capn_root(&ctx), 0, 1)}; + EXPECT_EQ(CAPN_STRUCT, root.p.type); + + struct CodeGeneratorRequest req; + read_CodeGeneratorRequest(&req, root); + for (int i = 0; i < req.nodes.p.len; i++) { + } +} + diff --git a/src/subprojects/c-capnproto/compiler/schema.capnp b/src/subprojects/c-capnproto/compiler/schema.capnp new file mode 100644 index 00000000..169f7759 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/schema.capnp @@ -0,0 +1,477 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +using C = import "c.capnp"; +using Cxx = import "c++.capnp"; + +@0xa93fc509624c72d9; +$Cxx.namespace("capnp::schema"); + +$C.fieldgetset; + +using Id = UInt64; +# The globally-unique ID of a file, type, or annotation. + +struct Node { + id @0 :Id; + + displayName @1 :Text; + # Name to present to humans to identify this Node. You should not attempt to parse this. Its + # format could change. It is not guaranteed to be unique. + # + # (On Zooko's triangle, this is the node's nickname.) + + displayNamePrefixLength @2 :UInt32; + # If you want a shorter version of `displayName` (just naming this node, without its surrounding + # scope), chop off this many characters from the beginning of `displayName`. + + scopeId @3 :Id; + # ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back + # at this node, but robust code should avoid relying on this (and, in fact, group nodes are not + # listed in the outer struct's nestedNodes, since they are listed in the fields). `scopeId` is + # zero if the node has no parent, which is normally only the case with files, but should be + # allowed for any kind of node (in order to make runtime type generation easier). + + parameters @32 :List(Parameter); + # If this node is parameterized (generic), the list of parameters. Empty for non-generic types. + + isGeneric @33 :Bool; + # True if this node is generic, meaning that it or one of its parent scopes has a non-empty + # `parameters`. + + struct Parameter { + # Information about one of the node's parameters. + + name @0 :Text; + } + + nestedNodes @4 :List(NestedNode); + # List of nodes nested within this node, along with the names under which they were declared. + + struct NestedNode { + name @0 :Text; + # Unqualified symbol name. Unlike Node.displayName, this *can* be used programmatically. + # + # (On Zooko's triangle, this is the node's petname according to its parent scope.) + + id @1 :Id; + # ID of the nested node. Typically, the target node's scopeId points back to this node, but + # robust code should avoid relying on this. + } + + annotations @5 :List(Annotation); + # Annotations applied to this node. + + union { + # Info specific to each kind of node. + + file @6 :Void; + + struct :group { + dataWordCount @7 :UInt16; + # Size of the data section, in words. + + pointerCount @8 :UInt16; + # Size of the pointer section, in pointers (which are one word each). + + preferredListEncoding @9 :ElementSize; + # The preferred element size to use when encoding a list of this struct. If this is anything + # other than `inlineComposite` then the struct is one word or less in size and is a candidate + # for list packing optimization. + + isGroup @10 :Bool; + # If true, then this "struct" node is actually not an independent node, but merely represents + # some named union or group within a particular parent struct. This node's scopeId refers + # to the parent struct, which may itself be a union/group in yet another struct. + # + # All group nodes share the same dataWordCount and pointerCount as the top-level + # struct, and their fields live in the same ordinal and offset spaces as all other fields in + # the struct. + # + # Note that a named union is considered a special kind of group -- in fact, a named union + # is exactly equivalent to a group that contains nothing but an unnamed union. + + discriminantCount @11 :UInt16; + # Number of fields in this struct which are members of an anonymous union, and thus may + # overlap. If this is non-zero, then a 16-bit discriminant is present indicating which + # of the overlapping fields is active. This can never be 1 -- if it is non-zero, it must be + # two or more. + # + # Note that the fields of an unnamed union are considered fields of the scope containing the + # union -- an unnamed union is not its own group. So, a top-level struct may contain a + # non-zero discriminant count. Named unions, on the other hand, are equivalent to groups + # containing unnamed unions. So, a named union has its own independent schema node, with + # `isGroup` = true. + + discriminantOffset @12 :UInt32; + # If `discriminantCount` is non-zero, this is the offset of the union discriminant, in + # multiples of 16 bits. + + fields @13 :List(Field); + # Fields defined within this scope (either the struct's top-level fields, or the fields of + # a particular group; see `isGroup`). + # + # The fields are sorted by ordinal number, but note that because groups share the same + # ordinal space, the field's index in this list is not necessarily exactly its ordinal. + # On the other hand, the field's position in this list does remain the same even as the + # protocol evolves, since it is not possible to insert or remove an earlier ordinal. + # Therefore, for most use cases, if you want to identify a field by number, it may make the + # most sense to use the field's index in this list rather than its ordinal. + } + + enum :group { + enumerants@14 :List(Enumerant); + # Enumerants ordered by numeric value (ordinal). + } + + interface :group { + methods @15 :List(Method); + # Methods ordered by ordinal. + + superclasses @31 :List(Superclass); + # Superclasses of this interface. + } + + const :group { + type @16 :Type; + value @17 :Value; + } + + annotation :group { + type @18 :Type; + + targetsFile @19 :Bool; + targetsConst @20 :Bool; + targetsEnum @21 :Bool; + targetsEnumerant @22 :Bool; + targetsStruct @23 :Bool; + targetsField @24 :Bool; + targetsUnion @25 :Bool; + targetsGroup @26 :Bool; + targetsInterface @27 :Bool; + targetsMethod @28 :Bool; + targetsParam @29 :Bool; + targetsAnnotation @30 :Bool; + } + } +} + +struct Field { + # Schema for a field of a struct. + + name @0 :Text; + + codeOrder @1 :UInt16; + # Indicates where this member appeared in the code, relative to other members. + # Code ordering may have semantic relevance -- programmers tend to place related fields + # together. So, using code ordering makes sense in human-readable formats where ordering is + # otherwise irrelevant, like JSON. The values of codeOrder are tightly-packed, so the maximum + # value is count(members) - 1. Fields that are members of a union are only ordered relative to + # the other members of that union, so the maximum value there is count(union.members). + + annotations @2 :List(Annotation); + + const noDiscriminant :UInt16 = 0xffff; + + discriminantValue @3 :UInt16 = Field.noDiscriminant; + # If the field is in a union, this is the value which the union's discriminant should take when + # the field is active. If the field is not in a union, this is 0xffff. + + union { + slot :group { + # A regular, non-group, non-fixed-list field. + + offset @4 :UInt32; + # Offset, in units of the field's size, from the beginning of the section in which the field + # resides. E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the + # beginning of the data section. + + type @5 :Type; + defaultValue @6 :Value; + + hadExplicitDefault @10 :Bool; + # Whether the default value was specified explicitly. Non-explicit default values are always + # zero or empty values. Usually, whether the default value was explicit shouldn't matter. + # The main use case for this flag is for structs representing method parameters: + # explicitly-defaulted parameters may be allowed to be omitted when calling the method. + } + + group :group { + # A group. + + typeId @7 :Id; + # The ID of the group's node. + } + } + + ordinal :union { + implicit @8 :Void; + explicit @9 :UInt16; + # The original ordinal number given to the field. You probably should NOT use this; if you need + # a numeric identifier for a field, use its position within the field array for its scope. + # The ordinal is given here mainly just so that the original schema text can be reproduced given + # the compiled version -- i.e. so that `capnp compile -ocapnp` can do its job. + } +} + +struct Enumerant { + # Schema for member of an enum. + + name @0 :Text; + + codeOrder @1 :UInt16; + # Specifies order in which the enumerants were declared in the code. + # Like Struct.Field.codeOrder. + + annotations @2 :List(Annotation); +} + +struct Superclass { + id @0 :Id; + brand @1 :Brand; +} + +struct Method { + # Schema for method of an interface. + + name @0 :Text; + + codeOrder @1 :UInt16; + # Specifies order in which the methods were declared in the code. + # Like Struct.Field.codeOrder. + + implicitParameters @7 :List(Node.Parameter); + # The parameters listed in [] (typically, type / generic parameters), whose bindings are intended + # to be inferred rather than specified explicitly, although not all languages support this. + + paramStructType @2 :Id; + # ID of the parameter struct type. If a named parameter list was specified in the method + # declaration (rather than a single struct parameter type) then a corresponding struct type is + # auto-generated. Such an auto-generated type will not be listed in the interface's + # `nestedNodes` and its `scopeId` will be zero -- it is completely detached from the namespace. + # (Awkwardly, it does of course inherit generic parameters from the method's scope, which makes + # this a situation where you can't just climb the scope chain to find where a particular + # generic parameter was introduced. Making the `scopeId` zero was a mistake.) + + paramBrand @5 :Brand; + # Brand of param struct type. + + resultStructType @3 :Id; + # ID of the return struct type; similar to `paramStructType`. + + resultBrand @6 :Brand; + # Brand of result struct type. + + annotations @4 :List(Annotation); +} + +struct Type { + # Represents a type expression. + + union { + # The ordinals intentionally match those of Value. + + void @0 :Void; + bool @1 :Void; + int8 @2 :Void; + int16 @3 :Void; + int32 @4 :Void; + int64 @5 :Void; + uint8 @6 :Void; + uint16 @7 :Void; + uint32 @8 :Void; + uint64 @9 :Void; + float32 @10 :Void; + float64 @11 :Void; + text @12 :Void; + data @13 :Void; + + list :group { + elementType @14 :Type; + } + + enum :group { + typeId @15 :Id; + brand @21 :Brand; + } + struct :group { + typeId @16 :Id; + brand @22 :Brand; + } + interface :group { + typeId @17 :Id; + brand @23 :Brand; + } + + anyPointer :union { + unconstrained @18 :Void; + # A regular AnyPointer. + + parameter :group { + # This is actually a reference to a type parameter defined within this scope. + + scopeId @19 :Id; + # ID of the generic type whose parameter we're referencing. This should be a parent of the + # current scope. + + parameterIndex @20 :UInt16; + # Index of the parameter within the generic type's parameter list. + } + + implicitMethodParameter :group { + # This is actually a reference to an implicit (generic) parameter of a method. The only + # legal context for this type to appear is inside Method.paramBrand or Method.resultBrand. + + parameterIndex @24 :UInt16; + } + } + } +} + +struct Brand { + # Specifies bindings for parameters of generics. Since these bindings turn a generic into a + # non-generic, we call it the "brand". + + scopes @0 :List(Scope); + # For each of the target type and each of its parent scopes, a parameterization may be included + # in this list. If no parameterization is included for a particular relevant scope, then either + # that scope has no parameters or all parameters should be considered to be `AnyPointer`. + + struct Scope { + scopeId @0 :Id; + # ID of the scope to which these params apply. + + union { + bind @1 :List(Binding); + # List of parameter bindings. + + inherit @2 :Void; + # The place where this Brand appears is actually within this scope or a sub-scope, + # and the bindings for this scope should be inherited from the reference point. + } + } + + struct Binding { + union { + unbound @0 :Void; + type @1 :Type; + + # TODO(someday): Allow non-type parameters? Unsure if useful. + } + } +} + +struct Value { + # Represents a value, e.g. a field default value, constant value, or annotation value. + + union { + # The ordinals intentionally match those of Type. + + void @0 :Void; + bool @1 :Bool; + int8 @2 :Int8; + int16 @3 :Int16; + int32 @4 :Int32; + int64 @5 :Int64; + uint8 @6 :UInt8; + uint16 @7 :UInt16; + uint32 @8 :UInt32; + uint64 @9 :UInt64; + float32 @10 :Float32; + float64 @11 :Float64; + text @12 :Text; + data @13 :Data; + + list @14 :AnyPointer; + + enum @15 :UInt16; + struct @16 :AnyPointer; + + interface @17 :Void; + # The only interface value that can be represented statically is "null", whose methods always + # throw exceptions. + + anyPointer @18 :AnyPointer; + } +} + +struct Annotation { + # Describes an annotation applied to a declaration. Note AnnotationNode describes the + # annotation's declaration, while this describes a use of the annotation. + + id @0 :Id; + # ID of the annotation node. + + brand @2 :Brand; + # Brand of the annotation. + # + # Note that the annotation itself is not allowed to be parameterized, but its scope might be. + + value @1 :Value; +} + +enum ElementSize { + # Possible element sizes for encoded lists. These correspond exactly to the possible values of + # the 3-bit element size component of a list pointer. + + empty @0; # aka "void", but that's a keyword. + bit @1; + byte @2; + twoBytes @3; + fourBytes @4; + eightBytes @5; + pointer @6; + inlineComposite @7; +} + +struct CodeGeneratorRequest { + nodes @0 :List(Node); + # All nodes parsed by the compiler, including for the files on the command line and their + # imports. + + requestedFiles @1 :List(RequestedFile); + # Files which were listed on the command line. + + struct RequestedFile { + id @0 :Id; + # ID of the file. + + filename @1 :Text; + # Name of the file as it appeared on the command-line (minus the src-prefix). You may use + # this to decide where to write the output. + + imports @2 :List(Import); + # List of all imported paths seen in this file. + + struct Import { + id @0 :Id; + # ID of the imported file. + + name @1 :Text; + # Name which *this* file used to refer to the foreign file. This may be a relative name. + # This information is provided because it might be useful for code generation, e.g. to + # generate #include directives in C++. We don't put this in Node.file because this + # information is only meaningful at compile time anyway. + # + # (On Zooko's triangle, this is the import's petname according to the importing file.) + } + } +} diff --git a/src/subprojects/c-capnproto/compiler/schema.capnp.c b/src/subprojects/c-capnproto/compiler/schema.capnp.c new file mode 100644 index 00000000..8bcbcc51 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/schema.capnp.c @@ -0,0 +1,1336 @@ +#include "schema.capnp.h" +/* AUTO GENERATED - DO NOT EDIT */ +#ifdef __GNUC__ +# define capnp_unused __attribute__((unused)) +# define capnp_use(x) (void) (x); +#else +# define capnp_unused +# define capnp_use(x) +#endif + +static const capn_text capn_val0 = {0,"",0}; +uint16_t Field_noDiscriminant = 65535; + +Node_ptr new_Node(struct capn_segment *s) { + Node_ptr p; + p.p = capn_new_struct(s, 40, 6); + return p; +} +Node_list new_Node_list(struct capn_segment *s, int len) { + Node_list p; + p.p = capn_new_list(s, len, 40, 6); + return p; +} +void read_Node(struct Node *s capnp_unused, Node_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->id = capn_read64(p.p, 0); + s->displayName = capn_get_text(p.p, 0, capn_val0); + s->displayNamePrefixLength = capn_read32(p.p, 8); + s->scopeId = capn_read64(p.p, 16); + s->parameters.p = capn_getp(p.p, 5, 0); + s->isGeneric = (capn_read8(p.p, 36) & 1) != 0; + s->nestedNodes.p = capn_getp(p.p, 1, 0); + s->annotations.p = capn_getp(p.p, 2, 0); + s->which = (enum Node_which)(int) capn_read16(p.p, 12); + switch (s->which) { + case Node__struct: + s->_struct.dataWordCount = capn_read16(p.p, 14); + s->_struct.pointerCount = capn_read16(p.p, 24); + s->_struct.preferredListEncoding = (enum ElementSize)(int) capn_read16(p.p, 26); + s->_struct.isGroup = (capn_read8(p.p, 28) & 1) != 0; + s->_struct.discriminantCount = capn_read16(p.p, 30); + s->_struct.discriminantOffset = capn_read32(p.p, 32); + s->_struct.fields.p = capn_getp(p.p, 3, 0); + break; + case Node__enum: + s->_enum.enumerants.p = capn_getp(p.p, 3, 0); + break; + case Node__interface: + s->_interface.methods.p = capn_getp(p.p, 3, 0); + s->_interface.superclasses.p = capn_getp(p.p, 4, 0); + break; + case Node__const: + s->_const.type.p = capn_getp(p.p, 3, 0); + s->_const.value.p = capn_getp(p.p, 4, 0); + break; + case Node_annotation: + s->annotation.type.p = capn_getp(p.p, 3, 0); + s->annotation.targetsFile = (capn_read8(p.p, 14) & 1) != 0; + s->annotation.targetsConst = (capn_read8(p.p, 14) & 2) != 0; + s->annotation.targetsEnum = (capn_read8(p.p, 14) & 4) != 0; + s->annotation.targetsEnumerant = (capn_read8(p.p, 14) & 8) != 0; + s->annotation.targetsStruct = (capn_read8(p.p, 14) & 16) != 0; + s->annotation.targetsField = (capn_read8(p.p, 14) & 32) != 0; + s->annotation.targetsUnion = (capn_read8(p.p, 14) & 64) != 0; + s->annotation.targetsGroup = (capn_read8(p.p, 14) & 128) != 0; + s->annotation.targetsInterface = (capn_read8(p.p, 15) & 1) != 0; + s->annotation.targetsMethod = (capn_read8(p.p, 15) & 2) != 0; + s->annotation.targetsParam = (capn_read8(p.p, 15) & 4) != 0; + s->annotation.targetsAnnotation = (capn_read8(p.p, 15) & 8) != 0; + break; + default: + break; + } +} +void write_Node(const struct Node *s capnp_unused, Node_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, s->id); + capn_set_text(p.p, 0, s->displayName); + capn_write32(p.p, 8, s->displayNamePrefixLength); + capn_write64(p.p, 16, s->scopeId); + capn_setp(p.p, 5, s->parameters.p); + capn_write1(p.p, 288, s->isGeneric != 0); + capn_setp(p.p, 1, s->nestedNodes.p); + capn_setp(p.p, 2, s->annotations.p); + capn_write16(p.p, 12, s->which); + switch (s->which) { + case Node__struct: + capn_write16(p.p, 14, s->_struct.dataWordCount); + capn_write16(p.p, 24, s->_struct.pointerCount); + capn_write16(p.p, 26, (uint16_t) (s->_struct.preferredListEncoding)); + capn_write1(p.p, 224, s->_struct.isGroup != 0); + capn_write16(p.p, 30, s->_struct.discriminantCount); + capn_write32(p.p, 32, s->_struct.discriminantOffset); + capn_setp(p.p, 3, s->_struct.fields.p); + break; + case Node__enum: + capn_setp(p.p, 3, s->_enum.enumerants.p); + break; + case Node__interface: + capn_setp(p.p, 3, s->_interface.methods.p); + capn_setp(p.p, 4, s->_interface.superclasses.p); + break; + case Node__const: + capn_setp(p.p, 3, s->_const.type.p); + capn_setp(p.p, 4, s->_const.value.p); + break; + case Node_annotation: + capn_setp(p.p, 3, s->annotation.type.p); + capn_write1(p.p, 112, s->annotation.targetsFile != 0); + capn_write1(p.p, 113, s->annotation.targetsConst != 0); + capn_write1(p.p, 114, s->annotation.targetsEnum != 0); + capn_write1(p.p, 115, s->annotation.targetsEnumerant != 0); + capn_write1(p.p, 116, s->annotation.targetsStruct != 0); + capn_write1(p.p, 117, s->annotation.targetsField != 0); + capn_write1(p.p, 118, s->annotation.targetsUnion != 0); + capn_write1(p.p, 119, s->annotation.targetsGroup != 0); + capn_write1(p.p, 120, s->annotation.targetsInterface != 0); + capn_write1(p.p, 121, s->annotation.targetsMethod != 0); + capn_write1(p.p, 122, s->annotation.targetsParam != 0); + capn_write1(p.p, 123, s->annotation.targetsAnnotation != 0); + break; + default: + break; + } +} +void get_Node(struct Node *s, Node_list l, int i) { + Node_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Node(s, p); +} +void set_Node(const struct Node *s, Node_list l, int i) { + Node_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Node(s, p); +} + +uint64_t Node_get_id(Node_ptr p) +{ + uint64_t id; + id = capn_read64(p.p, 0); + return id; +} + +capn_text Node_get_displayName(Node_ptr p) +{ + capn_text displayName; + displayName = capn_get_text(p.p, 0, capn_val0); + return displayName; +} + +uint32_t Node_get_displayNamePrefixLength(Node_ptr p) +{ + uint32_t displayNamePrefixLength; + displayNamePrefixLength = capn_read32(p.p, 8); + return displayNamePrefixLength; +} + +uint64_t Node_get_scopeId(Node_ptr p) +{ + uint64_t scopeId; + scopeId = capn_read64(p.p, 16); + return scopeId; +} + +Node_Parameter_list Node_get_parameters(Node_ptr p) +{ + Node_Parameter_list parameters; + parameters.p = capn_getp(p.p, 5, 0); + return parameters; +} + +unsigned Node_get_isGeneric(Node_ptr p) +{ + unsigned isGeneric; + isGeneric = (capn_read8(p.p, 36) & 1) != 0; + return isGeneric; +} + +Node_NestedNode_list Node_get_nestedNodes(Node_ptr p) +{ + Node_NestedNode_list nestedNodes; + nestedNodes.p = capn_getp(p.p, 1, 0); + return nestedNodes; +} + +Annotation_list Node_get_annotations(Node_ptr p) +{ + Annotation_list annotations; + annotations.p = capn_getp(p.p, 2, 0); + return annotations; +} + +void Node_set_id(Node_ptr p, uint64_t id) +{ + capn_write64(p.p, 0, id); +} + +void Node_set_displayName(Node_ptr p, capn_text displayName) +{ + capn_set_text(p.p, 0, displayName); +} + +void Node_set_displayNamePrefixLength(Node_ptr p, uint32_t displayNamePrefixLength) +{ + capn_write32(p.p, 8, displayNamePrefixLength); +} + +void Node_set_scopeId(Node_ptr p, uint64_t scopeId) +{ + capn_write64(p.p, 16, scopeId); +} + +void Node_set_parameters(Node_ptr p, Node_Parameter_list parameters) +{ + capn_setp(p.p, 5, parameters.p); +} + +void Node_set_isGeneric(Node_ptr p, unsigned isGeneric) +{ + capn_write1(p.p, 288, isGeneric != 0); +} + +void Node_set_nestedNodes(Node_ptr p, Node_NestedNode_list nestedNodes) +{ + capn_setp(p.p, 1, nestedNodes.p); +} + +void Node_set_annotations(Node_ptr p, Annotation_list annotations) +{ + capn_setp(p.p, 2, annotations.p); +} + +Node_Parameter_ptr new_Node_Parameter(struct capn_segment *s) { + Node_Parameter_ptr p; + p.p = capn_new_struct(s, 0, 1); + return p; +} +Node_Parameter_list new_Node_Parameter_list(struct capn_segment *s, int len) { + Node_Parameter_list p; + p.p = capn_new_list(s, len, 0, 1); + return p; +} +void read_Node_Parameter(struct Node_Parameter *s capnp_unused, Node_Parameter_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->name = capn_get_text(p.p, 0, capn_val0); +} +void write_Node_Parameter(const struct Node_Parameter *s capnp_unused, Node_Parameter_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->name); +} +void get_Node_Parameter(struct Node_Parameter *s, Node_Parameter_list l, int i) { + Node_Parameter_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Node_Parameter(s, p); +} +void set_Node_Parameter(const struct Node_Parameter *s, Node_Parameter_list l, int i) { + Node_Parameter_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Node_Parameter(s, p); +} + +capn_text Node_Parameter_get_name(Node_Parameter_ptr p) +{ + capn_text name; + name = capn_get_text(p.p, 0, capn_val0); + return name; +} + +void Node_Parameter_set_name(Node_Parameter_ptr p, capn_text name) +{ + capn_set_text(p.p, 0, name); +} + +Node_NestedNode_ptr new_Node_NestedNode(struct capn_segment *s) { + Node_NestedNode_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +Node_NestedNode_list new_Node_NestedNode_list(struct capn_segment *s, int len) { + Node_NestedNode_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_Node_NestedNode(struct Node_NestedNode *s capnp_unused, Node_NestedNode_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->name = capn_get_text(p.p, 0, capn_val0); + s->id = capn_read64(p.p, 0); +} +void write_Node_NestedNode(const struct Node_NestedNode *s capnp_unused, Node_NestedNode_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->name); + capn_write64(p.p, 0, s->id); +} +void get_Node_NestedNode(struct Node_NestedNode *s, Node_NestedNode_list l, int i) { + Node_NestedNode_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Node_NestedNode(s, p); +} +void set_Node_NestedNode(const struct Node_NestedNode *s, Node_NestedNode_list l, int i) { + Node_NestedNode_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Node_NestedNode(s, p); +} + +capn_text Node_NestedNode_get_name(Node_NestedNode_ptr p) +{ + capn_text name; + name = capn_get_text(p.p, 0, capn_val0); + return name; +} + +uint64_t Node_NestedNode_get_id(Node_NestedNode_ptr p) +{ + uint64_t id; + id = capn_read64(p.p, 0); + return id; +} + +void Node_NestedNode_set_name(Node_NestedNode_ptr p, capn_text name) +{ + capn_set_text(p.p, 0, name); +} + +void Node_NestedNode_set_id(Node_NestedNode_ptr p, uint64_t id) +{ + capn_write64(p.p, 0, id); +} + +Field_ptr new_Field(struct capn_segment *s) { + Field_ptr p; + p.p = capn_new_struct(s, 24, 4); + return p; +} +Field_list new_Field_list(struct capn_segment *s, int len) { + Field_list p; + p.p = capn_new_list(s, len, 24, 4); + return p; +} +void read_Field(struct Field *s capnp_unused, Field_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->name = capn_get_text(p.p, 0, capn_val0); + s->codeOrder = capn_read16(p.p, 0); + s->annotations.p = capn_getp(p.p, 1, 0); + s->discriminantValue = capn_read16(p.p, 2) ^ 65535u; + s->which = (enum Field_which)(int) capn_read16(p.p, 8); + switch (s->which) { + case Field_slot: + s->slot.offset = capn_read32(p.p, 4); + s->slot.type.p = capn_getp(p.p, 2, 0); + s->slot.defaultValue.p = capn_getp(p.p, 3, 0); + s->slot.hadExplicitDefault = (capn_read8(p.p, 16) & 1) != 0; + break; + case Field_group: + s->group.typeId = capn_read64(p.p, 16); + break; + default: + break; + } + s->ordinal_which = (enum Field_ordinal_which)(int) capn_read16(p.p, 10); + switch (s->ordinal_which) { + case Field_ordinal__explicit: + s->ordinal._explicit = capn_read16(p.p, 12); + break; + default: + break; + } +} +void write_Field(const struct Field *s capnp_unused, Field_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->name); + capn_write16(p.p, 0, s->codeOrder); + capn_setp(p.p, 1, s->annotations.p); + capn_write16(p.p, 2, s->discriminantValue ^ 65535u); + capn_write16(p.p, 8, s->which); + switch (s->which) { + case Field_slot: + capn_write32(p.p, 4, s->slot.offset); + capn_setp(p.p, 2, s->slot.type.p); + capn_setp(p.p, 3, s->slot.defaultValue.p); + capn_write1(p.p, 128, s->slot.hadExplicitDefault != 0); + break; + case Field_group: + capn_write64(p.p, 16, s->group.typeId); + break; + default: + break; + } + capn_write16(p.p, 10, s->ordinal_which); + switch (s->ordinal_which) { + case Field_ordinal__explicit: + capn_write16(p.p, 12, s->ordinal._explicit); + break; + default: + break; + } +} +void get_Field(struct Field *s, Field_list l, int i) { + Field_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Field(s, p); +} +void set_Field(const struct Field *s, Field_list l, int i) { + Field_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Field(s, p); +} + +capn_text Field_get_name(Field_ptr p) +{ + capn_text name; + name = capn_get_text(p.p, 0, capn_val0); + return name; +} + +uint16_t Field_get_codeOrder(Field_ptr p) +{ + uint16_t codeOrder; + codeOrder = capn_read16(p.p, 0); + return codeOrder; +} + +Annotation_list Field_get_annotations(Field_ptr p) +{ + Annotation_list annotations; + annotations.p = capn_getp(p.p, 1, 0); + return annotations; +} + +uint16_t Field_get_discriminantValue(Field_ptr p) +{ + uint16_t discriminantValue; + discriminantValue = capn_read16(p.p, 2) ^ 65535u; + return discriminantValue; +} + +void Field_set_name(Field_ptr p, capn_text name) +{ + capn_set_text(p.p, 0, name); +} + +void Field_set_codeOrder(Field_ptr p, uint16_t codeOrder) +{ + capn_write16(p.p, 0, codeOrder); +} + +void Field_set_annotations(Field_ptr p, Annotation_list annotations) +{ + capn_setp(p.p, 1, annotations.p); +} + +void Field_set_discriminantValue(Field_ptr p, uint16_t discriminantValue) +{ + capn_write16(p.p, 2, discriminantValue ^ 65535u); +} + +Enumerant_ptr new_Enumerant(struct capn_segment *s) { + Enumerant_ptr p; + p.p = capn_new_struct(s, 8, 2); + return p; +} +Enumerant_list new_Enumerant_list(struct capn_segment *s, int len) { + Enumerant_list p; + p.p = capn_new_list(s, len, 8, 2); + return p; +} +void read_Enumerant(struct Enumerant *s capnp_unused, Enumerant_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->name = capn_get_text(p.p, 0, capn_val0); + s->codeOrder = capn_read16(p.p, 0); + s->annotations.p = capn_getp(p.p, 1, 0); +} +void write_Enumerant(const struct Enumerant *s capnp_unused, Enumerant_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->name); + capn_write16(p.p, 0, s->codeOrder); + capn_setp(p.p, 1, s->annotations.p); +} +void get_Enumerant(struct Enumerant *s, Enumerant_list l, int i) { + Enumerant_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Enumerant(s, p); +} +void set_Enumerant(const struct Enumerant *s, Enumerant_list l, int i) { + Enumerant_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Enumerant(s, p); +} + +capn_text Enumerant_get_name(Enumerant_ptr p) +{ + capn_text name; + name = capn_get_text(p.p, 0, capn_val0); + return name; +} + +uint16_t Enumerant_get_codeOrder(Enumerant_ptr p) +{ + uint16_t codeOrder; + codeOrder = capn_read16(p.p, 0); + return codeOrder; +} + +Annotation_list Enumerant_get_annotations(Enumerant_ptr p) +{ + Annotation_list annotations; + annotations.p = capn_getp(p.p, 1, 0); + return annotations; +} + +void Enumerant_set_name(Enumerant_ptr p, capn_text name) +{ + capn_set_text(p.p, 0, name); +} + +void Enumerant_set_codeOrder(Enumerant_ptr p, uint16_t codeOrder) +{ + capn_write16(p.p, 0, codeOrder); +} + +void Enumerant_set_annotations(Enumerant_ptr p, Annotation_list annotations) +{ + capn_setp(p.p, 1, annotations.p); +} + +Superclass_ptr new_Superclass(struct capn_segment *s) { + Superclass_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +Superclass_list new_Superclass_list(struct capn_segment *s, int len) { + Superclass_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_Superclass(struct Superclass *s capnp_unused, Superclass_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->id = capn_read64(p.p, 0); + s->brand.p = capn_getp(p.p, 0, 0); +} +void write_Superclass(const struct Superclass *s capnp_unused, Superclass_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, s->id); + capn_setp(p.p, 0, s->brand.p); +} +void get_Superclass(struct Superclass *s, Superclass_list l, int i) { + Superclass_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Superclass(s, p); +} +void set_Superclass(const struct Superclass *s, Superclass_list l, int i) { + Superclass_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Superclass(s, p); +} + +uint64_t Superclass_get_id(Superclass_ptr p) +{ + uint64_t id; + id = capn_read64(p.p, 0); + return id; +} + +Brand_ptr Superclass_get_brand(Superclass_ptr p) +{ + Brand_ptr brand; + brand.p = capn_getp(p.p, 0, 0); + return brand; +} + +void Superclass_set_id(Superclass_ptr p, uint64_t id) +{ + capn_write64(p.p, 0, id); +} + +void Superclass_set_brand(Superclass_ptr p, Brand_ptr brand) +{ + capn_setp(p.p, 0, brand.p); +} + +Method_ptr new_Method(struct capn_segment *s) { + Method_ptr p; + p.p = capn_new_struct(s, 24, 5); + return p; +} +Method_list new_Method_list(struct capn_segment *s, int len) { + Method_list p; + p.p = capn_new_list(s, len, 24, 5); + return p; +} +void read_Method(struct Method *s capnp_unused, Method_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->name = capn_get_text(p.p, 0, capn_val0); + s->codeOrder = capn_read16(p.p, 0); + s->implicitParameters.p = capn_getp(p.p, 4, 0); + s->paramStructType = capn_read64(p.p, 8); + s->paramBrand.p = capn_getp(p.p, 2, 0); + s->resultStructType = capn_read64(p.p, 16); + s->resultBrand.p = capn_getp(p.p, 3, 0); + s->annotations.p = capn_getp(p.p, 1, 0); +} +void write_Method(const struct Method *s capnp_unused, Method_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->name); + capn_write16(p.p, 0, s->codeOrder); + capn_setp(p.p, 4, s->implicitParameters.p); + capn_write64(p.p, 8, s->paramStructType); + capn_setp(p.p, 2, s->paramBrand.p); + capn_write64(p.p, 16, s->resultStructType); + capn_setp(p.p, 3, s->resultBrand.p); + capn_setp(p.p, 1, s->annotations.p); +} +void get_Method(struct Method *s, Method_list l, int i) { + Method_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Method(s, p); +} +void set_Method(const struct Method *s, Method_list l, int i) { + Method_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Method(s, p); +} + +capn_text Method_get_name(Method_ptr p) +{ + capn_text name; + name = capn_get_text(p.p, 0, capn_val0); + return name; +} + +uint16_t Method_get_codeOrder(Method_ptr p) +{ + uint16_t codeOrder; + codeOrder = capn_read16(p.p, 0); + return codeOrder; +} + +Node_Parameter_list Method_get_implicitParameters(Method_ptr p) +{ + Node_Parameter_list implicitParameters; + implicitParameters.p = capn_getp(p.p, 4, 0); + return implicitParameters; +} + +uint64_t Method_get_paramStructType(Method_ptr p) +{ + uint64_t paramStructType; + paramStructType = capn_read64(p.p, 8); + return paramStructType; +} + +Brand_ptr Method_get_paramBrand(Method_ptr p) +{ + Brand_ptr paramBrand; + paramBrand.p = capn_getp(p.p, 2, 0); + return paramBrand; +} + +uint64_t Method_get_resultStructType(Method_ptr p) +{ + uint64_t resultStructType; + resultStructType = capn_read64(p.p, 16); + return resultStructType; +} + +Brand_ptr Method_get_resultBrand(Method_ptr p) +{ + Brand_ptr resultBrand; + resultBrand.p = capn_getp(p.p, 3, 0); + return resultBrand; +} + +Annotation_list Method_get_annotations(Method_ptr p) +{ + Annotation_list annotations; + annotations.p = capn_getp(p.p, 1, 0); + return annotations; +} + +void Method_set_name(Method_ptr p, capn_text name) +{ + capn_set_text(p.p, 0, name); +} + +void Method_set_codeOrder(Method_ptr p, uint16_t codeOrder) +{ + capn_write16(p.p, 0, codeOrder); +} + +void Method_set_implicitParameters(Method_ptr p, Node_Parameter_list implicitParameters) +{ + capn_setp(p.p, 4, implicitParameters.p); +} + +void Method_set_paramStructType(Method_ptr p, uint64_t paramStructType) +{ + capn_write64(p.p, 8, paramStructType); +} + +void Method_set_paramBrand(Method_ptr p, Brand_ptr paramBrand) +{ + capn_setp(p.p, 2, paramBrand.p); +} + +void Method_set_resultStructType(Method_ptr p, uint64_t resultStructType) +{ + capn_write64(p.p, 16, resultStructType); +} + +void Method_set_resultBrand(Method_ptr p, Brand_ptr resultBrand) +{ + capn_setp(p.p, 3, resultBrand.p); +} + +void Method_set_annotations(Method_ptr p, Annotation_list annotations) +{ + capn_setp(p.p, 1, annotations.p); +} + +Type_ptr new_Type(struct capn_segment *s) { + Type_ptr p; + p.p = capn_new_struct(s, 24, 1); + return p; +} +Type_list new_Type_list(struct capn_segment *s, int len) { + Type_list p; + p.p = capn_new_list(s, len, 24, 1); + return p; +} +void read_Type(struct Type *s capnp_unused, Type_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->which = (enum Type_which)(int) capn_read16(p.p, 0); + switch (s->which) { + case Type__list: + s->_list.elementType.p = capn_getp(p.p, 0, 0); + break; + case Type__enum: + s->_enum.typeId = capn_read64(p.p, 8); + s->_enum.brand.p = capn_getp(p.p, 0, 0); + break; + case Type__struct: + s->_struct.typeId = capn_read64(p.p, 8); + s->_struct.brand.p = capn_getp(p.p, 0, 0); + break; + case Type__interface: + s->_interface.typeId = capn_read64(p.p, 8); + s->_interface.brand.p = capn_getp(p.p, 0, 0); + break; + case Type_anyPointer: + s->anyPointer.which = (enum Type_anyPointer_which)(int) capn_read16(p.p, 8); + switch (s->anyPointer.which) { + case Type_anyPointer_parameter: + s->anyPointer.parameter.scopeId = capn_read64(p.p, 16); + s->anyPointer.parameter.parameterIndex = capn_read16(p.p, 10); + break; + case Type_anyPointer_implicitMethodParameter: + s->anyPointer.implicitMethodParameter.parameterIndex = capn_read16(p.p, 10); + break; + default: + break; + } + break; + default: + break; + } +} +void write_Type(const struct Type *s capnp_unused, Type_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, s->which); + switch (s->which) { + case Type__list: + capn_setp(p.p, 0, s->_list.elementType.p); + break; + case Type__enum: + capn_write64(p.p, 8, s->_enum.typeId); + capn_setp(p.p, 0, s->_enum.brand.p); + break; + case Type__struct: + capn_write64(p.p, 8, s->_struct.typeId); + capn_setp(p.p, 0, s->_struct.brand.p); + break; + case Type__interface: + capn_write64(p.p, 8, s->_interface.typeId); + capn_setp(p.p, 0, s->_interface.brand.p); + break; + case Type_anyPointer: + capn_write16(p.p, 8, s->anyPointer.which); + switch (s->anyPointer.which) { + case Type_anyPointer_parameter: + capn_write64(p.p, 16, s->anyPointer.parameter.scopeId); + capn_write16(p.p, 10, s->anyPointer.parameter.parameterIndex); + break; + case Type_anyPointer_implicitMethodParameter: + capn_write16(p.p, 10, s->anyPointer.implicitMethodParameter.parameterIndex); + break; + default: + break; + } + break; + default: + break; + } +} +void get_Type(struct Type *s, Type_list l, int i) { + Type_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Type(s, p); +} +void set_Type(const struct Type *s, Type_list l, int i) { + Type_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Type(s, p); +} + +Brand_ptr new_Brand(struct capn_segment *s) { + Brand_ptr p; + p.p = capn_new_struct(s, 0, 1); + return p; +} +Brand_list new_Brand_list(struct capn_segment *s, int len) { + Brand_list p; + p.p = capn_new_list(s, len, 0, 1); + return p; +} +void read_Brand(struct Brand *s capnp_unused, Brand_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->scopes.p = capn_getp(p.p, 0, 0); +} +void write_Brand(const struct Brand *s capnp_unused, Brand_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_setp(p.p, 0, s->scopes.p); +} +void get_Brand(struct Brand *s, Brand_list l, int i) { + Brand_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Brand(s, p); +} +void set_Brand(const struct Brand *s, Brand_list l, int i) { + Brand_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Brand(s, p); +} + +Brand_Scope_list Brand_get_scopes(Brand_ptr p) +{ + Brand_Scope_list scopes; + scopes.p = capn_getp(p.p, 0, 0); + return scopes; +} + +void Brand_set_scopes(Brand_ptr p, Brand_Scope_list scopes) +{ + capn_setp(p.p, 0, scopes.p); +} + +Brand_Scope_ptr new_Brand_Scope(struct capn_segment *s) { + Brand_Scope_ptr p; + p.p = capn_new_struct(s, 16, 1); + return p; +} +Brand_Scope_list new_Brand_Scope_list(struct capn_segment *s, int len) { + Brand_Scope_list p; + p.p = capn_new_list(s, len, 16, 1); + return p; +} +void read_Brand_Scope(struct Brand_Scope *s capnp_unused, Brand_Scope_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->scopeId = capn_read64(p.p, 0); + s->which = (enum Brand_Scope_which)(int) capn_read16(p.p, 8); + switch (s->which) { + case Brand_Scope_bind: + s->bind.p = capn_getp(p.p, 0, 0); + break; + default: + break; + } +} +void write_Brand_Scope(const struct Brand_Scope *s capnp_unused, Brand_Scope_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, s->scopeId); + capn_write16(p.p, 8, s->which); + switch (s->which) { + case Brand_Scope_bind: + capn_setp(p.p, 0, s->bind.p); + break; + default: + break; + } +} +void get_Brand_Scope(struct Brand_Scope *s, Brand_Scope_list l, int i) { + Brand_Scope_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Brand_Scope(s, p); +} +void set_Brand_Scope(const struct Brand_Scope *s, Brand_Scope_list l, int i) { + Brand_Scope_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Brand_Scope(s, p); +} + +uint64_t Brand_Scope_get_scopeId(Brand_Scope_ptr p) +{ + uint64_t scopeId; + scopeId = capn_read64(p.p, 0); + return scopeId; +} + +void Brand_Scope_set_scopeId(Brand_Scope_ptr p, uint64_t scopeId) +{ + capn_write64(p.p, 0, scopeId); +} + +Brand_Binding_ptr new_Brand_Binding(struct capn_segment *s) { + Brand_Binding_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +Brand_Binding_list new_Brand_Binding_list(struct capn_segment *s, int len) { + Brand_Binding_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_Brand_Binding(struct Brand_Binding *s capnp_unused, Brand_Binding_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->which = (enum Brand_Binding_which)(int) capn_read16(p.p, 0); + switch (s->which) { + case Brand_Binding_type: + s->type.p = capn_getp(p.p, 0, 0); + break; + default: + break; + } +} +void write_Brand_Binding(const struct Brand_Binding *s capnp_unused, Brand_Binding_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, s->which); + switch (s->which) { + case Brand_Binding_type: + capn_setp(p.p, 0, s->type.p); + break; + default: + break; + } +} +void get_Brand_Binding(struct Brand_Binding *s, Brand_Binding_list l, int i) { + Brand_Binding_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Brand_Binding(s, p); +} +void set_Brand_Binding(const struct Brand_Binding *s, Brand_Binding_list l, int i) { + Brand_Binding_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Brand_Binding(s, p); +} + +Value_ptr new_Value(struct capn_segment *s) { + Value_ptr p; + p.p = capn_new_struct(s, 16, 1); + return p; +} +Value_list new_Value_list(struct capn_segment *s, int len) { + Value_list p; + p.p = capn_new_list(s, len, 16, 1); + return p; +} +void read_Value(struct Value *s capnp_unused, Value_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->which = (enum Value_which)(int) capn_read16(p.p, 0); + switch (s->which) { + case Value__bool: + s->_bool = (capn_read8(p.p, 2) & 1) != 0; + break; + case Value_int8: + case Value_uint8: + s->uint8 = capn_read8(p.p, 2); + break; + case Value_int16: + case Value_uint16: + case Value__enum: + s->_enum = capn_read16(p.p, 2); + break; + case Value_int32: + case Value_uint32: + case Value_float32: + s->float32 = capn_to_f32(capn_read32(p.p, 4)); + break; + case Value_int64: + case Value_uint64: + case Value_float64: + s->float64 = capn_to_f64(capn_read64(p.p, 8)); + break; + case Value_text: + s->text = capn_get_text(p.p, 0, capn_val0); + break; + case Value_data: + s->data = capn_get_data(p.p, 0); + break; + case Value__list: + case Value__struct: + case Value_anyPointer: + s->anyPointer = capn_getp(p.p, 0, 0); + break; + default: + break; + } +} +void write_Value(const struct Value *s capnp_unused, Value_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, s->which); + switch (s->which) { + case Value__bool: + capn_write1(p.p, 16, s->_bool != 0); + break; + case Value_int8: + case Value_uint8: + capn_write8(p.p, 2, s->uint8); + break; + case Value_int16: + case Value_uint16: + case Value__enum: + capn_write16(p.p, 2, s->_enum); + break; + case Value_int32: + case Value_uint32: + case Value_float32: + capn_write32(p.p, 4, capn_from_f32(s->float32)); + break; + case Value_int64: + case Value_uint64: + case Value_float64: + capn_write64(p.p, 8, capn_from_f64(s->float64)); + break; + case Value_text: + capn_set_text(p.p, 0, s->text); + break; + case Value_data: + capn_setp(p.p, 0, s->data.p); + break; + case Value__list: + case Value__struct: + case Value_anyPointer: + capn_setp(p.p, 0, s->anyPointer); + break; + default: + break; + } +} +void get_Value(struct Value *s, Value_list l, int i) { + Value_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Value(s, p); +} +void set_Value(const struct Value *s, Value_list l, int i) { + Value_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Value(s, p); +} + +Annotation_ptr new_Annotation(struct capn_segment *s) { + Annotation_ptr p; + p.p = capn_new_struct(s, 8, 2); + return p; +} +Annotation_list new_Annotation_list(struct capn_segment *s, int len) { + Annotation_list p; + p.p = capn_new_list(s, len, 8, 2); + return p; +} +void read_Annotation(struct Annotation *s capnp_unused, Annotation_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->id = capn_read64(p.p, 0); + s->brand.p = capn_getp(p.p, 1, 0); + s->value.p = capn_getp(p.p, 0, 0); +} +void write_Annotation(const struct Annotation *s capnp_unused, Annotation_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, s->id); + capn_setp(p.p, 1, s->brand.p); + capn_setp(p.p, 0, s->value.p); +} +void get_Annotation(struct Annotation *s, Annotation_list l, int i) { + Annotation_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Annotation(s, p); +} +void set_Annotation(const struct Annotation *s, Annotation_list l, int i) { + Annotation_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Annotation(s, p); +} + +uint64_t Annotation_get_id(Annotation_ptr p) +{ + uint64_t id; + id = capn_read64(p.p, 0); + return id; +} + +Brand_ptr Annotation_get_brand(Annotation_ptr p) +{ + Brand_ptr brand; + brand.p = capn_getp(p.p, 1, 0); + return brand; +} + +Value_ptr Annotation_get_value(Annotation_ptr p) +{ + Value_ptr value; + value.p = capn_getp(p.p, 0, 0); + return value; +} + +void Annotation_set_id(Annotation_ptr p, uint64_t id) +{ + capn_write64(p.p, 0, id); +} + +void Annotation_set_brand(Annotation_ptr p, Brand_ptr brand) +{ + capn_setp(p.p, 1, brand.p); +} + +void Annotation_set_value(Annotation_ptr p, Value_ptr value) +{ + capn_setp(p.p, 0, value.p); +} + +CodeGeneratorRequest_ptr new_CodeGeneratorRequest(struct capn_segment *s) { + CodeGeneratorRequest_ptr p; + p.p = capn_new_struct(s, 0, 2); + return p; +} +CodeGeneratorRequest_list new_CodeGeneratorRequest_list(struct capn_segment *s, int len) { + CodeGeneratorRequest_list p; + p.p = capn_new_list(s, len, 0, 2); + return p; +} +void read_CodeGeneratorRequest(struct CodeGeneratorRequest *s capnp_unused, CodeGeneratorRequest_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->nodes.p = capn_getp(p.p, 0, 0); + s->requestedFiles.p = capn_getp(p.p, 1, 0); +} +void write_CodeGeneratorRequest(const struct CodeGeneratorRequest *s capnp_unused, CodeGeneratorRequest_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_setp(p.p, 0, s->nodes.p); + capn_setp(p.p, 1, s->requestedFiles.p); +} +void get_CodeGeneratorRequest(struct CodeGeneratorRequest *s, CodeGeneratorRequest_list l, int i) { + CodeGeneratorRequest_ptr p; + p.p = capn_getp(l.p, i, 0); + read_CodeGeneratorRequest(s, p); +} +void set_CodeGeneratorRequest(const struct CodeGeneratorRequest *s, CodeGeneratorRequest_list l, int i) { + CodeGeneratorRequest_ptr p; + p.p = capn_getp(l.p, i, 0); + write_CodeGeneratorRequest(s, p); +} + +Node_list CodeGeneratorRequest_get_nodes(CodeGeneratorRequest_ptr p) +{ + Node_list nodes; + nodes.p = capn_getp(p.p, 0, 0); + return nodes; +} + +CodeGeneratorRequest_RequestedFile_list CodeGeneratorRequest_get_requestedFiles(CodeGeneratorRequest_ptr p) +{ + CodeGeneratorRequest_RequestedFile_list requestedFiles; + requestedFiles.p = capn_getp(p.p, 1, 0); + return requestedFiles; +} + +void CodeGeneratorRequest_set_nodes(CodeGeneratorRequest_ptr p, Node_list nodes) +{ + capn_setp(p.p, 0, nodes.p); +} + +void CodeGeneratorRequest_set_requestedFiles(CodeGeneratorRequest_ptr p, CodeGeneratorRequest_RequestedFile_list requestedFiles) +{ + capn_setp(p.p, 1, requestedFiles.p); +} + +CodeGeneratorRequest_RequestedFile_ptr new_CodeGeneratorRequest_RequestedFile(struct capn_segment *s) { + CodeGeneratorRequest_RequestedFile_ptr p; + p.p = capn_new_struct(s, 8, 2); + return p; +} +CodeGeneratorRequest_RequestedFile_list new_CodeGeneratorRequest_RequestedFile_list(struct capn_segment *s, int len) { + CodeGeneratorRequest_RequestedFile_list p; + p.p = capn_new_list(s, len, 8, 2); + return p; +} +void read_CodeGeneratorRequest_RequestedFile(struct CodeGeneratorRequest_RequestedFile *s capnp_unused, CodeGeneratorRequest_RequestedFile_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->id = capn_read64(p.p, 0); + s->filename = capn_get_text(p.p, 0, capn_val0); + s->imports.p = capn_getp(p.p, 1, 0); +} +void write_CodeGeneratorRequest_RequestedFile(const struct CodeGeneratorRequest_RequestedFile *s capnp_unused, CodeGeneratorRequest_RequestedFile_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, s->id); + capn_set_text(p.p, 0, s->filename); + capn_setp(p.p, 1, s->imports.p); +} +void get_CodeGeneratorRequest_RequestedFile(struct CodeGeneratorRequest_RequestedFile *s, CodeGeneratorRequest_RequestedFile_list l, int i) { + CodeGeneratorRequest_RequestedFile_ptr p; + p.p = capn_getp(l.p, i, 0); + read_CodeGeneratorRequest_RequestedFile(s, p); +} +void set_CodeGeneratorRequest_RequestedFile(const struct CodeGeneratorRequest_RequestedFile *s, CodeGeneratorRequest_RequestedFile_list l, int i) { + CodeGeneratorRequest_RequestedFile_ptr p; + p.p = capn_getp(l.p, i, 0); + write_CodeGeneratorRequest_RequestedFile(s, p); +} + +uint64_t CodeGeneratorRequest_RequestedFile_get_id(CodeGeneratorRequest_RequestedFile_ptr p) +{ + uint64_t id; + id = capn_read64(p.p, 0); + return id; +} + +capn_text CodeGeneratorRequest_RequestedFile_get_filename(CodeGeneratorRequest_RequestedFile_ptr p) +{ + capn_text filename; + filename = capn_get_text(p.p, 0, capn_val0); + return filename; +} + +CodeGeneratorRequest_RequestedFile_Import_list CodeGeneratorRequest_RequestedFile_get_imports(CodeGeneratorRequest_RequestedFile_ptr p) +{ + CodeGeneratorRequest_RequestedFile_Import_list imports; + imports.p = capn_getp(p.p, 1, 0); + return imports; +} + +void CodeGeneratorRequest_RequestedFile_set_id(CodeGeneratorRequest_RequestedFile_ptr p, uint64_t id) +{ + capn_write64(p.p, 0, id); +} + +void CodeGeneratorRequest_RequestedFile_set_filename(CodeGeneratorRequest_RequestedFile_ptr p, capn_text filename) +{ + capn_set_text(p.p, 0, filename); +} + +void CodeGeneratorRequest_RequestedFile_set_imports(CodeGeneratorRequest_RequestedFile_ptr p, CodeGeneratorRequest_RequestedFile_Import_list imports) +{ + capn_setp(p.p, 1, imports.p); +} + +CodeGeneratorRequest_RequestedFile_Import_ptr new_CodeGeneratorRequest_RequestedFile_Import(struct capn_segment *s) { + CodeGeneratorRequest_RequestedFile_Import_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +CodeGeneratorRequest_RequestedFile_Import_list new_CodeGeneratorRequest_RequestedFile_Import_list(struct capn_segment *s, int len) { + CodeGeneratorRequest_RequestedFile_Import_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_CodeGeneratorRequest_RequestedFile_Import(struct CodeGeneratorRequest_RequestedFile_Import *s capnp_unused, CodeGeneratorRequest_RequestedFile_Import_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->id = capn_read64(p.p, 0); + s->name = capn_get_text(p.p, 0, capn_val0); +} +void write_CodeGeneratorRequest_RequestedFile_Import(const struct CodeGeneratorRequest_RequestedFile_Import *s capnp_unused, CodeGeneratorRequest_RequestedFile_Import_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, s->id); + capn_set_text(p.p, 0, s->name); +} +void get_CodeGeneratorRequest_RequestedFile_Import(struct CodeGeneratorRequest_RequestedFile_Import *s, CodeGeneratorRequest_RequestedFile_Import_list l, int i) { + CodeGeneratorRequest_RequestedFile_Import_ptr p; + p.p = capn_getp(l.p, i, 0); + read_CodeGeneratorRequest_RequestedFile_Import(s, p); +} +void set_CodeGeneratorRequest_RequestedFile_Import(const struct CodeGeneratorRequest_RequestedFile_Import *s, CodeGeneratorRequest_RequestedFile_Import_list l, int i) { + CodeGeneratorRequest_RequestedFile_Import_ptr p; + p.p = capn_getp(l.p, i, 0); + write_CodeGeneratorRequest_RequestedFile_Import(s, p); +} + +uint64_t CodeGeneratorRequest_RequestedFile_Import_get_id(CodeGeneratorRequest_RequestedFile_Import_ptr p) +{ + uint64_t id; + id = capn_read64(p.p, 0); + return id; +} + +capn_text CodeGeneratorRequest_RequestedFile_Import_get_name(CodeGeneratorRequest_RequestedFile_Import_ptr p) +{ + capn_text name; + name = capn_get_text(p.p, 0, capn_val0); + return name; +} + +void CodeGeneratorRequest_RequestedFile_Import_set_id(CodeGeneratorRequest_RequestedFile_Import_ptr p, uint64_t id) +{ + capn_write64(p.p, 0, id); +} + +void CodeGeneratorRequest_RequestedFile_Import_set_name(CodeGeneratorRequest_RequestedFile_Import_ptr p, capn_text name) +{ + capn_set_text(p.p, 0, name); +} diff --git a/src/subprojects/c-capnproto/compiler/schema.capnp.h b/src/subprojects/c-capnproto/compiler/schema.capnp.h new file mode 100644 index 00000000..c986fbc6 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/schema.capnp.h @@ -0,0 +1,734 @@ +#ifndef CAPN_A93FC509624C72D9 +#define CAPN_A93FC509624C72D9 +/* AUTO GENERATED - DO NOT EDIT */ +#include + +#if CAPN_VERSION != 1 +#error "version mismatch between capnp_c.h and generated code" +#endif + +#ifndef capnp_nowarn +# ifdef __GNUC__ +# define capnp_nowarn __extension__ +# else +# define capnp_nowarn +# endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +struct Node; +struct Node_Parameter; +struct Node_NestedNode; +struct Field; +struct Enumerant; +struct Superclass; +struct Method; +struct Type; +struct Brand; +struct Brand_Scope; +struct Brand_Binding; +struct Value; +struct Annotation; +struct CodeGeneratorRequest; +struct CodeGeneratorRequest_RequestedFile; +struct CodeGeneratorRequest_RequestedFile_Import; + +typedef struct {capn_ptr p;} Node_ptr; +typedef struct {capn_ptr p;} Node_Parameter_ptr; +typedef struct {capn_ptr p;} Node_NestedNode_ptr; +typedef struct {capn_ptr p;} Field_ptr; +typedef struct {capn_ptr p;} Enumerant_ptr; +typedef struct {capn_ptr p;} Superclass_ptr; +typedef struct {capn_ptr p;} Method_ptr; +typedef struct {capn_ptr p;} Type_ptr; +typedef struct {capn_ptr p;} Brand_ptr; +typedef struct {capn_ptr p;} Brand_Scope_ptr; +typedef struct {capn_ptr p;} Brand_Binding_ptr; +typedef struct {capn_ptr p;} Value_ptr; +typedef struct {capn_ptr p;} Annotation_ptr; +typedef struct {capn_ptr p;} CodeGeneratorRequest_ptr; +typedef struct {capn_ptr p;} CodeGeneratorRequest_RequestedFile_ptr; +typedef struct {capn_ptr p;} CodeGeneratorRequest_RequestedFile_Import_ptr; + +typedef struct {capn_ptr p;} Node_list; +typedef struct {capn_ptr p;} Node_Parameter_list; +typedef struct {capn_ptr p;} Node_NestedNode_list; +typedef struct {capn_ptr p;} Field_list; +typedef struct {capn_ptr p;} Enumerant_list; +typedef struct {capn_ptr p;} Superclass_list; +typedef struct {capn_ptr p;} Method_list; +typedef struct {capn_ptr p;} Type_list; +typedef struct {capn_ptr p;} Brand_list; +typedef struct {capn_ptr p;} Brand_Scope_list; +typedef struct {capn_ptr p;} Brand_Binding_list; +typedef struct {capn_ptr p;} Value_list; +typedef struct {capn_ptr p;} Annotation_list; +typedef struct {capn_ptr p;} CodeGeneratorRequest_list; +typedef struct {capn_ptr p;} CodeGeneratorRequest_RequestedFile_list; +typedef struct {capn_ptr p;} CodeGeneratorRequest_RequestedFile_Import_list; + +enum ElementSize { + ElementSize_empty = 0, + ElementSize_bit = 1, + ElementSize_byte = 2, + ElementSize_twoBytes = 3, + ElementSize_fourBytes = 4, + ElementSize_eightBytes = 5, + ElementSize_pointer = 6, + ElementSize_inlineComposite = 7 +}; +extern uint16_t Field_noDiscriminant; +enum Node_which { + Node_file = 0, + Node__struct = 1, + Node__enum = 2, + Node__interface = 3, + Node__const = 4, + Node_annotation = 5 +}; + +struct Node { + uint64_t id; + capn_text displayName; + uint32_t displayNamePrefixLength; + uint64_t scopeId; + Node_Parameter_list parameters; + unsigned isGeneric : 1; + Node_NestedNode_list nestedNodes; + Annotation_list annotations; + enum Node_which which; + capnp_nowarn union { + capnp_nowarn struct { + uint16_t dataWordCount; + uint16_t pointerCount; + enum ElementSize preferredListEncoding; + unsigned isGroup : 1; + uint16_t discriminantCount; + uint32_t discriminantOffset; + Field_list fields; + } _struct; + capnp_nowarn struct { + Enumerant_list enumerants; + } _enum; + capnp_nowarn struct { + Method_list methods; + Superclass_list superclasses; + } _interface; + capnp_nowarn struct { + Type_ptr type; + Value_ptr value; + } _const; + capnp_nowarn struct { + Type_ptr type; + unsigned targetsFile : 1; + unsigned targetsConst : 1; + unsigned targetsEnum : 1; + unsigned targetsEnumerant : 1; + unsigned targetsStruct : 1; + unsigned targetsField : 1; + unsigned targetsUnion : 1; + unsigned targetsGroup : 1; + unsigned targetsInterface : 1; + unsigned targetsMethod : 1; + unsigned targetsParam : 1; + unsigned targetsAnnotation : 1; + } annotation; + }; +}; + +static const size_t Node_word_count = 5; + +static const size_t Node_pointer_count = 6; + +static const size_t Node_struct_bytes_count = 88; + + +uint64_t Node_get_id(Node_ptr p); + +capn_text Node_get_displayName(Node_ptr p); + +uint32_t Node_get_displayNamePrefixLength(Node_ptr p); + +uint64_t Node_get_scopeId(Node_ptr p); + +Node_Parameter_list Node_get_parameters(Node_ptr p); + +unsigned Node_get_isGeneric(Node_ptr p); + +Node_NestedNode_list Node_get_nestedNodes(Node_ptr p); + +Annotation_list Node_get_annotations(Node_ptr p); + +void Node_set_id(Node_ptr p, uint64_t id); + +void Node_set_displayName(Node_ptr p, capn_text displayName); + +void Node_set_displayNamePrefixLength(Node_ptr p, uint32_t displayNamePrefixLength); + +void Node_set_scopeId(Node_ptr p, uint64_t scopeId); + +void Node_set_parameters(Node_ptr p, Node_Parameter_list parameters); + +void Node_set_isGeneric(Node_ptr p, unsigned isGeneric); + +void Node_set_nestedNodes(Node_ptr p, Node_NestedNode_list nestedNodes); + +void Node_set_annotations(Node_ptr p, Annotation_list annotations); + +struct Node_Parameter { + capn_text name; +}; + +static const size_t Node_Parameter_word_count = 0; + +static const size_t Node_Parameter_pointer_count = 1; + +static const size_t Node_Parameter_struct_bytes_count = 8; + + +capn_text Node_Parameter_get_name(Node_Parameter_ptr p); + +void Node_Parameter_set_name(Node_Parameter_ptr p, capn_text name); + +struct Node_NestedNode { + capn_text name; + uint64_t id; +}; + +static const size_t Node_NestedNode_word_count = 1; + +static const size_t Node_NestedNode_pointer_count = 1; + +static const size_t Node_NestedNode_struct_bytes_count = 16; + + +capn_text Node_NestedNode_get_name(Node_NestedNode_ptr p); + +uint64_t Node_NestedNode_get_id(Node_NestedNode_ptr p); + +void Node_NestedNode_set_name(Node_NestedNode_ptr p, capn_text name); + +void Node_NestedNode_set_id(Node_NestedNode_ptr p, uint64_t id); +enum Field_which { + Field_slot = 0, + Field_group = 1 +}; +enum Field_ordinal_which { + Field_ordinal_implicit = 0, + Field_ordinal__explicit = 1 +}; + +struct Field { + capn_text name; + uint16_t codeOrder; + Annotation_list annotations; + uint16_t discriminantValue; + enum Field_which which; + capnp_nowarn union { + capnp_nowarn struct { + uint32_t offset; + Type_ptr type; + Value_ptr defaultValue; + unsigned hadExplicitDefault : 1; + } slot; + capnp_nowarn struct { + uint64_t typeId; + } group; + }; + enum Field_ordinal_which ordinal_which; + capnp_nowarn union { + uint16_t _explicit; + } ordinal; +}; + +static const size_t Field_word_count = 3; + +static const size_t Field_pointer_count = 4; + +static const size_t Field_struct_bytes_count = 56; + + +capn_text Field_get_name(Field_ptr p); + +uint16_t Field_get_codeOrder(Field_ptr p); + +Annotation_list Field_get_annotations(Field_ptr p); + +uint16_t Field_get_discriminantValue(Field_ptr p); + +void Field_set_name(Field_ptr p, capn_text name); + +void Field_set_codeOrder(Field_ptr p, uint16_t codeOrder); + +void Field_set_annotations(Field_ptr p, Annotation_list annotations); + +void Field_set_discriminantValue(Field_ptr p, uint16_t discriminantValue); + +struct Enumerant { + capn_text name; + uint16_t codeOrder; + Annotation_list annotations; +}; + +static const size_t Enumerant_word_count = 1; + +static const size_t Enumerant_pointer_count = 2; + +static const size_t Enumerant_struct_bytes_count = 24; + + +capn_text Enumerant_get_name(Enumerant_ptr p); + +uint16_t Enumerant_get_codeOrder(Enumerant_ptr p); + +Annotation_list Enumerant_get_annotations(Enumerant_ptr p); + +void Enumerant_set_name(Enumerant_ptr p, capn_text name); + +void Enumerant_set_codeOrder(Enumerant_ptr p, uint16_t codeOrder); + +void Enumerant_set_annotations(Enumerant_ptr p, Annotation_list annotations); + +struct Superclass { + uint64_t id; + Brand_ptr brand; +}; + +static const size_t Superclass_word_count = 1; + +static const size_t Superclass_pointer_count = 1; + +static const size_t Superclass_struct_bytes_count = 16; + + +uint64_t Superclass_get_id(Superclass_ptr p); + +Brand_ptr Superclass_get_brand(Superclass_ptr p); + +void Superclass_set_id(Superclass_ptr p, uint64_t id); + +void Superclass_set_brand(Superclass_ptr p, Brand_ptr brand); + +struct Method { + capn_text name; + uint16_t codeOrder; + Node_Parameter_list implicitParameters; + uint64_t paramStructType; + Brand_ptr paramBrand; + uint64_t resultStructType; + Brand_ptr resultBrand; + Annotation_list annotations; +}; + +static const size_t Method_word_count = 3; + +static const size_t Method_pointer_count = 5; + +static const size_t Method_struct_bytes_count = 64; + + +capn_text Method_get_name(Method_ptr p); + +uint16_t Method_get_codeOrder(Method_ptr p); + +Node_Parameter_list Method_get_implicitParameters(Method_ptr p); + +uint64_t Method_get_paramStructType(Method_ptr p); + +Brand_ptr Method_get_paramBrand(Method_ptr p); + +uint64_t Method_get_resultStructType(Method_ptr p); + +Brand_ptr Method_get_resultBrand(Method_ptr p); + +Annotation_list Method_get_annotations(Method_ptr p); + +void Method_set_name(Method_ptr p, capn_text name); + +void Method_set_codeOrder(Method_ptr p, uint16_t codeOrder); + +void Method_set_implicitParameters(Method_ptr p, Node_Parameter_list implicitParameters); + +void Method_set_paramStructType(Method_ptr p, uint64_t paramStructType); + +void Method_set_paramBrand(Method_ptr p, Brand_ptr paramBrand); + +void Method_set_resultStructType(Method_ptr p, uint64_t resultStructType); + +void Method_set_resultBrand(Method_ptr p, Brand_ptr resultBrand); + +void Method_set_annotations(Method_ptr p, Annotation_list annotations); +enum Type_anyPointer_which { + Type_anyPointer_unconstrained = 0, + Type_anyPointer_parameter = 1, + Type_anyPointer_implicitMethodParameter = 2 +}; +enum Type_which { + Type__void = 0, + Type__bool = 1, + Type_int8 = 2, + Type_int16 = 3, + Type_int32 = 4, + Type_int64 = 5, + Type_uint8 = 6, + Type_uint16 = 7, + Type_uint32 = 8, + Type_uint64 = 9, + Type_float32 = 10, + Type_float64 = 11, + Type_text = 12, + Type_data = 13, + Type__list = 14, + Type__enum = 15, + Type__struct = 16, + Type__interface = 17, + Type_anyPointer = 18 +}; + +struct Type { + enum Type_which which; + capnp_nowarn union { + capnp_nowarn struct { + Type_ptr elementType; + } _list; + capnp_nowarn struct { + uint64_t typeId; + Brand_ptr brand; + } _enum; + capnp_nowarn struct { + uint64_t typeId; + Brand_ptr brand; + } _struct; + capnp_nowarn struct { + uint64_t typeId; + Brand_ptr brand; + } _interface; + capnp_nowarn struct { + enum Type_anyPointer_which which; + capnp_nowarn union { + capnp_nowarn struct { + uint64_t scopeId; + uint16_t parameterIndex; + } parameter; + capnp_nowarn struct { + uint16_t parameterIndex; + } implicitMethodParameter; + }; + } anyPointer; + }; +}; + +static const size_t Type_word_count = 3; + +static const size_t Type_pointer_count = 1; + +static const size_t Type_struct_bytes_count = 32; + + +struct Brand { + Brand_Scope_list scopes; +}; + +static const size_t Brand_word_count = 0; + +static const size_t Brand_pointer_count = 1; + +static const size_t Brand_struct_bytes_count = 8; + + +Brand_Scope_list Brand_get_scopes(Brand_ptr p); + +void Brand_set_scopes(Brand_ptr p, Brand_Scope_list scopes); +enum Brand_Scope_which { + Brand_Scope_bind = 0, + Brand_Scope_inherit = 1 +}; + +struct Brand_Scope { + uint64_t scopeId; + enum Brand_Scope_which which; + capnp_nowarn union { + Brand_Binding_list bind; + }; +}; + +static const size_t Brand_Scope_word_count = 2; + +static const size_t Brand_Scope_pointer_count = 1; + +static const size_t Brand_Scope_struct_bytes_count = 24; + + +uint64_t Brand_Scope_get_scopeId(Brand_Scope_ptr p); + +void Brand_Scope_set_scopeId(Brand_Scope_ptr p, uint64_t scopeId); +enum Brand_Binding_which { + Brand_Binding_unbound = 0, + Brand_Binding_type = 1 +}; + +struct Brand_Binding { + enum Brand_Binding_which which; + capnp_nowarn union { + Type_ptr type; + }; +}; + +static const size_t Brand_Binding_word_count = 1; + +static const size_t Brand_Binding_pointer_count = 1; + +static const size_t Brand_Binding_struct_bytes_count = 16; + +enum Value_which { + Value__void = 0, + Value__bool = 1, + Value_int8 = 2, + Value_int16 = 3, + Value_int32 = 4, + Value_int64 = 5, + Value_uint8 = 6, + Value_uint16 = 7, + Value_uint32 = 8, + Value_uint64 = 9, + Value_float32 = 10, + Value_float64 = 11, + Value_text = 12, + Value_data = 13, + Value__list = 14, + Value__enum = 15, + Value__struct = 16, + Value__interface = 17, + Value_anyPointer = 18 +}; + +struct Value { + enum Value_which which; + capnp_nowarn union { + unsigned _bool : 1; + int8_t int8; + int16_t int16; + int32_t int32; + int64_t int64; + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + float float32; + double float64; + capn_text text; + capn_data data; + capn_ptr _list; + uint16_t _enum; + capn_ptr _struct; + capn_ptr anyPointer; + }; +}; + +static const size_t Value_word_count = 2; + +static const size_t Value_pointer_count = 1; + +static const size_t Value_struct_bytes_count = 24; + + +struct Annotation { + uint64_t id; + Brand_ptr brand; + Value_ptr value; +}; + +static const size_t Annotation_word_count = 1; + +static const size_t Annotation_pointer_count = 2; + +static const size_t Annotation_struct_bytes_count = 24; + + +uint64_t Annotation_get_id(Annotation_ptr p); + +Brand_ptr Annotation_get_brand(Annotation_ptr p); + +Value_ptr Annotation_get_value(Annotation_ptr p); + +void Annotation_set_id(Annotation_ptr p, uint64_t id); + +void Annotation_set_brand(Annotation_ptr p, Brand_ptr brand); + +void Annotation_set_value(Annotation_ptr p, Value_ptr value); + +struct CodeGeneratorRequest { + Node_list nodes; + CodeGeneratorRequest_RequestedFile_list requestedFiles; +}; + +static const size_t CodeGeneratorRequest_word_count = 0; + +static const size_t CodeGeneratorRequest_pointer_count = 2; + +static const size_t CodeGeneratorRequest_struct_bytes_count = 16; + + +Node_list CodeGeneratorRequest_get_nodes(CodeGeneratorRequest_ptr p); + +CodeGeneratorRequest_RequestedFile_list CodeGeneratorRequest_get_requestedFiles(CodeGeneratorRequest_ptr p); + +void CodeGeneratorRequest_set_nodes(CodeGeneratorRequest_ptr p, Node_list nodes); + +void CodeGeneratorRequest_set_requestedFiles(CodeGeneratorRequest_ptr p, CodeGeneratorRequest_RequestedFile_list requestedFiles); + +struct CodeGeneratorRequest_RequestedFile { + uint64_t id; + capn_text filename; + CodeGeneratorRequest_RequestedFile_Import_list imports; +}; + +static const size_t CodeGeneratorRequest_RequestedFile_word_count = 1; + +static const size_t CodeGeneratorRequest_RequestedFile_pointer_count = 2; + +static const size_t CodeGeneratorRequest_RequestedFile_struct_bytes_count = 24; + + +uint64_t CodeGeneratorRequest_RequestedFile_get_id(CodeGeneratorRequest_RequestedFile_ptr p); + +capn_text CodeGeneratorRequest_RequestedFile_get_filename(CodeGeneratorRequest_RequestedFile_ptr p); + +CodeGeneratorRequest_RequestedFile_Import_list CodeGeneratorRequest_RequestedFile_get_imports(CodeGeneratorRequest_RequestedFile_ptr p); + +void CodeGeneratorRequest_RequestedFile_set_id(CodeGeneratorRequest_RequestedFile_ptr p, uint64_t id); + +void CodeGeneratorRequest_RequestedFile_set_filename(CodeGeneratorRequest_RequestedFile_ptr p, capn_text filename); + +void CodeGeneratorRequest_RequestedFile_set_imports(CodeGeneratorRequest_RequestedFile_ptr p, CodeGeneratorRequest_RequestedFile_Import_list imports); + +struct CodeGeneratorRequest_RequestedFile_Import { + uint64_t id; + capn_text name; +}; + +static const size_t CodeGeneratorRequest_RequestedFile_Import_word_count = 1; + +static const size_t CodeGeneratorRequest_RequestedFile_Import_pointer_count = 1; + +static const size_t CodeGeneratorRequest_RequestedFile_Import_struct_bytes_count = 16; + + +uint64_t CodeGeneratorRequest_RequestedFile_Import_get_id(CodeGeneratorRequest_RequestedFile_Import_ptr p); + +capn_text CodeGeneratorRequest_RequestedFile_Import_get_name(CodeGeneratorRequest_RequestedFile_Import_ptr p); + +void CodeGeneratorRequest_RequestedFile_Import_set_id(CodeGeneratorRequest_RequestedFile_Import_ptr p, uint64_t id); + +void CodeGeneratorRequest_RequestedFile_Import_set_name(CodeGeneratorRequest_RequestedFile_Import_ptr p, capn_text name); + +Node_ptr new_Node(struct capn_segment*); +Node_Parameter_ptr new_Node_Parameter(struct capn_segment*); +Node_NestedNode_ptr new_Node_NestedNode(struct capn_segment*); +Field_ptr new_Field(struct capn_segment*); +Enumerant_ptr new_Enumerant(struct capn_segment*); +Superclass_ptr new_Superclass(struct capn_segment*); +Method_ptr new_Method(struct capn_segment*); +Type_ptr new_Type(struct capn_segment*); +Brand_ptr new_Brand(struct capn_segment*); +Brand_Scope_ptr new_Brand_Scope(struct capn_segment*); +Brand_Binding_ptr new_Brand_Binding(struct capn_segment*); +Value_ptr new_Value(struct capn_segment*); +Annotation_ptr new_Annotation(struct capn_segment*); +CodeGeneratorRequest_ptr new_CodeGeneratorRequest(struct capn_segment*); +CodeGeneratorRequest_RequestedFile_ptr new_CodeGeneratorRequest_RequestedFile(struct capn_segment*); +CodeGeneratorRequest_RequestedFile_Import_ptr new_CodeGeneratorRequest_RequestedFile_Import(struct capn_segment*); + +Node_list new_Node_list(struct capn_segment*, int len); +Node_Parameter_list new_Node_Parameter_list(struct capn_segment*, int len); +Node_NestedNode_list new_Node_NestedNode_list(struct capn_segment*, int len); +Field_list new_Field_list(struct capn_segment*, int len); +Enumerant_list new_Enumerant_list(struct capn_segment*, int len); +Superclass_list new_Superclass_list(struct capn_segment*, int len); +Method_list new_Method_list(struct capn_segment*, int len); +Type_list new_Type_list(struct capn_segment*, int len); +Brand_list new_Brand_list(struct capn_segment*, int len); +Brand_Scope_list new_Brand_Scope_list(struct capn_segment*, int len); +Brand_Binding_list new_Brand_Binding_list(struct capn_segment*, int len); +Value_list new_Value_list(struct capn_segment*, int len); +Annotation_list new_Annotation_list(struct capn_segment*, int len); +CodeGeneratorRequest_list new_CodeGeneratorRequest_list(struct capn_segment*, int len); +CodeGeneratorRequest_RequestedFile_list new_CodeGeneratorRequest_RequestedFile_list(struct capn_segment*, int len); +CodeGeneratorRequest_RequestedFile_Import_list new_CodeGeneratorRequest_RequestedFile_Import_list(struct capn_segment*, int len); + +void read_Node(struct Node*, Node_ptr); +void read_Node_Parameter(struct Node_Parameter*, Node_Parameter_ptr); +void read_Node_NestedNode(struct Node_NestedNode*, Node_NestedNode_ptr); +void read_Field(struct Field*, Field_ptr); +void read_Enumerant(struct Enumerant*, Enumerant_ptr); +void read_Superclass(struct Superclass*, Superclass_ptr); +void read_Method(struct Method*, Method_ptr); +void read_Type(struct Type*, Type_ptr); +void read_Brand(struct Brand*, Brand_ptr); +void read_Brand_Scope(struct Brand_Scope*, Brand_Scope_ptr); +void read_Brand_Binding(struct Brand_Binding*, Brand_Binding_ptr); +void read_Value(struct Value*, Value_ptr); +void read_Annotation(struct Annotation*, Annotation_ptr); +void read_CodeGeneratorRequest(struct CodeGeneratorRequest*, CodeGeneratorRequest_ptr); +void read_CodeGeneratorRequest_RequestedFile(struct CodeGeneratorRequest_RequestedFile*, CodeGeneratorRequest_RequestedFile_ptr); +void read_CodeGeneratorRequest_RequestedFile_Import(struct CodeGeneratorRequest_RequestedFile_Import*, CodeGeneratorRequest_RequestedFile_Import_ptr); + +void write_Node(const struct Node*, Node_ptr); +void write_Node_Parameter(const struct Node_Parameter*, Node_Parameter_ptr); +void write_Node_NestedNode(const struct Node_NestedNode*, Node_NestedNode_ptr); +void write_Field(const struct Field*, Field_ptr); +void write_Enumerant(const struct Enumerant*, Enumerant_ptr); +void write_Superclass(const struct Superclass*, Superclass_ptr); +void write_Method(const struct Method*, Method_ptr); +void write_Type(const struct Type*, Type_ptr); +void write_Brand(const struct Brand*, Brand_ptr); +void write_Brand_Scope(const struct Brand_Scope*, Brand_Scope_ptr); +void write_Brand_Binding(const struct Brand_Binding*, Brand_Binding_ptr); +void write_Value(const struct Value*, Value_ptr); +void write_Annotation(const struct Annotation*, Annotation_ptr); +void write_CodeGeneratorRequest(const struct CodeGeneratorRequest*, CodeGeneratorRequest_ptr); +void write_CodeGeneratorRequest_RequestedFile(const struct CodeGeneratorRequest_RequestedFile*, CodeGeneratorRequest_RequestedFile_ptr); +void write_CodeGeneratorRequest_RequestedFile_Import(const struct CodeGeneratorRequest_RequestedFile_Import*, CodeGeneratorRequest_RequestedFile_Import_ptr); + +void get_Node(struct Node*, Node_list, int i); +void get_Node_Parameter(struct Node_Parameter*, Node_Parameter_list, int i); +void get_Node_NestedNode(struct Node_NestedNode*, Node_NestedNode_list, int i); +void get_Field(struct Field*, Field_list, int i); +void get_Enumerant(struct Enumerant*, Enumerant_list, int i); +void get_Superclass(struct Superclass*, Superclass_list, int i); +void get_Method(struct Method*, Method_list, int i); +void get_Type(struct Type*, Type_list, int i); +void get_Brand(struct Brand*, Brand_list, int i); +void get_Brand_Scope(struct Brand_Scope*, Brand_Scope_list, int i); +void get_Brand_Binding(struct Brand_Binding*, Brand_Binding_list, int i); +void get_Value(struct Value*, Value_list, int i); +void get_Annotation(struct Annotation*, Annotation_list, int i); +void get_CodeGeneratorRequest(struct CodeGeneratorRequest*, CodeGeneratorRequest_list, int i); +void get_CodeGeneratorRequest_RequestedFile(struct CodeGeneratorRequest_RequestedFile*, CodeGeneratorRequest_RequestedFile_list, int i); +void get_CodeGeneratorRequest_RequestedFile_Import(struct CodeGeneratorRequest_RequestedFile_Import*, CodeGeneratorRequest_RequestedFile_Import_list, int i); + +void set_Node(const struct Node*, Node_list, int i); +void set_Node_Parameter(const struct Node_Parameter*, Node_Parameter_list, int i); +void set_Node_NestedNode(const struct Node_NestedNode*, Node_NestedNode_list, int i); +void set_Field(const struct Field*, Field_list, int i); +void set_Enumerant(const struct Enumerant*, Enumerant_list, int i); +void set_Superclass(const struct Superclass*, Superclass_list, int i); +void set_Method(const struct Method*, Method_list, int i); +void set_Type(const struct Type*, Type_list, int i); +void set_Brand(const struct Brand*, Brand_list, int i); +void set_Brand_Scope(const struct Brand_Scope*, Brand_Scope_list, int i); +void set_Brand_Binding(const struct Brand_Binding*, Brand_Binding_list, int i); +void set_Value(const struct Value*, Value_list, int i); +void set_Annotation(const struct Annotation*, Annotation_list, int i); +void set_CodeGeneratorRequest(const struct CodeGeneratorRequest*, CodeGeneratorRequest_list, int i); +void set_CodeGeneratorRequest_RequestedFile(const struct CodeGeneratorRequest_RequestedFile*, CodeGeneratorRequest_RequestedFile_list, int i); +void set_CodeGeneratorRequest_RequestedFile_Import(const struct CodeGeneratorRequest_RequestedFile_Import*, CodeGeneratorRequest_RequestedFile_Import_list, int i); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/subprojects/c-capnproto/compiler/str.c b/src/subprojects/c-capnproto/compiler/str.c new file mode 100644 index 00000000..699ec4b0 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/str.c @@ -0,0 +1,112 @@ +/* str.c + * + * Copyright (C) 2013 James McKaskill + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include "str.h" +#include +#include +#include + +#ifndef va_copy +# ifdef _MSC_VER +# define va_copy(d,s) d = s +# elif defined __GNUC__ +# define va_copy(d,s) __builtin_va_copy(d,s) +# else +# error +# endif +#endif + +char str_static[] = "\0"; + +void str_reserve(struct str *v, int sz) { + if (sz < v->cap) + return; + + v->cap = (v->cap * 2) + 16; + if (sz > v->cap) { + v->cap = (sz + 8) & ~7; + } + + if (v->str == str_static) { + v->str = NULL; + } + + v->str = realloc(v->str, v->cap + 1); +} + +void str_add(struct str *v, const char *str, int sz) { + if (sz < 0) + sz = strlen(str); + str_reserve(v, v->len + sz); + memcpy(v->str+v->len, str, sz); + v->len += sz; + v->str[v->len] = '\0'; +} + +int str_vaddf(struct str *v, const char* format, va_list ap) { + str_reserve(v, v->len + 1); + + for (;;) { + int ret; + + char* buf = v->str + v->len; + int bufsz = v->cap - v->len; + + va_list aq; + va_copy(aq, ap); + + /* We initialise buf[bufsz] to \0 to detect when snprintf runs out of + * buffer by seeing whether it overwrites it. + */ + buf[bufsz] = '\0'; + ret = vsnprintf(buf, bufsz + 1, format, aq); + + if (ret > bufsz) { + /* snprintf has told us the size of buffer required (ISO C99 + * behavior) + */ + str_reserve(v, v->len + ret); + + } else if (ret >= 0) { + /* success */ + v->len += ret; + return ret; + + } else if (buf[bufsz] != '\0') { + /* snprintf has returned an error but has written to the end of the + * buffer (MSVC behavior). The buffer is not large enough so grow + * and retry. This can also occur with a format error if it occurs + * right on the boundary, but then we grow the buffer and can + * figure out its an error next time around. + */ + str_reserve(v, v->len + bufsz + 1); + + } else { + /* snprintf has returned an error but has not written to the last + * character in the buffer. We have a format error. + */ + return -1; + } + } +} + + +int str_addf(struct str *v, const char* format, ...) { + va_list ap; + va_start(ap, format); + return str_vaddf(v, format, ap); +} + +char *strf(struct str *v, const char* format, ...) { + va_list ap; + va_start(ap, format); + str_reset(v); + str_vaddf(v, format, ap); + return v->str; +} + diff --git a/src/subprojects/c-capnproto/compiler/str.h b/src/subprojects/c-capnproto/compiler/str.h new file mode 100644 index 00000000..f2763c2f --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/str.h @@ -0,0 +1,61 @@ +/* vim: set sw=8 ts=8 sts=8 noet: */ +/* str.h + * + * Copyright (C) 2013 James McKaskill + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include +#include +#include + +struct str { + char *str; + int len, cap; +}; + +extern char str_static[]; +#define STR_INIT {str_static, 0, 0} + +void str_reserve(struct str *v, int sz); + +static inline void str_init(struct str *v, int sz) { + v->str = str_static; + v->len = v->cap = 0; + if (sz) + str_reserve(v, sz); +} + +static inline void str_release(struct str *v) { + if (v->cap) { + free(v->str); + } +} + +static inline void str_reset(struct str *v) { + if (v->len) { + v->len = 0; + v->str[0] = '\0'; + } +} + +static inline void str_setlen(struct str *v, int sz) { + str_reserve(v, sz); + v->str[sz] = '\0'; + v->len = sz; +} + +#ifdef __GNUC__ +#define ATTR(FMT, ARGS) __attribute__((format(printf,FMT,ARGS))) +#else +#define ATTR(FMT, ARGS) +#endif + +void str_add(struct str *v, const char *str, int sz); +int str_vaddf(struct str *v, const char *format, va_list ap) ATTR(2,0); +int str_addf(struct str *v, const char *format, ...) ATTR(2,3); +char *strf(struct str *v, const char *format, ...) ATTR(2,3); + + diff --git a/src/subprojects/c-capnproto/compiler/test.capnp b/src/subprojects/c-capnproto/compiler/test.capnp new file mode 100644 index 00000000..fbee1f21 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/test.capnp @@ -0,0 +1,661 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xd508eebdc2dc42b8; + +using C = import "c.capnp"; +using Cxx = import "c++.capnp"; + +$C.fieldgetset; + +# Use a namespace likely to cause trouble if the generated code doesn't use fully-qualified +# names for stuff in the capnproto namespace. +$Cxx.namespace("capnproto_test::capnp::test"); + +enum TestEnum { + foo @0; + bar @1; + baz @2; + qux @3; + quux @4; + corge @5; + grault @6; + garply @7; +} + +struct TestAllTypes { + voidField @0 : Void; + boolField @1 : Bool; + int8Field @2 : Int8; + int16Field @3 : Int16; + int32Field @4 : Int32; + int64Field @5 : Int64; + uInt8Field @6 : UInt8; + uInt16Field @7 : UInt16; + uInt32Field @8 : UInt32; + uInt64Field @9 : UInt64; + float32Field @10 : Float32; + float64Field @11 : Float64; + textField @12 : Text; + dataField @13 : Data; + structField @14 : TestAllTypes; + enumField @15 : TestEnum; + interfaceField @16 : Void; # TODO + + voidList @17 : List(Void); + boolList @18 : List(Bool); + int8List @19 : List(Int8); + int16List @20 : List(Int16); + int32List @21 : List(Int32); + int64List @22 : List(Int64); + uInt8List @23 : List(UInt8); + uInt16List @24 : List(UInt16); + uInt32List @25 : List(UInt32); + uInt64List @26 : List(UInt64); + float32List @27 : List(Float32); + float64List @28 : List(Float64); + textList @29 : List(Text); + dataList @30 : List(Data); + structList @31 : List(TestAllTypes); + enumList @32 : List(TestEnum); + interfaceList @33 : List(Void); # TODO +} + +struct TestDefaults { + voidField @0 : Void = void; + boolField @1 : Bool = true; + int8Field @2 : Int8 = -123; + int16Field @3 : Int16 = -12345; + int32Field @4 : Int32 = -12345678; + int64Field @5 : Int64 = -123456789012345; + uInt8Field @6 : UInt8 = 234; + uInt16Field @7 : UInt16 = 45678; + uInt32Field @8 : UInt32 = 3456789012; + uInt64Field @9 : UInt64 = 12345678901234567890; + float32Field @10 : Float32 = 1234.5; + float64Field @11 : Float64 = -123e45; + textField @12 : Text = "foo"; + dataField @13 : Data = 0x"62 61 72"; # "bar" + structField @14 : TestAllTypes = ( + voidField = void, + boolField = true, + int8Field = -12, + int16Field = 3456, + int32Field = -78901234, + int64Field = 56789012345678, + uInt8Field = 90, + uInt16Field = 1234, + uInt32Field = 56789012, + uInt64Field = 345678901234567890, + float32Field = -1.25e-10, + float64Field = 345, + textField = "baz", + dataField = "qux", + structField = ( + textField = "nested", + structField = (textField = "really nested")), + enumField = baz, + # interfaceField can't have a default + + voidList = [void, void, void], + boolList = [false, true, false, true, true], + int8List = [12, -34, -0x80, 0x7f], + int16List = [1234, -5678, -0x8000, 0x7fff], + int32List = [12345678, -90123456, -0x80000000, 0x7fffffff], + int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff], + uInt8List = [12, 34, 0, 0xff], + uInt16List = [1234, 5678, 0, 0xffff], + uInt32List = [12345678, 90123456, 0, 0xffffffff], + uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff], + float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], + float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], + textList = ["quux", "corge", "grault"], + dataList = ["garply", "waldo", "fred"], + structList = [ + (textField = "x structlist 1"), + (textField = "x structlist 2"), + (textField = "x structlist 3")], + enumList = [qux, bar, grault] + # interfaceList can't have a default + ); + enumField @15 : TestEnum = corge; + interfaceField @16 : Void; # TODO + + voidList @17 : List(Void) = [void, void, void, void, void, void]; + boolList @18 : List(Bool) = [true, false, false, true]; + int8List @19 : List(Int8) = [111, -111]; + int16List @20 : List(Int16) = [11111, -11111]; + int32List @21 : List(Int32) = [111111111, -111111111]; + int64List @22 : List(Int64) = [1111111111111111111, -1111111111111111111]; + uInt8List @23 : List(UInt8) = [111, 222] ; + uInt16List @24 : List(UInt16) = [33333, 44444]; + uInt32List @25 : List(UInt32) = [3333333333]; + uInt64List @26 : List(UInt64) = [11111111111111111111]; + float32List @27 : List(Float32) = [5555.5, inf, -inf, nan]; + float64List @28 : List(Float64) = [7777.75, inf, -inf, nan]; + textList @29 : List(Text) = ["plugh", "xyzzy", "thud"]; + dataList @30 : List(Data) = ["oops", "exhausted", "rfc3092"]; + structList @31 : List(TestAllTypes) = [ + (textField = "structlist 1"), + (textField = "structlist 2"), + (textField = "structlist 3")]; + enumList @32 : List(TestEnum) = [foo, garply]; + interfaceList @33 : List(Void); # TODO +} + +struct TestAnyPointer { + anyPointerField @0 :AnyPointer; + + # Do not add any other fields here! Some tests rely on anyPointerField being the last pointer + # in the struct. +} + +struct TestOutOfOrder { + foo @3 :Text; + bar @2 :Text; + baz @8 :Text; + qux @0 :Text; + quux @6 :Text; + corge @4 :Text; + grault @1 :Text; + garply @7 :Text; + waldo @5 :Text; +} + +struct TestUnion { + union0 @0! :union { + # Pack union 0 under ideal conditions: there is no unused padding space prior to it. + u0f0s0 @4: Void; + u0f0s1 @5: Bool; + u0f0s8 @6: Int8; + u0f0s16 @7: Int16; + u0f0s32 @8: Int32; + u0f0s64 @9: Int64; + u0f0sp @10: Text; + + # Pack more stuff into union0 -- should go in same space. + u0f1s0 @11: Void; + u0f1s1 @12: Bool; + u0f1s8 @13: Int8; + u0f1s16 @14: Int16; + u0f1s32 @15: Int32; + u0f1s64 @16: Int64; + u0f1sp @17: Text; + } + + # Pack one bit in order to make pathological situation for union1. + bit0 @18: Bool; + + union1 @1! :union { + # Pack pathologically bad case. Each field takes up new space. + u1f0s0 @19: Void; + u1f0s1 @20: Bool; + u1f1s1 @21: Bool; + u1f0s8 @22: Int8; + u1f1s8 @23: Int8; + u1f0s16 @24: Int16; + u1f1s16 @25: Int16; + u1f0s32 @26: Int32; + u1f1s32 @27: Int32; + u1f0s64 @28: Int64; + u1f1s64 @29: Int64; + u1f0sp @30: Text; + u1f1sp @31: Text; + + # Pack more stuff into union1 -- each should go into the same space as corresponding u1f0s*. + u1f2s0 @32: Void; + u1f2s1 @33: Bool; + u1f2s8 @34: Int8; + u1f2s16 @35: Int16; + u1f2s32 @36: Int32; + u1f2s64 @37: Int64; + u1f2sp @38: Text; + } + + # Fill in the rest of that bitfield from earlier. + bit2 @39: Bool; + bit3 @40: Bool; + bit4 @41: Bool; + bit5 @42: Bool; + bit6 @43: Bool; + bit7 @44: Bool; + + # Interleave two unions to be really annoying. + # Also declare in reverse order to make sure union discriminant values are sorted by field number + # and not by declaration order. + union2 @2! :union { + u2f0s64 @54: Int64; + u2f0s32 @52: Int32; + u2f0s16 @50: Int16; + u2f0s8 @47: Int8; + u2f0s1 @45: Bool; + } + + union3 @3! :union { + u3f0s64 @55: Int64; + u3f0s32 @53: Int32; + u3f0s16 @51: Int16; + u3f0s8 @48: Int8; + u3f0s1 @46: Bool; + } + + byte0 @49: UInt8; +} + +struct TestUnnamedUnion { + before @0 :Text; + + union { + foo @1 :UInt16; + bar @3 :UInt32; + } + + middle @2 :UInt16; + + after @4 :Text; +} + +struct TestUnionInUnion { + # There is no reason to ever do this. + outer :union { + inner :union { + foo @0 :Int32; + bar @1 :Int32; + } + baz @2 :Int32; + } +} + +struct TestGroups { + groups :union { + foo :group { + corge @0 :Int32; + grault @2 :Int64; + garply @8 :Text; + } + bar :group { + corge @3 :Int32; + grault @4 :Text; + garply @5 :Int64; + } + baz :group { + corge @1 :Int32; + grault @6 :Text; + garply @7 :Text; + } + } +} + +struct TestInterleavedGroups { + group1 :group { + foo @0 :UInt32; + bar @2 :UInt64; + union { + qux @4 :UInt16; + corge :group { + grault @6 :UInt64; + garply @8 :UInt16; + plugh @14 :Text; + xyzzy @16 :Text; + } + + fred @12 :Text; + } + + waldo @10 :Text; + } + + group2 :group { + foo @1 :UInt32; + bar @3 :UInt64; + union { + qux @5 :UInt16; + corge :group { + grault @7 :UInt64; + garply @9 :UInt16; + plugh @15 :Text; + xyzzy @17 :Text; + } + + fred @13 :Text; + } + + waldo @11 :Text; + } +} + +struct TestUnionDefaults { + s16s8s64s8Set @0 :TestUnion = + (union0 = (u0f0s16 = 321), union1 = (u1f0s8 = 123), union2 = (u2f0s64 = 12345678901234567), + union3 = (u3f0s8 = 55)); + s0sps1s32Set @1 :TestUnion = + (union0 = (u0f1s0 = void), union1 = (u1f0sp = "foo"), union2 = (u2f0s1 = true), + union3 = (u3f0s32 = 12345678)); + + unnamed1 @2 :TestUnnamedUnion = (foo = 123); + unnamed2 @3 :TestUnnamedUnion = (bar = 321, before = "foo", after = "bar"); +} + +struct TestNestedTypes { + enum NestedEnum { + foo @0; + bar @1; + } + + struct NestedStruct { + enum NestedEnum { + baz @0; + qux @1; + quux @2; + } + + outerNestedEnum @0 :TestNestedTypes.NestedEnum = bar; + innerNestedEnum @1 :NestedEnum = quux; + } + + nestedStruct @0 :NestedStruct; + + outerNestedEnum @1 :NestedEnum = bar; + innerNestedEnum @2 :NestedStruct.NestedEnum = quux; +} + +struct TestUsing { + using OuterNestedEnum = TestNestedTypes.NestedEnum; + using TestNestedTypes.NestedStruct.NestedEnum; + + outerNestedEnum @1 :OuterNestedEnum = bar; + innerNestedEnum @0 :NestedEnum = quux; +} + +struct TestLists { + # Small structs, when encoded as list, will be encoded as primitive lists rather than struct + # lists, to save space. + struct Struct0 { f @0 :Void; } + struct Struct1 { f @0 :Bool; } + struct Struct8 { f @0 :UInt8; } + struct Struct16 { f @0 :UInt16; } + struct Struct32 { f @0 :UInt32; } + struct Struct64 { f @0 :UInt64; } + struct StructP { f @0 :Text; } + + # Versions of the above which cannot be encoded as primitive lists. + struct Struct0c { f @0 :Void; pad @1 :Text; } + struct Struct1c { f @0 :Bool; pad @1 :Text; } + struct Struct8c { f @0 :UInt8; pad @1 :Text; } + struct Struct16c { f @0 :UInt16; pad @1 :Text; } + struct Struct32c { f @0 :UInt32; pad @1 :Text; } + struct Struct64c { f @0 :UInt64; pad @1 :Text; } + struct StructPc { f @0 :Text; pad @1 :UInt64; } + + list0 @0 :List(Struct0); + list1 @1 :List(Struct1); + list8 @2 :List(Struct8); + list16 @3 :List(Struct16); + list32 @4 :List(Struct32); + list64 @5 :List(Struct64); + listP @6 :List(StructP); + + int32ListList @7 :List(List(Int32)); + textListList @8 :List(List(Text)); + structListList @9 :List(List(TestAllTypes)); +} + +struct TestFieldZeroIsBit { + bit @0 :Bool; + secondBit @1 :Bool = true; + thirdField @2 :UInt8 = 123; +} + +struct TestListDefaults { + lists @0 :TestLists = ( + list0 = [(f = void), (f = void)], + list1 = [(f = true), (f = false), (f = true), (f = true)], + list8 = [(f = 123), (f = 45)], + list16 = [(f = 12345), (f = 6789)], + list32 = [(f = 123456789), (f = 234567890)], + list64 = [(f = 1234567890123456), (f = 2345678901234567)], + listP = [(f = "foo"), (f = "bar")], + int32ListList = [[1, 2, 3], [4, 5], [12341234]], + textListList = [["foo", "bar"], ["baz"], ["qux", "corge"]], + structListList = [[(int32Field = 123), (int32Field = 456)], [(int32Field = 789)]]); +} + +struct TestLateUnion { + # Test what happens if the unions are not the first ordinals in the struct. At one point this + # was broken for the dynamic API. + + foo @0 :Int32; + bar @1 :Text; + baz @2 :Int16; + + theUnion @3! :union { + qux @4 :Text; + corge @5 :List(Int32); + grault @6 :Float32; + } + + anotherUnion @7! :union { + qux @8 :Text; + corge @9 :List(Int32); + grault @10 :Float32; + } +} + +struct TestOldVersion { + # A subset of TestNewVersion. + old1 @0 :Int64; + old2 @1 :Text; + old3 @2 :TestOldVersion; +} + +struct TestNewVersion { + # A superset of TestOldVersion. + old1 @0 :Int64; + old2 @1 :Text; + old3 @2 :TestNewVersion; + new1 @3 :Int64 = 987; + new2 @4 :Text = "baz"; +} + +struct TestStructUnion { + un @0! :union { + struct @1 :SomeStruct; + object @2 :TestAnyPointer; + } + + struct SomeStruct { + someText @0 :Text; + moreText @1 :Text; + } +} + +struct TestPrintInlineStructs { + someText @0 :Text; + + structList @1 :List(InlineStruct); + struct InlineStruct { + int32Field @0 :Int32; + textField @1 :Text; + } +} + +struct TestWholeFloatDefault { + # At one point, these failed to compile in C++ because it would produce literals like "123f", + # which is not valid; it needs to be "123.0f". + field @0 :Float32 = 123; + bigField @1 :Float32 = 2e30; + const constant :Float32 = 456; + const bigConstant :Float32 = 4e30; +} + +struct TestEmptyStruct {} + +struct TestConstants { + const voidConst :Void = void; + const boolConst :Bool = true; + const int8Const :Int8 = -123; + const int16Const :Int16 = -12345; + const int32Const :Int32 = -12345678; + const int64Const :Int64 = -123456789012345; + const uint8Const :UInt8 = 234; + const uint16Const :UInt16 = 45678; + const uint32Const :UInt32 = 3456789012; + const uint64Const :UInt64 = 12345678901234567890; + const float32Const :Float32 = 1234.5; + const float64Const :Float64 = -123e45; + const textConst :Text = "foo"; + const dataConst :Data = "bar"; + const structConst :TestAllTypes = ( + voidField = void, + boolField = true, + int8Field = -12, + int16Field = 3456, + int32Field = -78901234, + int64Field = 56789012345678, + uInt8Field = 90, + uInt16Field = 1234, + uInt32Field = 56789012, + uInt64Field = 345678901234567890, + float32Field = -1.25e-10, + float64Field = 345, + textField = "baz", + dataField = "qux", + structField = ( + textField = "nested", + structField = (textField = "really nested")), + enumField = baz, + # interfaceField can't have a default + + voidList = [void, void, void], + boolList = [false, true, false, true, true], + int8List = [12, -34, -0x80, 0x7f], + int16List = [1234, -5678, -0x8000, 0x7fff], + int32List = [12345678, -90123456, -0x80000000, 0x7fffffff], + int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff], + uInt8List = [12, 34, 0, 0xff], + uInt16List = [1234, 5678, 0, 0xffff], + uInt32List = [12345678, 90123456, 0, 0xffffffff], + uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff], + float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], + float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], + textList = ["quux", "corge", "grault"], + dataList = ["garply", "waldo", "fred"], + structList = [ + (textField = "x structlist 1"), + (textField = "x structlist 2"), + (textField = "x structlist 3")], + enumList = [qux, bar, grault] + # interfaceList can't have a default + ); + const enumConst :TestEnum = corge; + + const voidListConst :List(Void) = [void, void, void, void, void, void]; + const boolListConst :List(Bool) = [true, false, false, true]; + const int8ListConst :List(Int8) = [111, -111]; + const int16ListConst :List(Int16) = [11111, -11111]; + const int32ListConst :List(Int32) = [111111111, -111111111]; + const int64ListConst :List(Int64) = [1111111111111111111, -1111111111111111111]; + const uint8ListConst :List(UInt8) = [111, 222] ; + const uint16ListConst :List(UInt16) = [33333, 44444]; + const uint32ListConst :List(UInt32) = [3333333333]; + const uint64ListConst :List(UInt64) = [11111111111111111111]; + const float32ListConst :List(Float32) = [5555.5, inf, -inf, nan]; + const float64ListConst :List(Float64) = [7777.75, inf, -inf, nan]; + const textListConst :List(Text) = ["plugh", "xyzzy", "thud"]; + const dataListConst :List(Data) = ["oops", "exhausted", "rfc3092"]; + const structListConst :List(TestAllTypes) = [ + (textField = "structlist 1"), + (textField = "structlist 2"), + (textField = "structlist 3")]; + const enumListConst :List(TestEnum) = [foo, garply]; +} + +const globalInt :UInt32 = 12345; +const globalText :Text = "foobar"; +const globalStruct :TestAllTypes = (int32Field = 54321); +const globalPrintableStruct :TestPrintInlineStructs = (someText = "foo"); +const derivedConstant :TestAllTypes = ( + uInt32Field = .globalInt, + textField = TestConstants.textConst, + structField = TestConstants.structConst, + int16List = TestConstants.int16ListConst, + structList = TestConstants.structListConst); + +struct TestSturdyRef { + hostId @0 :TestSturdyRefHostId; + objectId @1 :AnyPointer; +} + +struct TestSturdyRefHostId { + host @0 :Text; +} + +struct TestSturdyRefObjectId { + tag @0 :Tag; + enum Tag { + testInterface @0; + testExtends @1; + testPipeline @2; + testTailCallee @3; + testTailCaller @4; + testMoreStuff @5; + } +} + +struct TestProvisionId {} +struct TestRecipientId {} +struct TestThirdPartyCapId {} +struct TestJoinResult {} + +struct TestNameAnnotation $Cxx.name("RenamedStruct") { + union { + badFieldName @0 :Bool $Cxx.name("goodFieldName"); + bar @1 :Int8; + } + + enum BadlyNamedEnum $Cxx.name("RenamedEnum") { + foo @0; + bar @1; + baz @2 $Cxx.name("qux"); + } + + anotherBadFieldName @2 :BadlyNamedEnum $Cxx.name("anotherGoodFieldName"); + + struct NestedStruct $Cxx.name("RenamedNestedStruct") { + badNestedFieldName @0 :Bool $Cxx.name("goodNestedFieldName"); + anotherBadNestedFieldName @1 :NestedStruct $Cxx.name("anotherGoodNestedFieldName"); + + enum DeeplyNestedEnum $Cxx.name("RenamedDeeplyNestedEnum") { + quux @0; + corge @1; + grault @2 $Cxx.name("garply"); + } + } + + badlyNamedUnion :union $Cxx.name("renamedUnion") { + badlyNamedGroup :group $Cxx.name("renamedGroup") { + foo @3 :Void; + bar @4 :Void; + } + baz @5 :NestedStruct $Cxx.name("qux"); + } +} + diff --git a/src/subprojects/c-capnproto/compiler/test.capnp.c b/src/subprojects/c-capnproto/compiler/test.capnp.c new file mode 100644 index 00000000..97a026cb --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/test.capnp.c @@ -0,0 +1,5434 @@ +#include "test.capnp.h" +/* AUTO GENERATED - DO NOT EDIT */ +#ifdef __GNUC__ +# define capnp_unused __attribute__((unused)) +# define capnp_use(x) (void) (x); +#else +# define capnp_unused +# define capnp_use(x) +#endif + +static const capn_text capn_val0 = {0,"",0}; +static const capn_ptr capn_null = {CAPN_NULL}; +static const uint8_t capn_buf[9272] = { + 102,111,111,0,0,0,0,0, + 98,97,114,0,0,0,0,0, + 1,244,128,13,14,16,76,251, + 78,115,232,56,166,51,0,0, + 90,0,210,4,20,136,98,3, + 210,10,111,18,33,25,204,4, + 95,112,9,175,2,0,0,0, + 0,0,0,0,0,144,117,64, + 77,0,0,0,34,0,0,0, + 77,0,0,0,26,0,0,0, + 76,0,0,0,6,0,20,0, + 37,1,0,0,24,0,0,0, + 33,1,0,0,41,0,0,0, + 33,1,0,0,34,0,0,0, + 33,1,0,0,35,0,0,0, + 33,1,0,0,36,0,0,0, + 37,1,0,0,37,0,0,0, + 49,1,0,0,34,0,0,0, + 49,1,0,0,35,0,0,0, + 49,1,0,0,36,0,0,0, + 53,1,0,0,37,0,0,0, + 65,1,0,0,52,0,0,0, + 73,1,0,0,53,0,0,0, + 93,1,0,0,30,0,0,0, + 113,1,0,0,30,0,0,0, + 133,1,0,0,119,2,0,0, + 213,2,0,0,27,0,0,0, + 0,0,0,0,0,0,0,0, + 98,97,122,0,0,0,0,0, + 113,117,120,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 77,0,0,0,58,0,0,0, + 0,0,0,0,0,0,0,0, + 72,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 110,101,115,116,101,100,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 77,0,0,0,114,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 114,101,97,108,108,121,32,110, + 101,115,116,101,100,0,0,0, + 26,0,0,0,0,0,0,0, + 12,222,128,127,0,0,0,0, + 210,4,210,233,0,128,255,127, + 78,97,188,0,64,211,160,250, + 0,0,0,128,255,255,255,127, + 121,223,13,134,72,112,0,0, + 46,117,19,253,138,150,253,255, + 0,0,0,0,0,0,0,128, + 255,255,255,255,255,255,255,127, + 12,34,0,255,0,0,0,0, + 210,4,46,22,0,0,255,255, + 78,97,188,0,192,44,95,5, + 0,0,0,0,255,255,255,255, + 121,223,13,134,72,112,0,0, + 210,138,236,2,117,105,2,0, + 0,0,0,0,0,0,0,0, + 255,255,255,255,255,255,255,255, + 0,0,0,0,56,180,150,73, + 194,189,240,124,194,189,240,252, + 234,28,8,2,234,28,8,130, + 0,0,0,0,0,0,0,0, + 64,222,119,131,33,18,220,66, + 41,144,35,202,229,200,118,127, + 41,144,35,202,229,200,118,255, + 145,247,80,55,158,120,102,0, + 145,247,80,55,158,120,102,128, + 9,0,0,0,42,0,0,0, + 9,0,0,0,50,0,0,0, + 9,0,0,0,58,0,0,0, + 113,117,117,120,0,0,0,0, + 99,111,114,103,101,0,0,0, + 103,114,97,117,108,116,0,0, + 9,0,0,0,50,0,0,0, + 9,0,0,0,42,0,0,0, + 9,0,0,0,34,0,0,0, + 103,97,114,112,108,121,0,0, + 119,97,108,100,111,0,0,0, + 102,114,101,100,0,0,0,0, + 12,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 29,1,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 189,0,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 93,0,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,49,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,50,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,51,0,0, + 3,0,1,0,6,0,0,0, + 9,0,0,0,0,0,0,0, + 111,145,0,0,0,0,0,0, + 103,43,153,212,0,0,0,0, + 199,107,159,6,57,148,96,249, + 199,113,196,43,171,117,107,15, + 57,142,59,212,84,138,148,240, + 111,222,0,0,0,0,0,0, + 53,130,156,173,0,0,0,0, + 85,161,174,198,0,0,0,0, + 199,113,172,181,175,152,50,154, + 0,156,173,69,0,0,128,127, + 0,0,128,255,0,0,192,127, + 0,0,0,0,192,97,190,64, + 0,0,0,0,0,0,240,127, + 0,0,0,0,0,0,240,255, + 0,0,0,0,0,0,248,127, + 9,0,0,0,50,0,0,0, + 9,0,0,0,50,0,0,0, + 9,0,0,0,42,0,0,0, + 112,108,117,103,104,0,0,0, + 120,121,122,122,121,0,0,0, + 116,104,117,100,0,0,0,0, + 9,0,0,0,34,0,0,0, + 9,0,0,0,74,0,0,0, + 13,0,0,0,58,0,0,0, + 111,111,112,115,0,0,0,0, + 101,120,104,97,117,115,116,101, + 100,0,0,0,0,0,0,0, + 114,102,99,51,48,57,50,0, + 12,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 29,1,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 189,0,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 93,0,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,49,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,50,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,51,0,0,0,0, + 0,0,7,0,0,0,0,0, + 102,111,111,98,97,114,0,0, + 0,0,0,0,49,212,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 5,0,0,0,34,0,0,0, + 0,0,0,0,0,0,0,0, + 102,111,111,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,57,48,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 77,0,0,0,34,0,0,0, + 0,0,0,0,0,0,0,0, + 72,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 117,3,0,0,19,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 77,3,0,0,119,2,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 102,111,111,0,0,0,0,0, + 1,244,128,13,14,16,76,251, + 78,115,232,56,166,51,0,0, + 90,0,210,4,20,136,98,3, + 210,10,111,18,33,25,204,4, + 95,112,9,175,2,0,0,0, + 0,0,0,0,0,144,117,64, + 77,0,0,0,34,0,0,0, + 77,0,0,0,26,0,0,0, + 76,0,0,0,6,0,20,0, + 37,1,0,0,24,0,0,0, + 33,1,0,0,41,0,0,0, + 33,1,0,0,34,0,0,0, + 33,1,0,0,35,0,0,0, + 33,1,0,0,36,0,0,0, + 37,1,0,0,37,0,0,0, + 49,1,0,0,34,0,0,0, + 49,1,0,0,35,0,0,0, + 49,1,0,0,36,0,0,0, + 53,1,0,0,37,0,0,0, + 65,1,0,0,52,0,0,0, + 73,1,0,0,53,0,0,0, + 93,1,0,0,30,0,0,0, + 113,1,0,0,30,0,0,0, + 133,1,0,0,119,2,0,0, + 213,2,0,0,27,0,0,0, + 0,0,0,0,0,0,0,0, + 98,97,122,0,0,0,0,0, + 113,117,120,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 77,0,0,0,58,0,0,0, + 0,0,0,0,0,0,0,0, + 72,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 110,101,115,116,101,100,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 77,0,0,0,114,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 114,101,97,108,108,121,32,110, + 101,115,116,101,100,0,0,0, + 26,0,0,0,0,0,0,0, + 12,222,128,127,0,0,0,0, + 210,4,210,233,0,128,255,127, + 78,97,188,0,64,211,160,250, + 0,0,0,128,255,255,255,127, + 121,223,13,134,72,112,0,0, + 46,117,19,253,138,150,253,255, + 0,0,0,0,0,0,0,128, + 255,255,255,255,255,255,255,127, + 12,34,0,255,0,0,0,0, + 210,4,46,22,0,0,255,255, + 78,97,188,0,192,44,95,5, + 0,0,0,0,255,255,255,255, + 121,223,13,134,72,112,0,0, + 210,138,236,2,117,105,2,0, + 0,0,0,0,0,0,0,0, + 255,255,255,255,255,255,255,255, + 0,0,0,0,56,180,150,73, + 194,189,240,124,194,189,240,252, + 234,28,8,2,234,28,8,130, + 0,0,0,0,0,0,0,0, + 64,222,119,131,33,18,220,66, + 41,144,35,202,229,200,118,127, + 41,144,35,202,229,200,118,255, + 145,247,80,55,158,120,102,0, + 145,247,80,55,158,120,102,128, + 9,0,0,0,42,0,0,0, + 9,0,0,0,50,0,0,0, + 9,0,0,0,58,0,0,0, + 113,117,117,120,0,0,0,0, + 99,111,114,103,101,0,0,0, + 103,114,97,117,108,116,0,0, + 9,0,0,0,50,0,0,0, + 9,0,0,0,42,0,0,0, + 9,0,0,0,34,0,0,0, + 103,97,114,112,108,121,0,0, + 119,97,108,100,111,0,0,0, + 102,114,101,100,0,0,0,0, + 12,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 29,1,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 189,0,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 93,0,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,49,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,50,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,51,0,0, + 3,0,1,0,6,0,0,0, + 103,43,153,212,0,0,0,0, + 12,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 29,1,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 189,0,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 93,0,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,49,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,50,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,51,0,0,0,0, + 102,111,111,0,0,0,0,0, + 98,97,114,0,0,0,0,0, + 1,244,128,13,14,16,76,251, + 78,115,232,56,166,51,0,0, + 90,0,210,4,20,136,98,3, + 210,10,111,18,33,25,204,4, + 95,112,9,175,2,0,0,0, + 0,0,0,0,0,144,117,64, + 77,0,0,0,34,0,0,0, + 77,0,0,0,26,0,0,0, + 76,0,0,0,6,0,20,0, + 37,1,0,0,24,0,0,0, + 33,1,0,0,41,0,0,0, + 33,1,0,0,34,0,0,0, + 33,1,0,0,35,0,0,0, + 33,1,0,0,36,0,0,0, + 37,1,0,0,37,0,0,0, + 49,1,0,0,34,0,0,0, + 49,1,0,0,35,0,0,0, + 49,1,0,0,36,0,0,0, + 53,1,0,0,37,0,0,0, + 65,1,0,0,52,0,0,0, + 73,1,0,0,53,0,0,0, + 93,1,0,0,30,0,0,0, + 113,1,0,0,30,0,0,0, + 133,1,0,0,119,2,0,0, + 213,2,0,0,27,0,0,0, + 0,0,0,0,0,0,0,0, + 98,97,122,0,0,0,0,0, + 113,117,120,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 77,0,0,0,58,0,0,0, + 0,0,0,0,0,0,0,0, + 72,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 110,101,115,116,101,100,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 77,0,0,0,114,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 114,101,97,108,108,121,32,110, + 101,115,116,101,100,0,0,0, + 26,0,0,0,0,0,0,0, + 12,222,128,127,0,0,0,0, + 210,4,210,233,0,128,255,127, + 78,97,188,0,64,211,160,250, + 0,0,0,128,255,255,255,127, + 121,223,13,134,72,112,0,0, + 46,117,19,253,138,150,253,255, + 0,0,0,0,0,0,0,128, + 255,255,255,255,255,255,255,127, + 12,34,0,255,0,0,0,0, + 210,4,46,22,0,0,255,255, + 78,97,188,0,192,44,95,5, + 0,0,0,0,255,255,255,255, + 121,223,13,134,72,112,0,0, + 210,138,236,2,117,105,2,0, + 0,0,0,0,0,0,0,0, + 255,255,255,255,255,255,255,255, + 0,0,0,0,56,180,150,73, + 194,189,240,124,194,189,240,252, + 234,28,8,2,234,28,8,130, + 0,0,0,0,0,0,0,0, + 64,222,119,131,33,18,220,66, + 41,144,35,202,229,200,118,127, + 41,144,35,202,229,200,118,255, + 145,247,80,55,158,120,102,0, + 145,247,80,55,158,120,102,128, + 9,0,0,0,42,0,0,0, + 9,0,0,0,50,0,0,0, + 9,0,0,0,58,0,0,0, + 113,117,117,120,0,0,0,0, + 99,111,114,103,101,0,0,0, + 103,114,97,117,108,116,0,0, + 9,0,0,0,50,0,0,0, + 9,0,0,0,42,0,0,0, + 9,0,0,0,34,0,0,0, + 103,97,114,112,108,121,0,0, + 119,97,108,100,111,0,0,0, + 102,114,101,100,0,0,0,0, + 12,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 29,1,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 189,0,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 93,0,0,0,122,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,49,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,50,0,0, + 120,32,115,116,114,117,99,116, + 108,105,115,116,32,51,0,0, + 3,0,1,0,6,0,0,0, + 9,0,0,0,0,0,0,0, + 111,145,0,0,0,0,0,0, + 103,43,153,212,0,0,0,0, + 199,107,159,6,57,148,96,249, + 199,113,196,43,171,117,107,15, + 57,142,59,212,84,138,148,240, + 111,222,0,0,0,0,0,0, + 53,130,156,173,0,0,0,0, + 85,161,174,198,0,0,0,0, + 199,113,172,181,175,152,50,154, + 0,156,173,69,0,0,128,127, + 0,0,128,255,0,0,192,127, + 0,0,0,0,192,97,190,64, + 0,0,0,0,0,0,240,127, + 0,0,0,0,0,0,240,255, + 0,0,0,0,0,0,248,127, + 9,0,0,0,50,0,0,0, + 9,0,0,0,50,0,0,0, + 9,0,0,0,42,0,0,0, + 112,108,117,103,104,0,0,0, + 120,121,122,122,121,0,0,0, + 116,104,117,100,0,0,0,0, + 9,0,0,0,34,0,0,0, + 9,0,0,0,74,0,0,0, + 13,0,0,0,58,0,0,0, + 111,111,112,115,0,0,0,0, + 101,120,104,97,117,115,116,101, + 100,0,0,0,0,0,0,0, + 114,102,99,51,48,57,50,0, + 12,0,0,0,6,0,20,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 29,1,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 189,0,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 93,0,0,0,106,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,49,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,50,0,0,0,0, + 115,116,114,117,99,116,108,105, + 115,116,32,51,0,0,0,0, + 0,0,7,0,0,0,0,0, + 3,0,3,0,4,0,1,0, + 65,1,0,0,0,0,0,0, + 0,123,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,55,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 135,75,107,93,84,220,43,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 7,0,11,0,0,0,3,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 0,0,0,0,78,97,188,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 1,0,0,0,34,0,0,0, + 102,111,111,0,0,0,0,0, + 123,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0, + 65,1,0,0,0,0,0,0, + 5,0,0,0,34,0,0,0, + 5,0,0,0,34,0,0,0, + 102,111,111,0,0,0,0,0, + 98,97,114,0,0,0,0,0, + 37,0,0,0,16,0,0,0, + 33,0,0,0,37,0,0,0, + 45,0,0,0,21,0,0,0, + 49,0,0,0,21,0,0,0, + 53,0,0,0,21,0,0,0, + 57,0,0,0,21,0,0,0, + 61,0,0,0,23,0,0,0, + 77,0,0,0,30,0,0,0, + 101,0,0,0,30,0,0,0, + 149,0,0,0,22,0,0,0, + 1,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, + 123,0,0,0,0,0,0,0, + 45,0,0,0,0,0,0,0, + 57,48,0,0,0,0,0,0, + 133,26,0,0,0,0,0,0, + 21,205,91,7,0,0,0,0, + 210,56,251,13,0,0,0,0, + 192,186,138,60,213,98,4,0, + 135,75,170,237,97,85,8,0, + 8,0,0,0,0,0,1,0, + 5,0,0,0,34,0,0,0, + 5,0,0,0,34,0,0,0, + 102,111,111,0,0,0,0,0, + 98,97,114,0,0,0,0,0, + 9,0,0,0,28,0,0,0, + 13,0,0,0,20,0,0,0, + 13,0,0,0,12,0,0,0, + 1,0,0,0,2,0,0,0, + 3,0,0,0,0,0,0,0, + 4,0,0,0,5,0,0,0, + 242,79,188,0,0,0,0,0, + 9,0,0,0,22,0,0,0, + 21,0,0,0,14,0,0,0, + 25,0,0,0,22,0,0,0, + 5,0,0,0,34,0,0,0, + 5,0,0,0,34,0,0,0, + 102,111,111,0,0,0,0,0, + 98,97,114,0,0,0,0,0, + 1,0,0,0,34,0,0,0, + 98,97,122,0,0,0,0,0, + 5,0,0,0,34,0,0,0, + 5,0,0,0,50,0,0,0, + 113,117,120,0,0,0,0,0, + 99,111,114,103,101,0,0,0, + 5,0,0,0,167,1,0,0, + 213,0,0,0,215,0,0,0, + 8,0,0,0,6,0,20,0, + 0,0,0,0,123,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,200,1,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 4,0,0,0,6,0,20,0, + 0,0,0,0,21,3,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 98,97,122,0,0,0,0,0 +}; +static const struct capn_segment capn_seg = {{0},0,0,0,(char*)&capn_buf[0],9272,9272,0}; +union capn_conv_f32 TestWholeFloatDefault_constant = {0x43e40000u}; +union capn_conv_f32 TestWholeFloatDefault_bigConstant = {0x7249f2cau}; +unsigned TestConstants_boolConst = 1; +int8_t TestConstants_int8Const = -123; +int16_t TestConstants_int16Const = -12345; +int32_t TestConstants_int32Const = -12345678; +int64_t TestConstants_int64Const = ((uint64_t) 0xffff8fb7u << 32) | 0x79f22087u; +uint8_t TestConstants_uint8Const = 234; +uint16_t TestConstants_uint16Const = 45678; +uint32_t TestConstants_uint32Const = 3456789012u; +uint64_t TestConstants_uint64Const = ((uint64_t) 0xab54a98cu << 32) | 0xeb1f0ad2u; +union capn_conv_f32 TestConstants_float32Const = {0x449a5000u}; +union capn_conv_f64 TestConstants_float64Const = {((uint64_t) 0xc9b58b82u << 32) | 0xc0e0bb00u}; +capn_text TestConstants_textConst = {3,(char*)&capn_buf[0],(struct capn_segment*)&capn_seg}; +capn_data TestConstants_dataConst = {{2,0,0,0,1,0,3,(char*)&capn_buf[8],(struct capn_segment*)&capn_seg}}; +TestAllTypes_ptr TestConstants_structConst = {{1,0,0,0,48,20,0,(char*)&capn_buf[16],(struct capn_segment*)&capn_seg}}; +enum TestEnum TestConstants_enumConst = (enum TestEnum) 5u; +capn_ptr TestConstants_voidListConst = {2,0,0,0,0,0,6,(char*)&capn_buf[1672],(struct capn_segment*)&capn_seg}; +capn_list1 TestConstants_boolListConst = {{4,0,0,0,1,0,4,(char*)&capn_buf[1672],(struct capn_segment*)&capn_seg}}; +capn_list8 TestConstants_int8ListConst = {{2,0,0,0,1,0,2,(char*)&capn_buf[1680],(struct capn_segment*)&capn_seg}}; +capn_list16 TestConstants_int16ListConst = {{2,0,0,0,2,0,2,(char*)&capn_buf[1688],(struct capn_segment*)&capn_seg}}; +capn_list32 TestConstants_int32ListConst = {{2,0,0,0,4,0,2,(char*)&capn_buf[1696],(struct capn_segment*)&capn_seg}}; +capn_list64 TestConstants_int64ListConst = {{2,0,0,0,8,0,2,(char*)&capn_buf[1704],(struct capn_segment*)&capn_seg}}; +capn_list8 TestConstants_uint8ListConst = {{2,0,0,0,1,0,2,(char*)&capn_buf[1720],(struct capn_segment*)&capn_seg}}; +capn_list16 TestConstants_uint16ListConst = {{2,0,0,0,2,0,2,(char*)&capn_buf[1728],(struct capn_segment*)&capn_seg}}; +capn_list32 TestConstants_uint32ListConst = {{2,0,0,0,4,0,1,(char*)&capn_buf[1736],(struct capn_segment*)&capn_seg}}; +capn_list64 TestConstants_uint64ListConst = {{2,0,0,0,8,0,1,(char*)&capn_buf[1744],(struct capn_segment*)&capn_seg}}; +capn_list32 TestConstants_float32ListConst = {{2,0,0,0,4,0,4,(char*)&capn_buf[1752],(struct capn_segment*)&capn_seg}}; +capn_list64 TestConstants_float64ListConst = {{2,0,0,0,8,0,4,(char*)&capn_buf[1768],(struct capn_segment*)&capn_seg}}; +capn_ptr TestConstants_textListConst = {3,0,0,0,0,0,3,(char*)&capn_buf[1800],(struct capn_segment*)&capn_seg}; +capn_ptr TestConstants_dataListConst = {3,0,0,0,0,0,3,(char*)&capn_buf[1848],(struct capn_segment*)&capn_seg}; +TestAllTypes_list TestConstants_structListConst = {{2,0,0,1,48,20,3,(char*)&capn_buf[1912],(struct capn_segment*)&capn_seg}}; +capn_list16 TestConstants_enumListConst = {{2,0,0,0,2,0,2,(char*)&capn_buf[2584],(struct capn_segment*)&capn_seg}}; +uint32_t globalInt = 12345u; +capn_text globalText = {6,(char*)&capn_buf[2592],(struct capn_segment*)&capn_seg}; +TestAllTypes_ptr globalStruct = {{1,0,0,0,48,20,0,(char*)&capn_buf[2600],(struct capn_segment*)&capn_seg}}; +TestPrintInlineStructs_ptr globalPrintableStruct = {{1,0,0,0,0,2,0,(char*)&capn_buf[2808],(struct capn_segment*)&capn_seg}}; +TestAllTypes_ptr derivedConstant = {{1,0,0,0,48,20,0,(char*)&capn_buf[2832],(struct capn_segment*)&capn_seg}}; + +TestAllTypes_ptr new_TestAllTypes(struct capn_segment *s) { + TestAllTypes_ptr p; + p.p = capn_new_struct(s, 48, 20); + return p; +} +TestAllTypes_list new_TestAllTypes_list(struct capn_segment *s, int len) { + TestAllTypes_list p; + p.p = capn_new_list(s, len, 48, 20); + return p; +} +void read_TestAllTypes(struct TestAllTypes *s capnp_unused, TestAllTypes_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->boolField = (capn_read8(p.p, 0) & 1) != 0; + s->int8Field = (int8_t) ((int8_t)capn_read8(p.p, 1)); + s->int16Field = (int16_t) ((int16_t)capn_read16(p.p, 2)); + s->int32Field = (int32_t) ((int32_t)capn_read32(p.p, 4)); + s->int64Field = (int64_t) ((int64_t)(capn_read64(p.p, 8))); + s->uInt8Field = capn_read8(p.p, 16); + s->uInt16Field = capn_read16(p.p, 18); + s->uInt32Field = capn_read32(p.p, 20); + s->uInt64Field = capn_read64(p.p, 24); + s->float32Field = capn_to_f32(capn_read32(p.p, 32)); + s->float64Field = capn_to_f64(capn_read64(p.p, 40)); + s->textField = capn_get_text(p.p, 0, capn_val0); + s->dataField = capn_get_data(p.p, 1); + s->structField.p = capn_getp(p.p, 2, 0); + s->enumField = (enum TestEnum)(int) capn_read16(p.p, 36); + s->voidList = capn_getp(p.p, 3, 0); + s->boolList.p = capn_getp(p.p, 4, 0); + s->int8List.p = capn_getp(p.p, 5, 0); + s->int16List.p = capn_getp(p.p, 6, 0); + s->int32List.p = capn_getp(p.p, 7, 0); + s->int64List.p = capn_getp(p.p, 8, 0); + s->uInt8List.p = capn_getp(p.p, 9, 0); + s->uInt16List.p = capn_getp(p.p, 10, 0); + s->uInt32List.p = capn_getp(p.p, 11, 0); + s->uInt64List.p = capn_getp(p.p, 12, 0); + s->float32List.p = capn_getp(p.p, 13, 0); + s->float64List.p = capn_getp(p.p, 14, 0); + s->textList = capn_getp(p.p, 15, 0); + s->dataList = capn_getp(p.p, 16, 0); + s->structList.p = capn_getp(p.p, 17, 0); + s->enumList.p = capn_getp(p.p, 18, 0); + s->interfaceList = capn_getp(p.p, 19, 0); +} +void write_TestAllTypes(const struct TestAllTypes *s capnp_unused, TestAllTypes_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write1(p.p, 0, s->boolField != 0); + capn_write8(p.p, 1, (uint8_t) (s->int8Field)); + capn_write16(p.p, 2, (uint16_t) (s->int16Field)); + capn_write32(p.p, 4, (uint32_t) (s->int32Field)); + capn_write64(p.p, 8, (uint64_t) (s->int64Field)); + capn_write8(p.p, 16, s->uInt8Field); + capn_write16(p.p, 18, s->uInt16Field); + capn_write32(p.p, 20, s->uInt32Field); + capn_write64(p.p, 24, s->uInt64Field); + capn_write32(p.p, 32, capn_from_f32(s->float32Field)); + capn_write64(p.p, 40, capn_from_f64(s->float64Field)); + capn_set_text(p.p, 0, s->textField); + capn_setp(p.p, 1, s->dataField.p); + capn_setp(p.p, 2, s->structField.p); + capn_write16(p.p, 36, (uint16_t) (s->enumField)); + capn_setp(p.p, 3, s->voidList); + capn_setp(p.p, 4, s->boolList.p); + capn_setp(p.p, 5, s->int8List.p); + capn_setp(p.p, 6, s->int16List.p); + capn_setp(p.p, 7, s->int32List.p); + capn_setp(p.p, 8, s->int64List.p); + capn_setp(p.p, 9, s->uInt8List.p); + capn_setp(p.p, 10, s->uInt16List.p); + capn_setp(p.p, 11, s->uInt32List.p); + capn_setp(p.p, 12, s->uInt64List.p); + capn_setp(p.p, 13, s->float32List.p); + capn_setp(p.p, 14, s->float64List.p); + capn_setp(p.p, 15, s->textList); + capn_setp(p.p, 16, s->dataList); + capn_setp(p.p, 17, s->structList.p); + capn_setp(p.p, 18, s->enumList.p); + capn_setp(p.p, 19, s->interfaceList); +} +void get_TestAllTypes(struct TestAllTypes *s, TestAllTypes_list l, int i) { + TestAllTypes_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestAllTypes(s, p); +} +void set_TestAllTypes(const struct TestAllTypes *s, TestAllTypes_list l, int i) { + TestAllTypes_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestAllTypes(s, p); +} + +unsigned TestAllTypes_get_boolField(TestAllTypes_ptr p) +{ + unsigned boolField; + boolField = (capn_read8(p.p, 0) & 1) != 0; + return boolField; +} + +int8_t TestAllTypes_get_int8Field(TestAllTypes_ptr p) +{ + int8_t int8Field; + int8Field = (int8_t) ((int8_t)capn_read8(p.p, 1)); + return int8Field; +} + +int16_t TestAllTypes_get_int16Field(TestAllTypes_ptr p) +{ + int16_t int16Field; + int16Field = (int16_t) ((int16_t)capn_read16(p.p, 2)); + return int16Field; +} + +int32_t TestAllTypes_get_int32Field(TestAllTypes_ptr p) +{ + int32_t int32Field; + int32Field = (int32_t) ((int32_t)capn_read32(p.p, 4)); + return int32Field; +} + +int64_t TestAllTypes_get_int64Field(TestAllTypes_ptr p) +{ + int64_t int64Field; + int64Field = (int64_t) ((int64_t)(capn_read64(p.p, 8))); + return int64Field; +} + +uint8_t TestAllTypes_get_uInt8Field(TestAllTypes_ptr p) +{ + uint8_t uInt8Field; + uInt8Field = capn_read8(p.p, 16); + return uInt8Field; +} + +uint16_t TestAllTypes_get_uInt16Field(TestAllTypes_ptr p) +{ + uint16_t uInt16Field; + uInt16Field = capn_read16(p.p, 18); + return uInt16Field; +} + +uint32_t TestAllTypes_get_uInt32Field(TestAllTypes_ptr p) +{ + uint32_t uInt32Field; + uInt32Field = capn_read32(p.p, 20); + return uInt32Field; +} + +uint64_t TestAllTypes_get_uInt64Field(TestAllTypes_ptr p) +{ + uint64_t uInt64Field; + uInt64Field = capn_read64(p.p, 24); + return uInt64Field; +} + +float TestAllTypes_get_float32Field(TestAllTypes_ptr p) +{ + float float32Field; + float32Field = capn_to_f32(capn_read32(p.p, 32)); + return float32Field; +} + +double TestAllTypes_get_float64Field(TestAllTypes_ptr p) +{ + double float64Field; + float64Field = capn_to_f64(capn_read64(p.p, 40)); + return float64Field; +} + +capn_text TestAllTypes_get_textField(TestAllTypes_ptr p) +{ + capn_text textField; + textField = capn_get_text(p.p, 0, capn_val0); + return textField; +} + +capn_data TestAllTypes_get_dataField(TestAllTypes_ptr p) +{ + capn_data dataField; + dataField = capn_get_data(p.p, 1); + return dataField; +} + +TestAllTypes_ptr TestAllTypes_get_structField(TestAllTypes_ptr p) +{ + TestAllTypes_ptr structField; + structField.p = capn_getp(p.p, 2, 0); + return structField; +} + +enum TestEnum TestAllTypes_get_enumField(TestAllTypes_ptr p) +{ + enum TestEnum enumField; + enumField = (enum TestEnum)(int) capn_read16(p.p, 36); + return enumField; +} + +capn_ptr TestAllTypes_get_voidList(TestAllTypes_ptr p) +{ + capn_ptr voidList; + voidList = capn_getp(p.p, 3, 0); + return voidList; +} + +capn_list1 TestAllTypes_get_boolList(TestAllTypes_ptr p) +{ + capn_list1 boolList; + boolList.p = capn_getp(p.p, 4, 0); + return boolList; +} + +capn_list8 TestAllTypes_get_int8List(TestAllTypes_ptr p) +{ + capn_list8 int8List; + int8List.p = capn_getp(p.p, 5, 0); + return int8List; +} + +capn_list16 TestAllTypes_get_int16List(TestAllTypes_ptr p) +{ + capn_list16 int16List; + int16List.p = capn_getp(p.p, 6, 0); + return int16List; +} + +capn_list32 TestAllTypes_get_int32List(TestAllTypes_ptr p) +{ + capn_list32 int32List; + int32List.p = capn_getp(p.p, 7, 0); + return int32List; +} + +capn_list64 TestAllTypes_get_int64List(TestAllTypes_ptr p) +{ + capn_list64 int64List; + int64List.p = capn_getp(p.p, 8, 0); + return int64List; +} + +capn_list8 TestAllTypes_get_uInt8List(TestAllTypes_ptr p) +{ + capn_list8 uInt8List; + uInt8List.p = capn_getp(p.p, 9, 0); + return uInt8List; +} + +capn_list16 TestAllTypes_get_uInt16List(TestAllTypes_ptr p) +{ + capn_list16 uInt16List; + uInt16List.p = capn_getp(p.p, 10, 0); + return uInt16List; +} + +capn_list32 TestAllTypes_get_uInt32List(TestAllTypes_ptr p) +{ + capn_list32 uInt32List; + uInt32List.p = capn_getp(p.p, 11, 0); + return uInt32List; +} + +capn_list64 TestAllTypes_get_uInt64List(TestAllTypes_ptr p) +{ + capn_list64 uInt64List; + uInt64List.p = capn_getp(p.p, 12, 0); + return uInt64List; +} + +capn_list32 TestAllTypes_get_float32List(TestAllTypes_ptr p) +{ + capn_list32 float32List; + float32List.p = capn_getp(p.p, 13, 0); + return float32List; +} + +capn_list64 TestAllTypes_get_float64List(TestAllTypes_ptr p) +{ + capn_list64 float64List; + float64List.p = capn_getp(p.p, 14, 0); + return float64List; +} + +capn_ptr TestAllTypes_get_textList(TestAllTypes_ptr p) +{ + capn_ptr textList; + textList = capn_getp(p.p, 15, 0); + return textList; +} + +capn_ptr TestAllTypes_get_dataList(TestAllTypes_ptr p) +{ + capn_ptr dataList; + dataList = capn_getp(p.p, 16, 0); + return dataList; +} + +TestAllTypes_list TestAllTypes_get_structList(TestAllTypes_ptr p) +{ + TestAllTypes_list structList; + structList.p = capn_getp(p.p, 17, 0); + return structList; +} + +capn_list16 TestAllTypes_get_enumList(TestAllTypes_ptr p) +{ + capn_list16 enumList; + enumList.p = capn_getp(p.p, 18, 0); + return enumList; +} + +capn_ptr TestAllTypes_get_interfaceList(TestAllTypes_ptr p) +{ + capn_ptr interfaceList; + interfaceList = capn_getp(p.p, 19, 0); + return interfaceList; +} + +void TestAllTypes_set_boolField(TestAllTypes_ptr p, unsigned boolField) +{ + capn_write1(p.p, 0, boolField != 0); +} + +void TestAllTypes_set_int8Field(TestAllTypes_ptr p, int8_t int8Field) +{ + capn_write8(p.p, 1, (uint8_t) (int8Field)); +} + +void TestAllTypes_set_int16Field(TestAllTypes_ptr p, int16_t int16Field) +{ + capn_write16(p.p, 2, (uint16_t) (int16Field)); +} + +void TestAllTypes_set_int32Field(TestAllTypes_ptr p, int32_t int32Field) +{ + capn_write32(p.p, 4, (uint32_t) (int32Field)); +} + +void TestAllTypes_set_int64Field(TestAllTypes_ptr p, int64_t int64Field) +{ + capn_write64(p.p, 8, (uint64_t) (int64Field)); +} + +void TestAllTypes_set_uInt8Field(TestAllTypes_ptr p, uint8_t uInt8Field) +{ + capn_write8(p.p, 16, uInt8Field); +} + +void TestAllTypes_set_uInt16Field(TestAllTypes_ptr p, uint16_t uInt16Field) +{ + capn_write16(p.p, 18, uInt16Field); +} + +void TestAllTypes_set_uInt32Field(TestAllTypes_ptr p, uint32_t uInt32Field) +{ + capn_write32(p.p, 20, uInt32Field); +} + +void TestAllTypes_set_uInt64Field(TestAllTypes_ptr p, uint64_t uInt64Field) +{ + capn_write64(p.p, 24, uInt64Field); +} + +void TestAllTypes_set_float32Field(TestAllTypes_ptr p, float float32Field) +{ + capn_write32(p.p, 32, capn_from_f32(float32Field)); +} + +void TestAllTypes_set_float64Field(TestAllTypes_ptr p, double float64Field) +{ + capn_write64(p.p, 40, capn_from_f64(float64Field)); +} + +void TestAllTypes_set_textField(TestAllTypes_ptr p, capn_text textField) +{ + capn_set_text(p.p, 0, textField); +} + +void TestAllTypes_set_dataField(TestAllTypes_ptr p, capn_data dataField) +{ + capn_setp(p.p, 1, dataField.p); +} + +void TestAllTypes_set_structField(TestAllTypes_ptr p, TestAllTypes_ptr structField) +{ + capn_setp(p.p, 2, structField.p); +} + +void TestAllTypes_set_enumField(TestAllTypes_ptr p, enum TestEnum enumField) +{ + capn_write16(p.p, 36, (uint16_t) (enumField)); +} + +void TestAllTypes_set_voidList(TestAllTypes_ptr p, capn_ptr voidList) +{ + capn_setp(p.p, 3, voidList); +} + +void TestAllTypes_set_boolList(TestAllTypes_ptr p, capn_list1 boolList) +{ + capn_setp(p.p, 4, boolList.p); +} + +void TestAllTypes_set_int8List(TestAllTypes_ptr p, capn_list8 int8List) +{ + capn_setp(p.p, 5, int8List.p); +} + +void TestAllTypes_set_int16List(TestAllTypes_ptr p, capn_list16 int16List) +{ + capn_setp(p.p, 6, int16List.p); +} + +void TestAllTypes_set_int32List(TestAllTypes_ptr p, capn_list32 int32List) +{ + capn_setp(p.p, 7, int32List.p); +} + +void TestAllTypes_set_int64List(TestAllTypes_ptr p, capn_list64 int64List) +{ + capn_setp(p.p, 8, int64List.p); +} + +void TestAllTypes_set_uInt8List(TestAllTypes_ptr p, capn_list8 uInt8List) +{ + capn_setp(p.p, 9, uInt8List.p); +} + +void TestAllTypes_set_uInt16List(TestAllTypes_ptr p, capn_list16 uInt16List) +{ + capn_setp(p.p, 10, uInt16List.p); +} + +void TestAllTypes_set_uInt32List(TestAllTypes_ptr p, capn_list32 uInt32List) +{ + capn_setp(p.p, 11, uInt32List.p); +} + +void TestAllTypes_set_uInt64List(TestAllTypes_ptr p, capn_list64 uInt64List) +{ + capn_setp(p.p, 12, uInt64List.p); +} + +void TestAllTypes_set_float32List(TestAllTypes_ptr p, capn_list32 float32List) +{ + capn_setp(p.p, 13, float32List.p); +} + +void TestAllTypes_set_float64List(TestAllTypes_ptr p, capn_list64 float64List) +{ + capn_setp(p.p, 14, float64List.p); +} + +void TestAllTypes_set_textList(TestAllTypes_ptr p, capn_ptr textList) +{ + capn_setp(p.p, 15, textList); +} + +void TestAllTypes_set_dataList(TestAllTypes_ptr p, capn_ptr dataList) +{ + capn_setp(p.p, 16, dataList); +} + +void TestAllTypes_set_structList(TestAllTypes_ptr p, TestAllTypes_list structList) +{ + capn_setp(p.p, 17, structList.p); +} + +void TestAllTypes_set_enumList(TestAllTypes_ptr p, capn_list16 enumList) +{ + capn_setp(p.p, 18, enumList.p); +} + +void TestAllTypes_set_interfaceList(TestAllTypes_ptr p, capn_ptr interfaceList) +{ + capn_setp(p.p, 19, interfaceList); +} +static capn_text capn_val1 = {3,(char*)&capn_buf[5392],(struct capn_segment*)&capn_seg}; +static capn_data capn_val2 = {{2,0,0,0,1,0,3,(char*)&capn_buf[5400],(struct capn_segment*)&capn_seg}}; +static TestAllTypes_ptr capn_val3 = {{1,0,0,0,48,20,0,(char*)&capn_buf[5408],(struct capn_segment*)&capn_seg}}; +static capn_ptr capn_val4 = {2,0,0,0,0,0,6,(char*)&capn_buf[7064],(struct capn_segment*)&capn_seg}; +static capn_list1 capn_val5 = {{4,0,0,0,1,0,4,(char*)&capn_buf[7064],(struct capn_segment*)&capn_seg}}; +static capn_list8 capn_val6 = {{2,0,0,0,1,0,2,(char*)&capn_buf[7072],(struct capn_segment*)&capn_seg}}; +static capn_list16 capn_val7 = {{2,0,0,0,2,0,2,(char*)&capn_buf[7080],(struct capn_segment*)&capn_seg}}; +static capn_list32 capn_val8 = {{2,0,0,0,4,0,2,(char*)&capn_buf[7088],(struct capn_segment*)&capn_seg}}; +static capn_list64 capn_val9 = {{2,0,0,0,8,0,2,(char*)&capn_buf[7096],(struct capn_segment*)&capn_seg}}; +static capn_list8 capn_val10 = {{2,0,0,0,1,0,2,(char*)&capn_buf[7112],(struct capn_segment*)&capn_seg}}; +static capn_list16 capn_val11 = {{2,0,0,0,2,0,2,(char*)&capn_buf[7120],(struct capn_segment*)&capn_seg}}; +static capn_list32 capn_val12 = {{2,0,0,0,4,0,1,(char*)&capn_buf[7128],(struct capn_segment*)&capn_seg}}; +static capn_list64 capn_val13 = {{2,0,0,0,8,0,1,(char*)&capn_buf[7136],(struct capn_segment*)&capn_seg}}; +static capn_list32 capn_val14 = {{2,0,0,0,4,0,4,(char*)&capn_buf[7144],(struct capn_segment*)&capn_seg}}; +static capn_list64 capn_val15 = {{2,0,0,0,8,0,4,(char*)&capn_buf[7160],(struct capn_segment*)&capn_seg}}; +static capn_ptr capn_val16 = {3,0,0,0,0,0,3,(char*)&capn_buf[7192],(struct capn_segment*)&capn_seg}; +static capn_ptr capn_val17 = {3,0,0,0,0,0,3,(char*)&capn_buf[7240],(struct capn_segment*)&capn_seg}; +static TestAllTypes_list capn_val18 = {{2,0,0,1,48,20,3,(char*)&capn_buf[7304],(struct capn_segment*)&capn_seg}}; +static capn_list16 capn_val19 = {{2,0,0,0,2,0,2,(char*)&capn_buf[7976],(struct capn_segment*)&capn_seg}}; + +TestDefaults_ptr new_TestDefaults(struct capn_segment *s) { + TestDefaults_ptr p; + p.p = capn_new_struct(s, 48, 20); + return p; +} +TestDefaults_list new_TestDefaults_list(struct capn_segment *s, int len) { + TestDefaults_list p; + p.p = capn_new_list(s, len, 48, 20); + return p; +} +void read_TestDefaults(struct TestDefaults *s capnp_unused, TestDefaults_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->boolField = (capn_read8(p.p, 0) & 1) != 1; + s->int8Field = (int8_t) ((int8_t)capn_read8(p.p, 1)) ^ -123; + s->int16Field = (int16_t) ((int16_t)capn_read16(p.p, 2)) ^ -12345; + s->int32Field = (int32_t) ((int32_t)capn_read32(p.p, 4)) ^ -12345678; + s->int64Field = (int64_t) ((int64_t)(capn_read64(p.p, 8)) ^ ((int64_t)((uint64_t) 0xffff8fb7u << 32) ^ 0x79f22087u)); + s->uInt8Field = capn_read8(p.p, 16) ^ 234u; + s->uInt16Field = capn_read16(p.p, 18) ^ 45678u; + s->uInt32Field = capn_read32(p.p, 20) ^ 3456789012u; + s->uInt64Field = capn_read64(p.p, 24) ^ ((uint64_t) 0xab54a98cu << 32) ^ 0xeb1f0ad2u; + s->float32Field = capn_to_f32(capn_read32(p.p, 32) ^ 0x449a5000u); + s->float64Field = capn_to_f64(capn_read64(p.p, 40) ^ ((uint64_t) 0xc9b58b82u << 32) ^ 0xc0e0bb00u); + s->textField = capn_get_text(p.p, 0, capn_val1); + s->dataField = capn_get_data(p.p, 1); + if (!s->dataField.p.type) { + s->dataField = capn_val2; + } + s->structField.p = capn_getp(p.p, 2, 0); + if (!s->structField.p.type) { + s->structField = capn_val3; + } + s->enumField = (enum TestEnum)(int) capn_read16(p.p, 36) ^ 5u; + s->voidList = capn_getp(p.p, 3, 0); + if (!s->voidList.type) { + s->voidList = capn_val4; + } + s->boolList.p = capn_getp(p.p, 4, 0); + if (!s->boolList.p.type) { + s->boolList = capn_val5; + } + s->int8List.p = capn_getp(p.p, 5, 0); + if (!s->int8List.p.type) { + s->int8List = capn_val6; + } + s->int16List.p = capn_getp(p.p, 6, 0); + if (!s->int16List.p.type) { + s->int16List = capn_val7; + } + s->int32List.p = capn_getp(p.p, 7, 0); + if (!s->int32List.p.type) { + s->int32List = capn_val8; + } + s->int64List.p = capn_getp(p.p, 8, 0); + if (!s->int64List.p.type) { + s->int64List = capn_val9; + } + s->uInt8List.p = capn_getp(p.p, 9, 0); + if (!s->uInt8List.p.type) { + s->uInt8List = capn_val10; + } + s->uInt16List.p = capn_getp(p.p, 10, 0); + if (!s->uInt16List.p.type) { + s->uInt16List = capn_val11; + } + s->uInt32List.p = capn_getp(p.p, 11, 0); + if (!s->uInt32List.p.type) { + s->uInt32List = capn_val12; + } + s->uInt64List.p = capn_getp(p.p, 12, 0); + if (!s->uInt64List.p.type) { + s->uInt64List = capn_val13; + } + s->float32List.p = capn_getp(p.p, 13, 0); + if (!s->float32List.p.type) { + s->float32List = capn_val14; + } + s->float64List.p = capn_getp(p.p, 14, 0); + if (!s->float64List.p.type) { + s->float64List = capn_val15; + } + s->textList = capn_getp(p.p, 15, 0); + if (!s->textList.type) { + s->textList = capn_val16; + } + s->dataList = capn_getp(p.p, 16, 0); + if (!s->dataList.type) { + s->dataList = capn_val17; + } + s->structList.p = capn_getp(p.p, 17, 0); + if (!s->structList.p.type) { + s->structList = capn_val18; + } + s->enumList.p = capn_getp(p.p, 18, 0); + if (!s->enumList.p.type) { + s->enumList = capn_val19; + } + s->interfaceList = capn_getp(p.p, 19, 0); +} +void write_TestDefaults(const struct TestDefaults *s capnp_unused, TestDefaults_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write1(p.p, 0, s->boolField != 1); + capn_write8(p.p, 1, (uint8_t) (s->int8Field ^ -123)); + capn_write16(p.p, 2, (uint16_t) (s->int16Field ^ -12345)); + capn_write32(p.p, 4, (uint32_t) (s->int32Field ^ -12345678)); + capn_write64(p.p, 8, (uint64_t) (s->int64Field ^ ((int64_t)((uint64_t) 0xffff8fb7u << 32) ^ 0x79f22087u))); + capn_write8(p.p, 16, s->uInt8Field ^ 234u); + capn_write16(p.p, 18, s->uInt16Field ^ 45678u); + capn_write32(p.p, 20, s->uInt32Field ^ 3456789012u); + capn_write64(p.p, 24, s->uInt64Field ^ ((uint64_t) 0xab54a98cu << 32) ^ 0xeb1f0ad2u); + capn_write32(p.p, 32, capn_from_f32(s->float32Field) ^ 0x449a5000u); + capn_write64(p.p, 40, capn_from_f64(s->float64Field) ^ ((uint64_t) 0xc9b58b82u << 32) ^ 0xc0e0bb00u); + capn_set_text(p.p, 0, (s->textField.str != capn_val1.str) ? s->textField : capn_val0); + capn_setp(p.p, 1, (s->dataField.p.data != capn_val2.p.data) ? s->dataField.p : capn_null); + capn_setp(p.p, 2, (s->structField.p.data != capn_val3.p.data) ? s->structField.p : capn_null); + capn_write16(p.p, 36, (uint16_t) (s->enumField ^ 5u)); + capn_setp(p.p, 3, (s->voidList.data != capn_val4.data) ? s->voidList : capn_null); + capn_setp(p.p, 4, (s->boolList.p.data != capn_val5.p.data) ? s->boolList.p : capn_null); + capn_setp(p.p, 5, (s->int8List.p.data != capn_val6.p.data) ? s->int8List.p : capn_null); + capn_setp(p.p, 6, (s->int16List.p.data != capn_val7.p.data) ? s->int16List.p : capn_null); + capn_setp(p.p, 7, (s->int32List.p.data != capn_val8.p.data) ? s->int32List.p : capn_null); + capn_setp(p.p, 8, (s->int64List.p.data != capn_val9.p.data) ? s->int64List.p : capn_null); + capn_setp(p.p, 9, (s->uInt8List.p.data != capn_val10.p.data) ? s->uInt8List.p : capn_null); + capn_setp(p.p, 10, (s->uInt16List.p.data != capn_val11.p.data) ? s->uInt16List.p : capn_null); + capn_setp(p.p, 11, (s->uInt32List.p.data != capn_val12.p.data) ? s->uInt32List.p : capn_null); + capn_setp(p.p, 12, (s->uInt64List.p.data != capn_val13.p.data) ? s->uInt64List.p : capn_null); + capn_setp(p.p, 13, (s->float32List.p.data != capn_val14.p.data) ? s->float32List.p : capn_null); + capn_setp(p.p, 14, (s->float64List.p.data != capn_val15.p.data) ? s->float64List.p : capn_null); + capn_setp(p.p, 15, (s->textList.data != capn_val16.data) ? s->textList : capn_null); + capn_setp(p.p, 16, (s->dataList.data != capn_val17.data) ? s->dataList : capn_null); + capn_setp(p.p, 17, (s->structList.p.data != capn_val18.p.data) ? s->structList.p : capn_null); + capn_setp(p.p, 18, (s->enumList.p.data != capn_val19.p.data) ? s->enumList.p : capn_null); + capn_setp(p.p, 19, s->interfaceList); +} +void get_TestDefaults(struct TestDefaults *s, TestDefaults_list l, int i) { + TestDefaults_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestDefaults(s, p); +} +void set_TestDefaults(const struct TestDefaults *s, TestDefaults_list l, int i) { + TestDefaults_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestDefaults(s, p); +} + +unsigned TestDefaults_get_boolField(TestDefaults_ptr p) +{ + unsigned boolField; + boolField = (capn_read8(p.p, 0) & 1) != 1; + return boolField; +} + +int8_t TestDefaults_get_int8Field(TestDefaults_ptr p) +{ + int8_t int8Field; + int8Field = (int8_t) ((int8_t)capn_read8(p.p, 1)) ^ -123; + return int8Field; +} + +int16_t TestDefaults_get_int16Field(TestDefaults_ptr p) +{ + int16_t int16Field; + int16Field = (int16_t) ((int16_t)capn_read16(p.p, 2)) ^ -12345; + return int16Field; +} + +int32_t TestDefaults_get_int32Field(TestDefaults_ptr p) +{ + int32_t int32Field; + int32Field = (int32_t) ((int32_t)capn_read32(p.p, 4)) ^ -12345678; + return int32Field; +} + +int64_t TestDefaults_get_int64Field(TestDefaults_ptr p) +{ + int64_t int64Field; + int64Field = (int64_t) ((int64_t)(capn_read64(p.p, 8)) ^ ((int64_t)((uint64_t) 0xffff8fb7u << 32) ^ 0x79f22087u)); + return int64Field; +} + +uint8_t TestDefaults_get_uInt8Field(TestDefaults_ptr p) +{ + uint8_t uInt8Field; + uInt8Field = capn_read8(p.p, 16) ^ 234u; + return uInt8Field; +} + +uint16_t TestDefaults_get_uInt16Field(TestDefaults_ptr p) +{ + uint16_t uInt16Field; + uInt16Field = capn_read16(p.p, 18) ^ 45678u; + return uInt16Field; +} + +uint32_t TestDefaults_get_uInt32Field(TestDefaults_ptr p) +{ + uint32_t uInt32Field; + uInt32Field = capn_read32(p.p, 20) ^ 3456789012u; + return uInt32Field; +} + +uint64_t TestDefaults_get_uInt64Field(TestDefaults_ptr p) +{ + uint64_t uInt64Field; + uInt64Field = capn_read64(p.p, 24) ^ ((uint64_t) 0xab54a98cu << 32) ^ 0xeb1f0ad2u; + return uInt64Field; +} + +float TestDefaults_get_float32Field(TestDefaults_ptr p) +{ + float float32Field; + float32Field = capn_to_f32(capn_read32(p.p, 32) ^ 0x449a5000u); + return float32Field; +} + +double TestDefaults_get_float64Field(TestDefaults_ptr p) +{ + double float64Field; + float64Field = capn_to_f64(capn_read64(p.p, 40) ^ ((uint64_t) 0xc9b58b82u << 32) ^ 0xc0e0bb00u); + return float64Field; +} + +capn_text TestDefaults_get_textField(TestDefaults_ptr p) +{ + capn_text textField; + textField = capn_get_text(p.p, 0, capn_val1); + return textField; +} + +capn_data TestDefaults_get_dataField(TestDefaults_ptr p) +{ + capn_data dataField; + dataField = capn_get_data(p.p, 1); +if (!dataField.p.type) { + dataField = capn_val2; +} + return dataField; +} + +TestAllTypes_ptr TestDefaults_get_structField(TestDefaults_ptr p) +{ + TestAllTypes_ptr structField; + structField.p = capn_getp(p.p, 2, 0); +if (!structField.p.type) { + structField = capn_val3; +} + return structField; +} + +enum TestEnum TestDefaults_get_enumField(TestDefaults_ptr p) +{ + enum TestEnum enumField; + enumField = (enum TestEnum)(int) capn_read16(p.p, 36) ^ 5u; + return enumField; +} + +capn_ptr TestDefaults_get_voidList(TestDefaults_ptr p) +{ + capn_ptr voidList; + voidList = capn_getp(p.p, 3, 0); +if (!voidList.type) { + voidList = capn_val4; +} + return voidList; +} + +capn_list1 TestDefaults_get_boolList(TestDefaults_ptr p) +{ + capn_list1 boolList; + boolList.p = capn_getp(p.p, 4, 0); +if (!boolList.p.type) { + boolList = capn_val5; +} + return boolList; +} + +capn_list8 TestDefaults_get_int8List(TestDefaults_ptr p) +{ + capn_list8 int8List; + int8List.p = capn_getp(p.p, 5, 0); +if (!int8List.p.type) { + int8List = capn_val6; +} + return int8List; +} + +capn_list16 TestDefaults_get_int16List(TestDefaults_ptr p) +{ + capn_list16 int16List; + int16List.p = capn_getp(p.p, 6, 0); +if (!int16List.p.type) { + int16List = capn_val7; +} + return int16List; +} + +capn_list32 TestDefaults_get_int32List(TestDefaults_ptr p) +{ + capn_list32 int32List; + int32List.p = capn_getp(p.p, 7, 0); +if (!int32List.p.type) { + int32List = capn_val8; +} + return int32List; +} + +capn_list64 TestDefaults_get_int64List(TestDefaults_ptr p) +{ + capn_list64 int64List; + int64List.p = capn_getp(p.p, 8, 0); +if (!int64List.p.type) { + int64List = capn_val9; +} + return int64List; +} + +capn_list8 TestDefaults_get_uInt8List(TestDefaults_ptr p) +{ + capn_list8 uInt8List; + uInt8List.p = capn_getp(p.p, 9, 0); +if (!uInt8List.p.type) { + uInt8List = capn_val10; +} + return uInt8List; +} + +capn_list16 TestDefaults_get_uInt16List(TestDefaults_ptr p) +{ + capn_list16 uInt16List; + uInt16List.p = capn_getp(p.p, 10, 0); +if (!uInt16List.p.type) { + uInt16List = capn_val11; +} + return uInt16List; +} + +capn_list32 TestDefaults_get_uInt32List(TestDefaults_ptr p) +{ + capn_list32 uInt32List; + uInt32List.p = capn_getp(p.p, 11, 0); +if (!uInt32List.p.type) { + uInt32List = capn_val12; +} + return uInt32List; +} + +capn_list64 TestDefaults_get_uInt64List(TestDefaults_ptr p) +{ + capn_list64 uInt64List; + uInt64List.p = capn_getp(p.p, 12, 0); +if (!uInt64List.p.type) { + uInt64List = capn_val13; +} + return uInt64List; +} + +capn_list32 TestDefaults_get_float32List(TestDefaults_ptr p) +{ + capn_list32 float32List; + float32List.p = capn_getp(p.p, 13, 0); +if (!float32List.p.type) { + float32List = capn_val14; +} + return float32List; +} + +capn_list64 TestDefaults_get_float64List(TestDefaults_ptr p) +{ + capn_list64 float64List; + float64List.p = capn_getp(p.p, 14, 0); +if (!float64List.p.type) { + float64List = capn_val15; +} + return float64List; +} + +capn_ptr TestDefaults_get_textList(TestDefaults_ptr p) +{ + capn_ptr textList; + textList = capn_getp(p.p, 15, 0); +if (!textList.type) { + textList = capn_val16; +} + return textList; +} + +capn_ptr TestDefaults_get_dataList(TestDefaults_ptr p) +{ + capn_ptr dataList; + dataList = capn_getp(p.p, 16, 0); +if (!dataList.type) { + dataList = capn_val17; +} + return dataList; +} + +TestAllTypes_list TestDefaults_get_structList(TestDefaults_ptr p) +{ + TestAllTypes_list structList; + structList.p = capn_getp(p.p, 17, 0); +if (!structList.p.type) { + structList = capn_val18; +} + return structList; +} + +capn_list16 TestDefaults_get_enumList(TestDefaults_ptr p) +{ + capn_list16 enumList; + enumList.p = capn_getp(p.p, 18, 0); +if (!enumList.p.type) { + enumList = capn_val19; +} + return enumList; +} + +capn_ptr TestDefaults_get_interfaceList(TestDefaults_ptr p) +{ + capn_ptr interfaceList; + interfaceList = capn_getp(p.p, 19, 0); + return interfaceList; +} + +void TestDefaults_set_boolField(TestDefaults_ptr p, unsigned boolField) +{ + capn_write1(p.p, 0, boolField != 1); +} + +void TestDefaults_set_int8Field(TestDefaults_ptr p, int8_t int8Field) +{ + capn_write8(p.p, 1, (uint8_t) (int8Field ^ -123)); +} + +void TestDefaults_set_int16Field(TestDefaults_ptr p, int16_t int16Field) +{ + capn_write16(p.p, 2, (uint16_t) (int16Field ^ -12345)); +} + +void TestDefaults_set_int32Field(TestDefaults_ptr p, int32_t int32Field) +{ + capn_write32(p.p, 4, (uint32_t) (int32Field ^ -12345678)); +} + +void TestDefaults_set_int64Field(TestDefaults_ptr p, int64_t int64Field) +{ + capn_write64(p.p, 8, (uint64_t) (int64Field ^ ((int64_t)((uint64_t) 0xffff8fb7u << 32) ^ 0x79f22087u))); +} + +void TestDefaults_set_uInt8Field(TestDefaults_ptr p, uint8_t uInt8Field) +{ + capn_write8(p.p, 16, uInt8Field ^ 234u); +} + +void TestDefaults_set_uInt16Field(TestDefaults_ptr p, uint16_t uInt16Field) +{ + capn_write16(p.p, 18, uInt16Field ^ 45678u); +} + +void TestDefaults_set_uInt32Field(TestDefaults_ptr p, uint32_t uInt32Field) +{ + capn_write32(p.p, 20, uInt32Field ^ 3456789012u); +} + +void TestDefaults_set_uInt64Field(TestDefaults_ptr p, uint64_t uInt64Field) +{ + capn_write64(p.p, 24, uInt64Field ^ ((uint64_t) 0xab54a98cu << 32) ^ 0xeb1f0ad2u); +} + +void TestDefaults_set_float32Field(TestDefaults_ptr p, float float32Field) +{ + capn_write32(p.p, 32, capn_from_f32(float32Field) ^ 0x449a5000u); +} + +void TestDefaults_set_float64Field(TestDefaults_ptr p, double float64Field) +{ + capn_write64(p.p, 40, capn_from_f64(float64Field) ^ ((uint64_t) 0xc9b58b82u << 32) ^ 0xc0e0bb00u); +} + +void TestDefaults_set_textField(TestDefaults_ptr p, capn_text textField) +{ + capn_set_text(p.p, 0, (textField.str != capn_val1.str) ? textField : capn_val0); +} + +void TestDefaults_set_dataField(TestDefaults_ptr p, capn_data dataField) +{ + capn_setp(p.p, 1, (dataField.p.data != capn_val2.p.data) ? dataField.p : capn_null); +} + +void TestDefaults_set_structField(TestDefaults_ptr p, TestAllTypes_ptr structField) +{ + capn_setp(p.p, 2, (structField.p.data != capn_val3.p.data) ? structField.p : capn_null); +} + +void TestDefaults_set_enumField(TestDefaults_ptr p, enum TestEnum enumField) +{ + capn_write16(p.p, 36, (uint16_t) (enumField ^ 5u)); +} + +void TestDefaults_set_voidList(TestDefaults_ptr p, capn_ptr voidList) +{ + capn_setp(p.p, 3, (voidList.data != capn_val4.data) ? voidList : capn_null); +} + +void TestDefaults_set_boolList(TestDefaults_ptr p, capn_list1 boolList) +{ + capn_setp(p.p, 4, (boolList.p.data != capn_val5.p.data) ? boolList.p : capn_null); +} + +void TestDefaults_set_int8List(TestDefaults_ptr p, capn_list8 int8List) +{ + capn_setp(p.p, 5, (int8List.p.data != capn_val6.p.data) ? int8List.p : capn_null); +} + +void TestDefaults_set_int16List(TestDefaults_ptr p, capn_list16 int16List) +{ + capn_setp(p.p, 6, (int16List.p.data != capn_val7.p.data) ? int16List.p : capn_null); +} + +void TestDefaults_set_int32List(TestDefaults_ptr p, capn_list32 int32List) +{ + capn_setp(p.p, 7, (int32List.p.data != capn_val8.p.data) ? int32List.p : capn_null); +} + +void TestDefaults_set_int64List(TestDefaults_ptr p, capn_list64 int64List) +{ + capn_setp(p.p, 8, (int64List.p.data != capn_val9.p.data) ? int64List.p : capn_null); +} + +void TestDefaults_set_uInt8List(TestDefaults_ptr p, capn_list8 uInt8List) +{ + capn_setp(p.p, 9, (uInt8List.p.data != capn_val10.p.data) ? uInt8List.p : capn_null); +} + +void TestDefaults_set_uInt16List(TestDefaults_ptr p, capn_list16 uInt16List) +{ + capn_setp(p.p, 10, (uInt16List.p.data != capn_val11.p.data) ? uInt16List.p : capn_null); +} + +void TestDefaults_set_uInt32List(TestDefaults_ptr p, capn_list32 uInt32List) +{ + capn_setp(p.p, 11, (uInt32List.p.data != capn_val12.p.data) ? uInt32List.p : capn_null); +} + +void TestDefaults_set_uInt64List(TestDefaults_ptr p, capn_list64 uInt64List) +{ + capn_setp(p.p, 12, (uInt64List.p.data != capn_val13.p.data) ? uInt64List.p : capn_null); +} + +void TestDefaults_set_float32List(TestDefaults_ptr p, capn_list32 float32List) +{ + capn_setp(p.p, 13, (float32List.p.data != capn_val14.p.data) ? float32List.p : capn_null); +} + +void TestDefaults_set_float64List(TestDefaults_ptr p, capn_list64 float64List) +{ + capn_setp(p.p, 14, (float64List.p.data != capn_val15.p.data) ? float64List.p : capn_null); +} + +void TestDefaults_set_textList(TestDefaults_ptr p, capn_ptr textList) +{ + capn_setp(p.p, 15, (textList.data != capn_val16.data) ? textList : capn_null); +} + +void TestDefaults_set_dataList(TestDefaults_ptr p, capn_ptr dataList) +{ + capn_setp(p.p, 16, (dataList.data != capn_val17.data) ? dataList : capn_null); +} + +void TestDefaults_set_structList(TestDefaults_ptr p, TestAllTypes_list structList) +{ + capn_setp(p.p, 17, (structList.p.data != capn_val18.p.data) ? structList.p : capn_null); +} + +void TestDefaults_set_enumList(TestDefaults_ptr p, capn_list16 enumList) +{ + capn_setp(p.p, 18, (enumList.p.data != capn_val19.p.data) ? enumList.p : capn_null); +} + +void TestDefaults_set_interfaceList(TestDefaults_ptr p, capn_ptr interfaceList) +{ + capn_setp(p.p, 19, interfaceList); +} + +TestAnyPointer_ptr new_TestAnyPointer(struct capn_segment *s) { + TestAnyPointer_ptr p; + p.p = capn_new_struct(s, 0, 1); + return p; +} +TestAnyPointer_list new_TestAnyPointer_list(struct capn_segment *s, int len) { + TestAnyPointer_list p; + p.p = capn_new_list(s, len, 0, 1); + return p; +} +void read_TestAnyPointer(struct TestAnyPointer *s capnp_unused, TestAnyPointer_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->anyPointerField = capn_getp(p.p, 0, 0); +} +void write_TestAnyPointer(const struct TestAnyPointer *s capnp_unused, TestAnyPointer_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_setp(p.p, 0, s->anyPointerField); +} +void get_TestAnyPointer(struct TestAnyPointer *s, TestAnyPointer_list l, int i) { + TestAnyPointer_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestAnyPointer(s, p); +} +void set_TestAnyPointer(const struct TestAnyPointer *s, TestAnyPointer_list l, int i) { + TestAnyPointer_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestAnyPointer(s, p); +} + +capn_ptr TestAnyPointer_get_anyPointerField(TestAnyPointer_ptr p) +{ + capn_ptr anyPointerField; + anyPointerField = capn_getp(p.p, 0, 0); + return anyPointerField; +} + +void TestAnyPointer_set_anyPointerField(TestAnyPointer_ptr p, capn_ptr anyPointerField) +{ + capn_setp(p.p, 0, anyPointerField); +} + +TestOutOfOrder_ptr new_TestOutOfOrder(struct capn_segment *s) { + TestOutOfOrder_ptr p; + p.p = capn_new_struct(s, 0, 9); + return p; +} +TestOutOfOrder_list new_TestOutOfOrder_list(struct capn_segment *s, int len) { + TestOutOfOrder_list p; + p.p = capn_new_list(s, len, 0, 9); + return p; +} +void read_TestOutOfOrder(struct TestOutOfOrder *s capnp_unused, TestOutOfOrder_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->foo = capn_get_text(p.p, 3, capn_val0); + s->bar = capn_get_text(p.p, 2, capn_val0); + s->baz = capn_get_text(p.p, 8, capn_val0); + s->qux = capn_get_text(p.p, 0, capn_val0); + s->quux = capn_get_text(p.p, 6, capn_val0); + s->corge = capn_get_text(p.p, 4, capn_val0); + s->grault = capn_get_text(p.p, 1, capn_val0); + s->garply = capn_get_text(p.p, 7, capn_val0); + s->waldo = capn_get_text(p.p, 5, capn_val0); +} +void write_TestOutOfOrder(const struct TestOutOfOrder *s capnp_unused, TestOutOfOrder_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 3, s->foo); + capn_set_text(p.p, 2, s->bar); + capn_set_text(p.p, 8, s->baz); + capn_set_text(p.p, 0, s->qux); + capn_set_text(p.p, 6, s->quux); + capn_set_text(p.p, 4, s->corge); + capn_set_text(p.p, 1, s->grault); + capn_set_text(p.p, 7, s->garply); + capn_set_text(p.p, 5, s->waldo); +} +void get_TestOutOfOrder(struct TestOutOfOrder *s, TestOutOfOrder_list l, int i) { + TestOutOfOrder_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestOutOfOrder(s, p); +} +void set_TestOutOfOrder(const struct TestOutOfOrder *s, TestOutOfOrder_list l, int i) { + TestOutOfOrder_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestOutOfOrder(s, p); +} + +capn_text TestOutOfOrder_get_foo(TestOutOfOrder_ptr p) +{ + capn_text foo; + foo = capn_get_text(p.p, 3, capn_val0); + return foo; +} + +capn_text TestOutOfOrder_get_bar(TestOutOfOrder_ptr p) +{ + capn_text bar; + bar = capn_get_text(p.p, 2, capn_val0); + return bar; +} + +capn_text TestOutOfOrder_get_baz(TestOutOfOrder_ptr p) +{ + capn_text baz; + baz = capn_get_text(p.p, 8, capn_val0); + return baz; +} + +capn_text TestOutOfOrder_get_qux(TestOutOfOrder_ptr p) +{ + capn_text qux; + qux = capn_get_text(p.p, 0, capn_val0); + return qux; +} + +capn_text TestOutOfOrder_get_quux(TestOutOfOrder_ptr p) +{ + capn_text quux; + quux = capn_get_text(p.p, 6, capn_val0); + return quux; +} + +capn_text TestOutOfOrder_get_corge(TestOutOfOrder_ptr p) +{ + capn_text corge; + corge = capn_get_text(p.p, 4, capn_val0); + return corge; +} + +capn_text TestOutOfOrder_get_grault(TestOutOfOrder_ptr p) +{ + capn_text grault; + grault = capn_get_text(p.p, 1, capn_val0); + return grault; +} + +capn_text TestOutOfOrder_get_garply(TestOutOfOrder_ptr p) +{ + capn_text garply; + garply = capn_get_text(p.p, 7, capn_val0); + return garply; +} + +capn_text TestOutOfOrder_get_waldo(TestOutOfOrder_ptr p) +{ + capn_text waldo; + waldo = capn_get_text(p.p, 5, capn_val0); + return waldo; +} + +void TestOutOfOrder_set_foo(TestOutOfOrder_ptr p, capn_text foo) +{ + capn_set_text(p.p, 3, foo); +} + +void TestOutOfOrder_set_bar(TestOutOfOrder_ptr p, capn_text bar) +{ + capn_set_text(p.p, 2, bar); +} + +void TestOutOfOrder_set_baz(TestOutOfOrder_ptr p, capn_text baz) +{ + capn_set_text(p.p, 8, baz); +} + +void TestOutOfOrder_set_qux(TestOutOfOrder_ptr p, capn_text qux) +{ + capn_set_text(p.p, 0, qux); +} + +void TestOutOfOrder_set_quux(TestOutOfOrder_ptr p, capn_text quux) +{ + capn_set_text(p.p, 6, quux); +} + +void TestOutOfOrder_set_corge(TestOutOfOrder_ptr p, capn_text corge) +{ + capn_set_text(p.p, 4, corge); +} + +void TestOutOfOrder_set_grault(TestOutOfOrder_ptr p, capn_text grault) +{ + capn_set_text(p.p, 1, grault); +} + +void TestOutOfOrder_set_garply(TestOutOfOrder_ptr p, capn_text garply) +{ + capn_set_text(p.p, 7, garply); +} + +void TestOutOfOrder_set_waldo(TestOutOfOrder_ptr p, capn_text waldo) +{ + capn_set_text(p.p, 5, waldo); +} + +TestUnion_ptr new_TestUnion(struct capn_segment *s) { + TestUnion_ptr p; + p.p = capn_new_struct(s, 64, 2); + return p; +} +TestUnion_list new_TestUnion_list(struct capn_segment *s, int len) { + TestUnion_list p; + p.p = capn_new_list(s, len, 64, 2); + return p; +} +void read_TestUnion(struct TestUnion *s capnp_unused, TestUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->union0_which = (enum TestUnion_union0_which)(int) capn_read16(p.p, 0); + switch (s->union0_which) { + case TestUnion_union0_u0f0s1: + case TestUnion_union0_u0f1s1: + s->union0.u0f1s1 = (capn_read8(p.p, 8) & 1) != 0; + break; + case TestUnion_union0_u0f0s8: + case TestUnion_union0_u0f1s8: + s->union0.u0f1s8 = (int8_t) ((int8_t)capn_read8(p.p, 8)); + break; + case TestUnion_union0_u0f0s16: + case TestUnion_union0_u0f1s16: + s->union0.u0f1s16 = (int16_t) ((int16_t)capn_read16(p.p, 8)); + break; + case TestUnion_union0_u0f0s32: + case TestUnion_union0_u0f1s32: + s->union0.u0f1s32 = (int32_t) ((int32_t)capn_read32(p.p, 8)); + break; + case TestUnion_union0_u0f0s64: + case TestUnion_union0_u0f1s64: + s->union0.u0f1s64 = (int64_t) ((int64_t)(capn_read64(p.p, 8))); + break; + case TestUnion_union0_u0f0sp: + case TestUnion_union0_u0f1sp: + s->union0.u0f1sp = capn_get_text(p.p, 0, capn_val0); + break; + default: + break; + } + s->bit0 = (capn_read8(p.p, 16) & 1) != 0; + s->union1_which = (enum TestUnion_union1_which)(int) capn_read16(p.p, 2); + switch (s->union1_which) { + case TestUnion_union1_u1f0s1: + case TestUnion_union1_u1f1s1: + case TestUnion_union1_u1f2s1: + s->union1.u1f2s1 = (capn_read8(p.p, 16) & 2) != 0; + break; + case TestUnion_union1_u1f0s8: + case TestUnion_union1_u1f1s8: + case TestUnion_union1_u1f2s8: + s->union1.u1f2s8 = (int8_t) ((int8_t)capn_read8(p.p, 17)); + break; + case TestUnion_union1_u1f0s16: + case TestUnion_union1_u1f1s16: + case TestUnion_union1_u1f2s16: + s->union1.u1f2s16 = (int16_t) ((int16_t)capn_read16(p.p, 18)); + break; + case TestUnion_union1_u1f0s32: + case TestUnion_union1_u1f1s32: + case TestUnion_union1_u1f2s32: + s->union1.u1f2s32 = (int32_t) ((int32_t)capn_read32(p.p, 20)); + break; + case TestUnion_union1_u1f0s64: + case TestUnion_union1_u1f1s64: + case TestUnion_union1_u1f2s64: + s->union1.u1f2s64 = (int64_t) ((int64_t)(capn_read64(p.p, 24))); + break; + case TestUnion_union1_u1f0sp: + case TestUnion_union1_u1f1sp: + case TestUnion_union1_u1f2sp: + s->union1.u1f2sp = capn_get_text(p.p, 1, capn_val0); + break; + default: + break; + } + s->bit2 = (capn_read8(p.p, 16) & 4) != 0; + s->bit3 = (capn_read8(p.p, 16) & 8) != 0; + s->bit4 = (capn_read8(p.p, 16) & 16) != 0; + s->bit5 = (capn_read8(p.p, 16) & 32) != 0; + s->bit6 = (capn_read8(p.p, 16) & 64) != 0; + s->bit7 = (capn_read8(p.p, 16) & 128) != 0; + s->union2_which = (enum TestUnion_union2_which)(int) capn_read16(p.p, 4); + switch (s->union2_which) { + case TestUnion_union2_u2f0s1: + s->union2.u2f0s1 = (capn_read8(p.p, 32) & 1) != 0; + break; + case TestUnion_union2_u2f0s8: + s->union2.u2f0s8 = (int8_t) ((int8_t)capn_read8(p.p, 33)); + break; + case TestUnion_union2_u2f0s16: + s->union2.u2f0s16 = (int16_t) ((int16_t)capn_read16(p.p, 36)); + break; + case TestUnion_union2_u2f0s32: + s->union2.u2f0s32 = (int32_t) ((int32_t)capn_read32(p.p, 40)); + break; + case TestUnion_union2_u2f0s64: + s->union2.u2f0s64 = (int64_t) ((int64_t)(capn_read64(p.p, 48))); + break; + default: + break; + } + s->union3_which = (enum TestUnion_union3_which)(int) capn_read16(p.p, 6); + switch (s->union3_which) { + case TestUnion_union3_u3f0s1: + s->union3.u3f0s1 = (capn_read8(p.p, 32) & 2) != 0; + break; + case TestUnion_union3_u3f0s8: + s->union3.u3f0s8 = (int8_t) ((int8_t)capn_read8(p.p, 34)); + break; + case TestUnion_union3_u3f0s16: + s->union3.u3f0s16 = (int16_t) ((int16_t)capn_read16(p.p, 38)); + break; + case TestUnion_union3_u3f0s32: + s->union3.u3f0s32 = (int32_t) ((int32_t)capn_read32(p.p, 44)); + break; + case TestUnion_union3_u3f0s64: + s->union3.u3f0s64 = (int64_t) ((int64_t)(capn_read64(p.p, 56))); + break; + default: + break; + } + s->byte0 = capn_read8(p.p, 35); +} +void write_TestUnion(const struct TestUnion *s capnp_unused, TestUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, s->union0_which); + switch (s->union0_which) { + case TestUnion_union0_u0f0s1: + case TestUnion_union0_u0f1s1: + capn_write1(p.p, 64, s->union0.u0f1s1 != 0); + break; + case TestUnion_union0_u0f0s8: + case TestUnion_union0_u0f1s8: + capn_write8(p.p, 8, (uint8_t) (s->union0.u0f1s8)); + break; + case TestUnion_union0_u0f0s16: + case TestUnion_union0_u0f1s16: + capn_write16(p.p, 8, (uint16_t) (s->union0.u0f1s16)); + break; + case TestUnion_union0_u0f0s32: + case TestUnion_union0_u0f1s32: + capn_write32(p.p, 8, (uint32_t) (s->union0.u0f1s32)); + break; + case TestUnion_union0_u0f0s64: + case TestUnion_union0_u0f1s64: + capn_write64(p.p, 8, (uint64_t) (s->union0.u0f1s64)); + break; + case TestUnion_union0_u0f0sp: + case TestUnion_union0_u0f1sp: + capn_set_text(p.p, 0, s->union0.u0f1sp); + break; + default: + break; + } + capn_write1(p.p, 128, s->bit0 != 0); + capn_write16(p.p, 2, s->union1_which); + switch (s->union1_which) { + case TestUnion_union1_u1f0s1: + case TestUnion_union1_u1f1s1: + case TestUnion_union1_u1f2s1: + capn_write1(p.p, 129, s->union1.u1f2s1 != 0); + break; + case TestUnion_union1_u1f0s8: + case TestUnion_union1_u1f1s8: + case TestUnion_union1_u1f2s8: + capn_write8(p.p, 17, (uint8_t) (s->union1.u1f2s8)); + break; + case TestUnion_union1_u1f0s16: + case TestUnion_union1_u1f1s16: + case TestUnion_union1_u1f2s16: + capn_write16(p.p, 18, (uint16_t) (s->union1.u1f2s16)); + break; + case TestUnion_union1_u1f0s32: + case TestUnion_union1_u1f1s32: + case TestUnion_union1_u1f2s32: + capn_write32(p.p, 20, (uint32_t) (s->union1.u1f2s32)); + break; + case TestUnion_union1_u1f0s64: + case TestUnion_union1_u1f1s64: + case TestUnion_union1_u1f2s64: + capn_write64(p.p, 24, (uint64_t) (s->union1.u1f2s64)); + break; + case TestUnion_union1_u1f0sp: + case TestUnion_union1_u1f1sp: + case TestUnion_union1_u1f2sp: + capn_set_text(p.p, 1, s->union1.u1f2sp); + break; + default: + break; + } + capn_write1(p.p, 130, s->bit2 != 0); + capn_write1(p.p, 131, s->bit3 != 0); + capn_write1(p.p, 132, s->bit4 != 0); + capn_write1(p.p, 133, s->bit5 != 0); + capn_write1(p.p, 134, s->bit6 != 0); + capn_write1(p.p, 135, s->bit7 != 0); + capn_write16(p.p, 4, s->union2_which); + switch (s->union2_which) { + case TestUnion_union2_u2f0s1: + capn_write1(p.p, 256, s->union2.u2f0s1 != 0); + break; + case TestUnion_union2_u2f0s8: + capn_write8(p.p, 33, (uint8_t) (s->union2.u2f0s8)); + break; + case TestUnion_union2_u2f0s16: + capn_write16(p.p, 36, (uint16_t) (s->union2.u2f0s16)); + break; + case TestUnion_union2_u2f0s32: + capn_write32(p.p, 40, (uint32_t) (s->union2.u2f0s32)); + break; + case TestUnion_union2_u2f0s64: + capn_write64(p.p, 48, (uint64_t) (s->union2.u2f0s64)); + break; + default: + break; + } + capn_write16(p.p, 6, s->union3_which); + switch (s->union3_which) { + case TestUnion_union3_u3f0s1: + capn_write1(p.p, 257, s->union3.u3f0s1 != 0); + break; + case TestUnion_union3_u3f0s8: + capn_write8(p.p, 34, (uint8_t) (s->union3.u3f0s8)); + break; + case TestUnion_union3_u3f0s16: + capn_write16(p.p, 38, (uint16_t) (s->union3.u3f0s16)); + break; + case TestUnion_union3_u3f0s32: + capn_write32(p.p, 44, (uint32_t) (s->union3.u3f0s32)); + break; + case TestUnion_union3_u3f0s64: + capn_write64(p.p, 56, (uint64_t) (s->union3.u3f0s64)); + break; + default: + break; + } + capn_write8(p.p, 35, s->byte0); +} +void get_TestUnion(struct TestUnion *s, TestUnion_list l, int i) { + TestUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestUnion(s, p); +} +void set_TestUnion(const struct TestUnion *s, TestUnion_list l, int i) { + TestUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestUnion(s, p); +} + +unsigned TestUnion_get_bit0(TestUnion_ptr p) +{ + unsigned bit0; + bit0 = (capn_read8(p.p, 16) & 1) != 0; + return bit0; +} + +unsigned TestUnion_get_bit2(TestUnion_ptr p) +{ + unsigned bit2; + bit2 = (capn_read8(p.p, 16) & 4) != 0; + return bit2; +} + +unsigned TestUnion_get_bit3(TestUnion_ptr p) +{ + unsigned bit3; + bit3 = (capn_read8(p.p, 16) & 8) != 0; + return bit3; +} + +unsigned TestUnion_get_bit4(TestUnion_ptr p) +{ + unsigned bit4; + bit4 = (capn_read8(p.p, 16) & 16) != 0; + return bit4; +} + +unsigned TestUnion_get_bit5(TestUnion_ptr p) +{ + unsigned bit5; + bit5 = (capn_read8(p.p, 16) & 32) != 0; + return bit5; +} + +unsigned TestUnion_get_bit6(TestUnion_ptr p) +{ + unsigned bit6; + bit6 = (capn_read8(p.p, 16) & 64) != 0; + return bit6; +} + +unsigned TestUnion_get_bit7(TestUnion_ptr p) +{ + unsigned bit7; + bit7 = (capn_read8(p.p, 16) & 128) != 0; + return bit7; +} + +uint8_t TestUnion_get_byte0(TestUnion_ptr p) +{ + uint8_t byte0; + byte0 = capn_read8(p.p, 35); + return byte0; +} + +void TestUnion_set_bit0(TestUnion_ptr p, unsigned bit0) +{ + capn_write1(p.p, 128, bit0 != 0); +} + +void TestUnion_set_bit2(TestUnion_ptr p, unsigned bit2) +{ + capn_write1(p.p, 130, bit2 != 0); +} + +void TestUnion_set_bit3(TestUnion_ptr p, unsigned bit3) +{ + capn_write1(p.p, 131, bit3 != 0); +} + +void TestUnion_set_bit4(TestUnion_ptr p, unsigned bit4) +{ + capn_write1(p.p, 132, bit4 != 0); +} + +void TestUnion_set_bit5(TestUnion_ptr p, unsigned bit5) +{ + capn_write1(p.p, 133, bit5 != 0); +} + +void TestUnion_set_bit6(TestUnion_ptr p, unsigned bit6) +{ + capn_write1(p.p, 134, bit6 != 0); +} + +void TestUnion_set_bit7(TestUnion_ptr p, unsigned bit7) +{ + capn_write1(p.p, 135, bit7 != 0); +} + +void TestUnion_set_byte0(TestUnion_ptr p, uint8_t byte0) +{ + capn_write8(p.p, 35, byte0); +} + +TestUnnamedUnion_ptr new_TestUnnamedUnion(struct capn_segment *s) { + TestUnnamedUnion_ptr p; + p.p = capn_new_struct(s, 16, 2); + return p; +} +TestUnnamedUnion_list new_TestUnnamedUnion_list(struct capn_segment *s, int len) { + TestUnnamedUnion_list p; + p.p = capn_new_list(s, len, 16, 2); + return p; +} +void read_TestUnnamedUnion(struct TestUnnamedUnion *s capnp_unused, TestUnnamedUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->before = capn_get_text(p.p, 0, capn_val0); + s->which = (enum TestUnnamedUnion_which)(int) capn_read16(p.p, 4); + switch (s->which) { + case TestUnnamedUnion_foo: + s->foo = capn_read16(p.p, 0); + break; + case TestUnnamedUnion_bar: + s->bar = capn_read32(p.p, 8); + break; + default: + break; + } + s->middle = capn_read16(p.p, 2); + s->after = capn_get_text(p.p, 1, capn_val0); +} +void write_TestUnnamedUnion(const struct TestUnnamedUnion *s capnp_unused, TestUnnamedUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->before); + capn_write16(p.p, 4, s->which); + switch (s->which) { + case TestUnnamedUnion_foo: + capn_write16(p.p, 0, s->foo); + break; + case TestUnnamedUnion_bar: + capn_write32(p.p, 8, s->bar); + break; + default: + break; + } + capn_write16(p.p, 2, s->middle); + capn_set_text(p.p, 1, s->after); +} +void get_TestUnnamedUnion(struct TestUnnamedUnion *s, TestUnnamedUnion_list l, int i) { + TestUnnamedUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestUnnamedUnion(s, p); +} +void set_TestUnnamedUnion(const struct TestUnnamedUnion *s, TestUnnamedUnion_list l, int i) { + TestUnnamedUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestUnnamedUnion(s, p); +} + +capn_text TestUnnamedUnion_get_before(TestUnnamedUnion_ptr p) +{ + capn_text before; + before = capn_get_text(p.p, 0, capn_val0); + return before; +} + +void TestUnnamedUnion_set_before(TestUnnamedUnion_ptr p, capn_text before) +{ + capn_set_text(p.p, 0, before); +} + +TestUnionInUnion_ptr new_TestUnionInUnion(struct capn_segment *s) { + TestUnionInUnion_ptr p; + p.p = capn_new_struct(s, 16, 0); + return p; +} +TestUnionInUnion_list new_TestUnionInUnion_list(struct capn_segment *s, int len) { + TestUnionInUnion_list p; + p.p = capn_new_list(s, len, 16, 0); + return p; +} +void read_TestUnionInUnion(struct TestUnionInUnion *s capnp_unused, TestUnionInUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->outer_which = (enum TestUnionInUnion_outer_which)(int) capn_read16(p.p, 8); + switch (s->outer_which) { + case TestUnionInUnion_outer_baz: + s->outer.baz = (int32_t) ((int32_t)capn_read32(p.p, 0)); + break; + case TestUnionInUnion_outer_inner: + s->outer.inner.which = (enum TestUnionInUnion_outer_inner_which)(int) capn_read16(p.p, 4); + switch (s->outer.inner.which) { + case TestUnionInUnion_outer_inner_foo: + case TestUnionInUnion_outer_inner_bar: + s->outer.inner.bar = (int32_t) ((int32_t)capn_read32(p.p, 0)); + break; + default: + break; + } + break; + default: + break; + } +} +void write_TestUnionInUnion(const struct TestUnionInUnion *s capnp_unused, TestUnionInUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 8, s->outer_which); + switch (s->outer_which) { + case TestUnionInUnion_outer_baz: + capn_write32(p.p, 0, (uint32_t) (s->outer.baz)); + break; + case TestUnionInUnion_outer_inner: + capn_write16(p.p, 4, s->outer.inner.which); + switch (s->outer.inner.which) { + case TestUnionInUnion_outer_inner_foo: + case TestUnionInUnion_outer_inner_bar: + capn_write32(p.p, 0, (uint32_t) (s->outer.inner.bar)); + break; + default: + break; + } + break; + default: + break; + } +} +void get_TestUnionInUnion(struct TestUnionInUnion *s, TestUnionInUnion_list l, int i) { + TestUnionInUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestUnionInUnion(s, p); +} +void set_TestUnionInUnion(const struct TestUnionInUnion *s, TestUnionInUnion_list l, int i) { + TestUnionInUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestUnionInUnion(s, p); +} + +TestGroups_ptr new_TestGroups(struct capn_segment *s) { + TestGroups_ptr p; + p.p = capn_new_struct(s, 16, 2); + return p; +} +TestGroups_list new_TestGroups_list(struct capn_segment *s, int len) { + TestGroups_list p; + p.p = capn_new_list(s, len, 16, 2); + return p; +} +void read_TestGroups(struct TestGroups *s capnp_unused, TestGroups_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->groups_which = (enum TestGroups_groups_which)(int) capn_read16(p.p, 4); + switch (s->groups_which) { + case TestGroups_groups_foo: + s->groups.foo.corge = (int32_t) ((int32_t)capn_read32(p.p, 0)); + s->groups.foo.grault = (int64_t) ((int64_t)(capn_read64(p.p, 8))); + s->groups.foo.garply = capn_get_text(p.p, 0, capn_val0); + break; + case TestGroups_groups_bar: + s->groups.bar.corge = (int32_t) ((int32_t)capn_read32(p.p, 0)); + s->groups.bar.grault = capn_get_text(p.p, 0, capn_val0); + s->groups.bar.garply = (int64_t) ((int64_t)(capn_read64(p.p, 8))); + break; + case TestGroups_groups_baz: + s->groups.baz.corge = (int32_t) ((int32_t)capn_read32(p.p, 0)); + s->groups.baz.grault = capn_get_text(p.p, 0, capn_val0); + s->groups.baz.garply = capn_get_text(p.p, 1, capn_val0); + break; + default: + break; + } +} +void write_TestGroups(const struct TestGroups *s capnp_unused, TestGroups_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 4, s->groups_which); + switch (s->groups_which) { + case TestGroups_groups_foo: + capn_write32(p.p, 0, (uint32_t) (s->groups.foo.corge)); + capn_write64(p.p, 8, (uint64_t) (s->groups.foo.grault)); + capn_set_text(p.p, 0, s->groups.foo.garply); + break; + case TestGroups_groups_bar: + capn_write32(p.p, 0, (uint32_t) (s->groups.bar.corge)); + capn_set_text(p.p, 0, s->groups.bar.grault); + capn_write64(p.p, 8, (uint64_t) (s->groups.bar.garply)); + break; + case TestGroups_groups_baz: + capn_write32(p.p, 0, (uint32_t) (s->groups.baz.corge)); + capn_set_text(p.p, 0, s->groups.baz.grault); + capn_set_text(p.p, 1, s->groups.baz.garply); + break; + default: + break; + } +} +void get_TestGroups(struct TestGroups *s, TestGroups_list l, int i) { + TestGroups_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestGroups(s, p); +} +void set_TestGroups(const struct TestGroups *s, TestGroups_list l, int i) { + TestGroups_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestGroups(s, p); +} + +TestInterleavedGroups_ptr new_TestInterleavedGroups(struct capn_segment *s) { + TestInterleavedGroups_ptr p; + p.p = capn_new_struct(s, 48, 6); + return p; +} +TestInterleavedGroups_list new_TestInterleavedGroups_list(struct capn_segment *s, int len) { + TestInterleavedGroups_list p; + p.p = capn_new_list(s, len, 48, 6); + return p; +} +void read_TestInterleavedGroups(struct TestInterleavedGroups *s capnp_unused, TestInterleavedGroups_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->group1.foo = capn_read32(p.p, 0); + s->group1.bar = capn_read64(p.p, 8); + s->group1.which = (enum TestInterleavedGroups_group1_which)(int) capn_read16(p.p, 28); + switch (s->group1.which) { + case TestInterleavedGroups_group1_qux: + s->group1.qux = capn_read16(p.p, 24); + break; + case TestInterleavedGroups_group1_fred: + s->group1.fred = capn_get_text(p.p, 2, capn_val0); + break; + case TestInterleavedGroups_group1_corge: + s->group1.corge.grault = capn_read64(p.p, 32); + s->group1.corge.garply = capn_read16(p.p, 24); + s->group1.corge.plugh = capn_get_text(p.p, 2, capn_val0); + s->group1.corge.xyzzy = capn_get_text(p.p, 4, capn_val0); + break; + default: + break; + } + s->group1.waldo = capn_get_text(p.p, 0, capn_val0); + s->group2.foo = capn_read32(p.p, 4); + s->group2.bar = capn_read64(p.p, 16); + s->group2.which = (enum TestInterleavedGroups_group2_which)(int) capn_read16(p.p, 30); + switch (s->group2.which) { + case TestInterleavedGroups_group2_qux: + s->group2.qux = capn_read16(p.p, 26); + break; + case TestInterleavedGroups_group2_fred: + s->group2.fred = capn_get_text(p.p, 3, capn_val0); + break; + case TestInterleavedGroups_group2_corge: + s->group2.corge.grault = capn_read64(p.p, 40); + s->group2.corge.garply = capn_read16(p.p, 26); + s->group2.corge.plugh = capn_get_text(p.p, 3, capn_val0); + s->group2.corge.xyzzy = capn_get_text(p.p, 5, capn_val0); + break; + default: + break; + } + s->group2.waldo = capn_get_text(p.p, 1, capn_val0); +} +void write_TestInterleavedGroups(const struct TestInterleavedGroups *s capnp_unused, TestInterleavedGroups_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write32(p.p, 0, s->group1.foo); + capn_write64(p.p, 8, s->group1.bar); + capn_write16(p.p, 28, s->group1.which); + switch (s->group1.which) { + case TestInterleavedGroups_group1_qux: + capn_write16(p.p, 24, s->group1.qux); + break; + case TestInterleavedGroups_group1_fred: + capn_set_text(p.p, 2, s->group1.fred); + break; + case TestInterleavedGroups_group1_corge: + capn_write64(p.p, 32, s->group1.corge.grault); + capn_write16(p.p, 24, s->group1.corge.garply); + capn_set_text(p.p, 2, s->group1.corge.plugh); + capn_set_text(p.p, 4, s->group1.corge.xyzzy); + break; + default: + break; + } + capn_set_text(p.p, 0, s->group1.waldo); + capn_write32(p.p, 4, s->group2.foo); + capn_write64(p.p, 16, s->group2.bar); + capn_write16(p.p, 30, s->group2.which); + switch (s->group2.which) { + case TestInterleavedGroups_group2_qux: + capn_write16(p.p, 26, s->group2.qux); + break; + case TestInterleavedGroups_group2_fred: + capn_set_text(p.p, 3, s->group2.fred); + break; + case TestInterleavedGroups_group2_corge: + capn_write64(p.p, 40, s->group2.corge.grault); + capn_write16(p.p, 26, s->group2.corge.garply); + capn_set_text(p.p, 3, s->group2.corge.plugh); + capn_set_text(p.p, 5, s->group2.corge.xyzzy); + break; + default: + break; + } + capn_set_text(p.p, 1, s->group2.waldo); +} +void get_TestInterleavedGroups(struct TestInterleavedGroups *s, TestInterleavedGroups_list l, int i) { + TestInterleavedGroups_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestInterleavedGroups(s, p); +} +void set_TestInterleavedGroups(const struct TestInterleavedGroups *s, TestInterleavedGroups_list l, int i) { + TestInterleavedGroups_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestInterleavedGroups(s, p); +} +static TestUnion_ptr capn_val20 = {{1,0,0,0,64,2,0,(char*)&capn_buf[7984],(struct capn_segment*)&capn_seg}}; +static TestUnion_ptr capn_val21 = {{1,0,0,0,64,2,0,(char*)&capn_buf[8064],(struct capn_segment*)&capn_seg}}; +static TestUnnamedUnion_ptr capn_val22 = {{1,0,0,0,16,2,0,(char*)&capn_buf[8152],(struct capn_segment*)&capn_seg}}; +static TestUnnamedUnion_ptr capn_val23 = {{1,0,0,0,16,2,0,(char*)&capn_buf[8184],(struct capn_segment*)&capn_seg}}; + +TestUnionDefaults_ptr new_TestUnionDefaults(struct capn_segment *s) { + TestUnionDefaults_ptr p; + p.p = capn_new_struct(s, 0, 4); + return p; +} +TestUnionDefaults_list new_TestUnionDefaults_list(struct capn_segment *s, int len) { + TestUnionDefaults_list p; + p.p = capn_new_list(s, len, 0, 4); + return p; +} +void read_TestUnionDefaults(struct TestUnionDefaults *s capnp_unused, TestUnionDefaults_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->s16s8s64s8Set.p = capn_getp(p.p, 0, 0); + if (!s->s16s8s64s8Set.p.type) { + s->s16s8s64s8Set = capn_val20; + } + s->s0sps1s32Set.p = capn_getp(p.p, 1, 0); + if (!s->s0sps1s32Set.p.type) { + s->s0sps1s32Set = capn_val21; + } + s->unnamed1.p = capn_getp(p.p, 2, 0); + if (!s->unnamed1.p.type) { + s->unnamed1 = capn_val22; + } + s->unnamed2.p = capn_getp(p.p, 3, 0); + if (!s->unnamed2.p.type) { + s->unnamed2 = capn_val23; + } +} +void write_TestUnionDefaults(const struct TestUnionDefaults *s capnp_unused, TestUnionDefaults_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_setp(p.p, 0, (s->s16s8s64s8Set.p.data != capn_val20.p.data) ? s->s16s8s64s8Set.p : capn_null); + capn_setp(p.p, 1, (s->s0sps1s32Set.p.data != capn_val21.p.data) ? s->s0sps1s32Set.p : capn_null); + capn_setp(p.p, 2, (s->unnamed1.p.data != capn_val22.p.data) ? s->unnamed1.p : capn_null); + capn_setp(p.p, 3, (s->unnamed2.p.data != capn_val23.p.data) ? s->unnamed2.p : capn_null); +} +void get_TestUnionDefaults(struct TestUnionDefaults *s, TestUnionDefaults_list l, int i) { + TestUnionDefaults_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestUnionDefaults(s, p); +} +void set_TestUnionDefaults(const struct TestUnionDefaults *s, TestUnionDefaults_list l, int i) { + TestUnionDefaults_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestUnionDefaults(s, p); +} + +TestUnion_ptr TestUnionDefaults_get_s16s8s64s8Set(TestUnionDefaults_ptr p) +{ + TestUnion_ptr s16s8s64s8Set; + s16s8s64s8Set.p = capn_getp(p.p, 0, 0); +if (!s16s8s64s8Set.p.type) { + s16s8s64s8Set = capn_val20; +} + return s16s8s64s8Set; +} + +TestUnion_ptr TestUnionDefaults_get_s0sps1s32Set(TestUnionDefaults_ptr p) +{ + TestUnion_ptr s0sps1s32Set; + s0sps1s32Set.p = capn_getp(p.p, 1, 0); +if (!s0sps1s32Set.p.type) { + s0sps1s32Set = capn_val21; +} + return s0sps1s32Set; +} + +TestUnnamedUnion_ptr TestUnionDefaults_get_unnamed1(TestUnionDefaults_ptr p) +{ + TestUnnamedUnion_ptr unnamed1; + unnamed1.p = capn_getp(p.p, 2, 0); +if (!unnamed1.p.type) { + unnamed1 = capn_val22; +} + return unnamed1; +} + +TestUnnamedUnion_ptr TestUnionDefaults_get_unnamed2(TestUnionDefaults_ptr p) +{ + TestUnnamedUnion_ptr unnamed2; + unnamed2.p = capn_getp(p.p, 3, 0); +if (!unnamed2.p.type) { + unnamed2 = capn_val23; +} + return unnamed2; +} + +void TestUnionDefaults_set_s16s8s64s8Set(TestUnionDefaults_ptr p, TestUnion_ptr s16s8s64s8Set) +{ + capn_setp(p.p, 0, (s16s8s64s8Set.p.data != capn_val20.p.data) ? s16s8s64s8Set.p : capn_null); +} + +void TestUnionDefaults_set_s0sps1s32Set(TestUnionDefaults_ptr p, TestUnion_ptr s0sps1s32Set) +{ + capn_setp(p.p, 1, (s0sps1s32Set.p.data != capn_val21.p.data) ? s0sps1s32Set.p : capn_null); +} + +void TestUnionDefaults_set_unnamed1(TestUnionDefaults_ptr p, TestUnnamedUnion_ptr unnamed1) +{ + capn_setp(p.p, 2, (unnamed1.p.data != capn_val22.p.data) ? unnamed1.p : capn_null); +} + +void TestUnionDefaults_set_unnamed2(TestUnionDefaults_ptr p, TestUnnamedUnion_ptr unnamed2) +{ + capn_setp(p.p, 3, (unnamed2.p.data != capn_val23.p.data) ? unnamed2.p : capn_null); +} + +TestNestedTypes_ptr new_TestNestedTypes(struct capn_segment *s) { + TestNestedTypes_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestNestedTypes_list new_TestNestedTypes_list(struct capn_segment *s, int len) { + TestNestedTypes_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestNestedTypes(struct TestNestedTypes *s capnp_unused, TestNestedTypes_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->nestedStruct.p = capn_getp(p.p, 0, 0); + s->outerNestedEnum = (enum TestNestedTypes_NestedEnum)(int) capn_read16(p.p, 0) ^ 1u; + s->innerNestedEnum = (enum TestNestedTypes_NestedStruct_NestedEnum)(int) capn_read16(p.p, 2) ^ 2u; +} +void write_TestNestedTypes(const struct TestNestedTypes *s capnp_unused, TestNestedTypes_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_setp(p.p, 0, s->nestedStruct.p); + capn_write16(p.p, 0, (uint16_t) (s->outerNestedEnum ^ 1u)); + capn_write16(p.p, 2, (uint16_t) (s->innerNestedEnum ^ 2u)); +} +void get_TestNestedTypes(struct TestNestedTypes *s, TestNestedTypes_list l, int i) { + TestNestedTypes_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestNestedTypes(s, p); +} +void set_TestNestedTypes(const struct TestNestedTypes *s, TestNestedTypes_list l, int i) { + TestNestedTypes_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestNestedTypes(s, p); +} + +TestNestedTypes_NestedStruct_ptr TestNestedTypes_get_nestedStruct(TestNestedTypes_ptr p) +{ + TestNestedTypes_NestedStruct_ptr nestedStruct; + nestedStruct.p = capn_getp(p.p, 0, 0); + return nestedStruct; +} + +enum TestNestedTypes_NestedEnum TestNestedTypes_get_outerNestedEnum(TestNestedTypes_ptr p) +{ + enum TestNestedTypes_NestedEnum outerNestedEnum; + outerNestedEnum = (enum TestNestedTypes_NestedEnum)(int) capn_read16(p.p, 0) ^ 1u; + return outerNestedEnum; +} + +enum TestNestedTypes_NestedStruct_NestedEnum TestNestedTypes_get_innerNestedEnum(TestNestedTypes_ptr p) +{ + enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum; + innerNestedEnum = (enum TestNestedTypes_NestedStruct_NestedEnum)(int) capn_read16(p.p, 2) ^ 2u; + return innerNestedEnum; +} + +void TestNestedTypes_set_nestedStruct(TestNestedTypes_ptr p, TestNestedTypes_NestedStruct_ptr nestedStruct) +{ + capn_setp(p.p, 0, nestedStruct.p); +} + +void TestNestedTypes_set_outerNestedEnum(TestNestedTypes_ptr p, enum TestNestedTypes_NestedEnum outerNestedEnum) +{ + capn_write16(p.p, 0, (uint16_t) (outerNestedEnum ^ 1u)); +} + +void TestNestedTypes_set_innerNestedEnum(TestNestedTypes_ptr p, enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum) +{ + capn_write16(p.p, 2, (uint16_t) (innerNestedEnum ^ 2u)); +} + +TestNestedTypes_NestedStruct_ptr new_TestNestedTypes_NestedStruct(struct capn_segment *s) { + TestNestedTypes_NestedStruct_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestNestedTypes_NestedStruct_list new_TestNestedTypes_NestedStruct_list(struct capn_segment *s, int len) { + TestNestedTypes_NestedStruct_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestNestedTypes_NestedStruct(struct TestNestedTypes_NestedStruct *s capnp_unused, TestNestedTypes_NestedStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->outerNestedEnum = (enum TestNestedTypes_NestedEnum)(int) capn_read16(p.p, 0) ^ 1u; + s->innerNestedEnum = (enum TestNestedTypes_NestedStruct_NestedEnum)(int) capn_read16(p.p, 2) ^ 2u; +} +void write_TestNestedTypes_NestedStruct(const struct TestNestedTypes_NestedStruct *s capnp_unused, TestNestedTypes_NestedStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, (uint16_t) (s->outerNestedEnum ^ 1u)); + capn_write16(p.p, 2, (uint16_t) (s->innerNestedEnum ^ 2u)); +} +void get_TestNestedTypes_NestedStruct(struct TestNestedTypes_NestedStruct *s, TestNestedTypes_NestedStruct_list l, int i) { + TestNestedTypes_NestedStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestNestedTypes_NestedStruct(s, p); +} +void set_TestNestedTypes_NestedStruct(const struct TestNestedTypes_NestedStruct *s, TestNestedTypes_NestedStruct_list l, int i) { + TestNestedTypes_NestedStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestNestedTypes_NestedStruct(s, p); +} + +enum TestNestedTypes_NestedEnum TestNestedTypes_NestedStruct_get_outerNestedEnum(TestNestedTypes_NestedStruct_ptr p) +{ + enum TestNestedTypes_NestedEnum outerNestedEnum; + outerNestedEnum = (enum TestNestedTypes_NestedEnum)(int) capn_read16(p.p, 0) ^ 1u; + return outerNestedEnum; +} + +enum TestNestedTypes_NestedStruct_NestedEnum TestNestedTypes_NestedStruct_get_innerNestedEnum(TestNestedTypes_NestedStruct_ptr p) +{ + enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum; + innerNestedEnum = (enum TestNestedTypes_NestedStruct_NestedEnum)(int) capn_read16(p.p, 2) ^ 2u; + return innerNestedEnum; +} + +void TestNestedTypes_NestedStruct_set_outerNestedEnum(TestNestedTypes_NestedStruct_ptr p, enum TestNestedTypes_NestedEnum outerNestedEnum) +{ + capn_write16(p.p, 0, (uint16_t) (outerNestedEnum ^ 1u)); +} + +void TestNestedTypes_NestedStruct_set_innerNestedEnum(TestNestedTypes_NestedStruct_ptr p, enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum) +{ + capn_write16(p.p, 2, (uint16_t) (innerNestedEnum ^ 2u)); +} + +TestUsing_ptr new_TestUsing(struct capn_segment *s) { + TestUsing_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestUsing_list new_TestUsing_list(struct capn_segment *s, int len) { + TestUsing_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestUsing(struct TestUsing *s capnp_unused, TestUsing_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->outerNestedEnum = (enum TestNestedTypes_NestedEnum)(int) capn_read16(p.p, 2) ^ 1u; + s->innerNestedEnum = (enum TestNestedTypes_NestedStruct_NestedEnum)(int) capn_read16(p.p, 0) ^ 2u; +} +void write_TestUsing(const struct TestUsing *s capnp_unused, TestUsing_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 2, (uint16_t) (s->outerNestedEnum ^ 1u)); + capn_write16(p.p, 0, (uint16_t) (s->innerNestedEnum ^ 2u)); +} +void get_TestUsing(struct TestUsing *s, TestUsing_list l, int i) { + TestUsing_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestUsing(s, p); +} +void set_TestUsing(const struct TestUsing *s, TestUsing_list l, int i) { + TestUsing_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestUsing(s, p); +} + +enum TestNestedTypes_NestedEnum TestUsing_get_outerNestedEnum(TestUsing_ptr p) +{ + enum TestNestedTypes_NestedEnum outerNestedEnum; + outerNestedEnum = (enum TestNestedTypes_NestedEnum)(int) capn_read16(p.p, 2) ^ 1u; + return outerNestedEnum; +} + +enum TestNestedTypes_NestedStruct_NestedEnum TestUsing_get_innerNestedEnum(TestUsing_ptr p) +{ + enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum; + innerNestedEnum = (enum TestNestedTypes_NestedStruct_NestedEnum)(int) capn_read16(p.p, 0) ^ 2u; + return innerNestedEnum; +} + +void TestUsing_set_outerNestedEnum(TestUsing_ptr p, enum TestNestedTypes_NestedEnum outerNestedEnum) +{ + capn_write16(p.p, 2, (uint16_t) (outerNestedEnum ^ 1u)); +} + +void TestUsing_set_innerNestedEnum(TestUsing_ptr p, enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum) +{ + capn_write16(p.p, 0, (uint16_t) (innerNestedEnum ^ 2u)); +} + +TestLists_ptr new_TestLists(struct capn_segment *s) { + TestLists_ptr p; + p.p = capn_new_struct(s, 0, 10); + return p; +} +TestLists_list new_TestLists_list(struct capn_segment *s, int len) { + TestLists_list p; + p.p = capn_new_list(s, len, 0, 10); + return p; +} +void read_TestLists(struct TestLists *s capnp_unused, TestLists_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->list0.p = capn_getp(p.p, 0, 0); + s->list1.p = capn_getp(p.p, 1, 0); + s->list8.p = capn_getp(p.p, 2, 0); + s->list16.p = capn_getp(p.p, 3, 0); + s->list32.p = capn_getp(p.p, 4, 0); + s->list64.p = capn_getp(p.p, 5, 0); + s->listP.p = capn_getp(p.p, 6, 0); + s->int32ListList = capn_getp(p.p, 7, 0); + s->textListList = capn_getp(p.p, 8, 0); + s->structListList = capn_getp(p.p, 9, 0); +} +void write_TestLists(const struct TestLists *s capnp_unused, TestLists_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_setp(p.p, 0, s->list0.p); + capn_setp(p.p, 1, s->list1.p); + capn_setp(p.p, 2, s->list8.p); + capn_setp(p.p, 3, s->list16.p); + capn_setp(p.p, 4, s->list32.p); + capn_setp(p.p, 5, s->list64.p); + capn_setp(p.p, 6, s->listP.p); + capn_setp(p.p, 7, s->int32ListList); + capn_setp(p.p, 8, s->textListList); + capn_setp(p.p, 9, s->structListList); +} +void get_TestLists(struct TestLists *s, TestLists_list l, int i) { + TestLists_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists(s, p); +} +void set_TestLists(const struct TestLists *s, TestLists_list l, int i) { + TestLists_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists(s, p); +} + +TestLists_Struct0_list TestLists_get_list0(TestLists_ptr p) +{ + TestLists_Struct0_list list0; + list0.p = capn_getp(p.p, 0, 0); + return list0; +} + +TestLists_Struct1_list TestLists_get_list1(TestLists_ptr p) +{ + TestLists_Struct1_list list1; + list1.p = capn_getp(p.p, 1, 0); + return list1; +} + +TestLists_Struct8_list TestLists_get_list8(TestLists_ptr p) +{ + TestLists_Struct8_list list8; + list8.p = capn_getp(p.p, 2, 0); + return list8; +} + +TestLists_Struct16_list TestLists_get_list16(TestLists_ptr p) +{ + TestLists_Struct16_list list16; + list16.p = capn_getp(p.p, 3, 0); + return list16; +} + +TestLists_Struct32_list TestLists_get_list32(TestLists_ptr p) +{ + TestLists_Struct32_list list32; + list32.p = capn_getp(p.p, 4, 0); + return list32; +} + +TestLists_Struct64_list TestLists_get_list64(TestLists_ptr p) +{ + TestLists_Struct64_list list64; + list64.p = capn_getp(p.p, 5, 0); + return list64; +} + +TestLists_StructP_list TestLists_get_listP(TestLists_ptr p) +{ + TestLists_StructP_list listP; + listP.p = capn_getp(p.p, 6, 0); + return listP; +} + +capn_ptr TestLists_get_int32ListList(TestLists_ptr p) +{ + capn_ptr int32ListList; + int32ListList = capn_getp(p.p, 7, 0); + return int32ListList; +} + +capn_ptr TestLists_get_textListList(TestLists_ptr p) +{ + capn_ptr textListList; + textListList = capn_getp(p.p, 8, 0); + return textListList; +} + +capn_ptr TestLists_get_structListList(TestLists_ptr p) +{ + capn_ptr structListList; + structListList = capn_getp(p.p, 9, 0); + return structListList; +} + +void TestLists_set_list0(TestLists_ptr p, TestLists_Struct0_list list0) +{ + capn_setp(p.p, 0, list0.p); +} + +void TestLists_set_list1(TestLists_ptr p, TestLists_Struct1_list list1) +{ + capn_setp(p.p, 1, list1.p); +} + +void TestLists_set_list8(TestLists_ptr p, TestLists_Struct8_list list8) +{ + capn_setp(p.p, 2, list8.p); +} + +void TestLists_set_list16(TestLists_ptr p, TestLists_Struct16_list list16) +{ + capn_setp(p.p, 3, list16.p); +} + +void TestLists_set_list32(TestLists_ptr p, TestLists_Struct32_list list32) +{ + capn_setp(p.p, 4, list32.p); +} + +void TestLists_set_list64(TestLists_ptr p, TestLists_Struct64_list list64) +{ + capn_setp(p.p, 5, list64.p); +} + +void TestLists_set_listP(TestLists_ptr p, TestLists_StructP_list listP) +{ + capn_setp(p.p, 6, listP.p); +} + +void TestLists_set_int32ListList(TestLists_ptr p, capn_ptr int32ListList) +{ + capn_setp(p.p, 7, int32ListList); +} + +void TestLists_set_textListList(TestLists_ptr p, capn_ptr textListList) +{ + capn_setp(p.p, 8, textListList); +} + +void TestLists_set_structListList(TestLists_ptr p, capn_ptr structListList) +{ + capn_setp(p.p, 9, structListList); +} + +TestLists_Struct0_ptr new_TestLists_Struct0(struct capn_segment *s) { + TestLists_Struct0_ptr p; + p.p = capn_new_struct(s, 0, 0); + return p; +} +TestLists_Struct0_list new_TestLists_Struct0_list(struct capn_segment *s, int len) { + TestLists_Struct0_list p; + p.p = capn_new_list(s, len, 0, 0); + return p; +} +void read_TestLists_Struct0(struct TestLists_Struct0 *s capnp_unused, TestLists_Struct0_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void write_TestLists_Struct0(const struct TestLists_Struct0 *s capnp_unused, TestLists_Struct0_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void get_TestLists_Struct0(struct TestLists_Struct0 *s, TestLists_Struct0_list l, int i) { + TestLists_Struct0_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct0(s, p); +} +void set_TestLists_Struct0(const struct TestLists_Struct0 *s, TestLists_Struct0_list l, int i) { + TestLists_Struct0_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct0(s, p); +} + +TestLists_Struct1_ptr new_TestLists_Struct1(struct capn_segment *s) { + TestLists_Struct1_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestLists_Struct1_list new_TestLists_Struct1_list(struct capn_segment *s, int len) { + TestLists_Struct1_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestLists_Struct1(struct TestLists_Struct1 *s capnp_unused, TestLists_Struct1_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = (capn_read8(p.p, 0) & 1) != 0; +} +void write_TestLists_Struct1(const struct TestLists_Struct1 *s capnp_unused, TestLists_Struct1_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write1(p.p, 0, s->f != 0); +} +void get_TestLists_Struct1(struct TestLists_Struct1 *s, TestLists_Struct1_list l, int i) { + TestLists_Struct1_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct1(s, p); +} +void set_TestLists_Struct1(const struct TestLists_Struct1 *s, TestLists_Struct1_list l, int i) { + TestLists_Struct1_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct1(s, p); +} + +unsigned TestLists_Struct1_get_f(TestLists_Struct1_ptr p) +{ + unsigned f; + f = (capn_read8(p.p, 0) & 1) != 0; + return f; +} + +void TestLists_Struct1_set_f(TestLists_Struct1_ptr p, unsigned f) +{ + capn_write1(p.p, 0, f != 0); +} + +TestLists_Struct8_ptr new_TestLists_Struct8(struct capn_segment *s) { + TestLists_Struct8_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestLists_Struct8_list new_TestLists_Struct8_list(struct capn_segment *s, int len) { + TestLists_Struct8_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestLists_Struct8(struct TestLists_Struct8 *s capnp_unused, TestLists_Struct8_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_read8(p.p, 0); +} +void write_TestLists_Struct8(const struct TestLists_Struct8 *s capnp_unused, TestLists_Struct8_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write8(p.p, 0, s->f); +} +void get_TestLists_Struct8(struct TestLists_Struct8 *s, TestLists_Struct8_list l, int i) { + TestLists_Struct8_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct8(s, p); +} +void set_TestLists_Struct8(const struct TestLists_Struct8 *s, TestLists_Struct8_list l, int i) { + TestLists_Struct8_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct8(s, p); +} + +uint8_t TestLists_Struct8_get_f(TestLists_Struct8_ptr p) +{ + uint8_t f; + f = capn_read8(p.p, 0); + return f; +} + +void TestLists_Struct8_set_f(TestLists_Struct8_ptr p, uint8_t f) +{ + capn_write8(p.p, 0, f); +} + +TestLists_Struct16_ptr new_TestLists_Struct16(struct capn_segment *s) { + TestLists_Struct16_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestLists_Struct16_list new_TestLists_Struct16_list(struct capn_segment *s, int len) { + TestLists_Struct16_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestLists_Struct16(struct TestLists_Struct16 *s capnp_unused, TestLists_Struct16_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_read16(p.p, 0); +} +void write_TestLists_Struct16(const struct TestLists_Struct16 *s capnp_unused, TestLists_Struct16_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, s->f); +} +void get_TestLists_Struct16(struct TestLists_Struct16 *s, TestLists_Struct16_list l, int i) { + TestLists_Struct16_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct16(s, p); +} +void set_TestLists_Struct16(const struct TestLists_Struct16 *s, TestLists_Struct16_list l, int i) { + TestLists_Struct16_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct16(s, p); +} + +uint16_t TestLists_Struct16_get_f(TestLists_Struct16_ptr p) +{ + uint16_t f; + f = capn_read16(p.p, 0); + return f; +} + +void TestLists_Struct16_set_f(TestLists_Struct16_ptr p, uint16_t f) +{ + capn_write16(p.p, 0, f); +} + +TestLists_Struct32_ptr new_TestLists_Struct32(struct capn_segment *s) { + TestLists_Struct32_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestLists_Struct32_list new_TestLists_Struct32_list(struct capn_segment *s, int len) { + TestLists_Struct32_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestLists_Struct32(struct TestLists_Struct32 *s capnp_unused, TestLists_Struct32_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_read32(p.p, 0); +} +void write_TestLists_Struct32(const struct TestLists_Struct32 *s capnp_unused, TestLists_Struct32_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write32(p.p, 0, s->f); +} +void get_TestLists_Struct32(struct TestLists_Struct32 *s, TestLists_Struct32_list l, int i) { + TestLists_Struct32_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct32(s, p); +} +void set_TestLists_Struct32(const struct TestLists_Struct32 *s, TestLists_Struct32_list l, int i) { + TestLists_Struct32_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct32(s, p); +} + +uint32_t TestLists_Struct32_get_f(TestLists_Struct32_ptr p) +{ + uint32_t f; + f = capn_read32(p.p, 0); + return f; +} + +void TestLists_Struct32_set_f(TestLists_Struct32_ptr p, uint32_t f) +{ + capn_write32(p.p, 0, f); +} + +TestLists_Struct64_ptr new_TestLists_Struct64(struct capn_segment *s) { + TestLists_Struct64_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestLists_Struct64_list new_TestLists_Struct64_list(struct capn_segment *s, int len) { + TestLists_Struct64_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestLists_Struct64(struct TestLists_Struct64 *s capnp_unused, TestLists_Struct64_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_read64(p.p, 0); +} +void write_TestLists_Struct64(const struct TestLists_Struct64 *s capnp_unused, TestLists_Struct64_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, s->f); +} +void get_TestLists_Struct64(struct TestLists_Struct64 *s, TestLists_Struct64_list l, int i) { + TestLists_Struct64_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct64(s, p); +} +void set_TestLists_Struct64(const struct TestLists_Struct64 *s, TestLists_Struct64_list l, int i) { + TestLists_Struct64_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct64(s, p); +} + +uint64_t TestLists_Struct64_get_f(TestLists_Struct64_ptr p) +{ + uint64_t f; + f = capn_read64(p.p, 0); + return f; +} + +void TestLists_Struct64_set_f(TestLists_Struct64_ptr p, uint64_t f) +{ + capn_write64(p.p, 0, f); +} + +TestLists_StructP_ptr new_TestLists_StructP(struct capn_segment *s) { + TestLists_StructP_ptr p; + p.p = capn_new_struct(s, 0, 1); + return p; +} +TestLists_StructP_list new_TestLists_StructP_list(struct capn_segment *s, int len) { + TestLists_StructP_list p; + p.p = capn_new_list(s, len, 0, 1); + return p; +} +void read_TestLists_StructP(struct TestLists_StructP *s capnp_unused, TestLists_StructP_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_get_text(p.p, 0, capn_val0); +} +void write_TestLists_StructP(const struct TestLists_StructP *s capnp_unused, TestLists_StructP_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->f); +} +void get_TestLists_StructP(struct TestLists_StructP *s, TestLists_StructP_list l, int i) { + TestLists_StructP_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_StructP(s, p); +} +void set_TestLists_StructP(const struct TestLists_StructP *s, TestLists_StructP_list l, int i) { + TestLists_StructP_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_StructP(s, p); +} + +capn_text TestLists_StructP_get_f(TestLists_StructP_ptr p) +{ + capn_text f; + f = capn_get_text(p.p, 0, capn_val0); + return f; +} + +void TestLists_StructP_set_f(TestLists_StructP_ptr p, capn_text f) +{ + capn_set_text(p.p, 0, f); +} + +TestLists_Struct0c_ptr new_TestLists_Struct0c(struct capn_segment *s) { + TestLists_Struct0c_ptr p; + p.p = capn_new_struct(s, 0, 1); + return p; +} +TestLists_Struct0c_list new_TestLists_Struct0c_list(struct capn_segment *s, int len) { + TestLists_Struct0c_list p; + p.p = capn_new_list(s, len, 0, 1); + return p; +} +void read_TestLists_Struct0c(struct TestLists_Struct0c *s capnp_unused, TestLists_Struct0c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->pad = capn_get_text(p.p, 0, capn_val0); +} +void write_TestLists_Struct0c(const struct TestLists_Struct0c *s capnp_unused, TestLists_Struct0c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->pad); +} +void get_TestLists_Struct0c(struct TestLists_Struct0c *s, TestLists_Struct0c_list l, int i) { + TestLists_Struct0c_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct0c(s, p); +} +void set_TestLists_Struct0c(const struct TestLists_Struct0c *s, TestLists_Struct0c_list l, int i) { + TestLists_Struct0c_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct0c(s, p); +} + +capn_text TestLists_Struct0c_get_pad(TestLists_Struct0c_ptr p) +{ + capn_text pad; + pad = capn_get_text(p.p, 0, capn_val0); + return pad; +} + +void TestLists_Struct0c_set_pad(TestLists_Struct0c_ptr p, capn_text pad) +{ + capn_set_text(p.p, 0, pad); +} + +TestLists_Struct1c_ptr new_TestLists_Struct1c(struct capn_segment *s) { + TestLists_Struct1c_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestLists_Struct1c_list new_TestLists_Struct1c_list(struct capn_segment *s, int len) { + TestLists_Struct1c_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestLists_Struct1c(struct TestLists_Struct1c *s capnp_unused, TestLists_Struct1c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = (capn_read8(p.p, 0) & 1) != 0; + s->pad = capn_get_text(p.p, 0, capn_val0); +} +void write_TestLists_Struct1c(const struct TestLists_Struct1c *s capnp_unused, TestLists_Struct1c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write1(p.p, 0, s->f != 0); + capn_set_text(p.p, 0, s->pad); +} +void get_TestLists_Struct1c(struct TestLists_Struct1c *s, TestLists_Struct1c_list l, int i) { + TestLists_Struct1c_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct1c(s, p); +} +void set_TestLists_Struct1c(const struct TestLists_Struct1c *s, TestLists_Struct1c_list l, int i) { + TestLists_Struct1c_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct1c(s, p); +} + +unsigned TestLists_Struct1c_get_f(TestLists_Struct1c_ptr p) +{ + unsigned f; + f = (capn_read8(p.p, 0) & 1) != 0; + return f; +} + +capn_text TestLists_Struct1c_get_pad(TestLists_Struct1c_ptr p) +{ + capn_text pad; + pad = capn_get_text(p.p, 0, capn_val0); + return pad; +} + +void TestLists_Struct1c_set_f(TestLists_Struct1c_ptr p, unsigned f) +{ + capn_write1(p.p, 0, f != 0); +} + +void TestLists_Struct1c_set_pad(TestLists_Struct1c_ptr p, capn_text pad) +{ + capn_set_text(p.p, 0, pad); +} + +TestLists_Struct8c_ptr new_TestLists_Struct8c(struct capn_segment *s) { + TestLists_Struct8c_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestLists_Struct8c_list new_TestLists_Struct8c_list(struct capn_segment *s, int len) { + TestLists_Struct8c_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestLists_Struct8c(struct TestLists_Struct8c *s capnp_unused, TestLists_Struct8c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_read8(p.p, 0); + s->pad = capn_get_text(p.p, 0, capn_val0); +} +void write_TestLists_Struct8c(const struct TestLists_Struct8c *s capnp_unused, TestLists_Struct8c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write8(p.p, 0, s->f); + capn_set_text(p.p, 0, s->pad); +} +void get_TestLists_Struct8c(struct TestLists_Struct8c *s, TestLists_Struct8c_list l, int i) { + TestLists_Struct8c_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct8c(s, p); +} +void set_TestLists_Struct8c(const struct TestLists_Struct8c *s, TestLists_Struct8c_list l, int i) { + TestLists_Struct8c_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct8c(s, p); +} + +uint8_t TestLists_Struct8c_get_f(TestLists_Struct8c_ptr p) +{ + uint8_t f; + f = capn_read8(p.p, 0); + return f; +} + +capn_text TestLists_Struct8c_get_pad(TestLists_Struct8c_ptr p) +{ + capn_text pad; + pad = capn_get_text(p.p, 0, capn_val0); + return pad; +} + +void TestLists_Struct8c_set_f(TestLists_Struct8c_ptr p, uint8_t f) +{ + capn_write8(p.p, 0, f); +} + +void TestLists_Struct8c_set_pad(TestLists_Struct8c_ptr p, capn_text pad) +{ + capn_set_text(p.p, 0, pad); +} + +TestLists_Struct16c_ptr new_TestLists_Struct16c(struct capn_segment *s) { + TestLists_Struct16c_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestLists_Struct16c_list new_TestLists_Struct16c_list(struct capn_segment *s, int len) { + TestLists_Struct16c_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestLists_Struct16c(struct TestLists_Struct16c *s capnp_unused, TestLists_Struct16c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_read16(p.p, 0); + s->pad = capn_get_text(p.p, 0, capn_val0); +} +void write_TestLists_Struct16c(const struct TestLists_Struct16c *s capnp_unused, TestLists_Struct16c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, s->f); + capn_set_text(p.p, 0, s->pad); +} +void get_TestLists_Struct16c(struct TestLists_Struct16c *s, TestLists_Struct16c_list l, int i) { + TestLists_Struct16c_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct16c(s, p); +} +void set_TestLists_Struct16c(const struct TestLists_Struct16c *s, TestLists_Struct16c_list l, int i) { + TestLists_Struct16c_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct16c(s, p); +} + +uint16_t TestLists_Struct16c_get_f(TestLists_Struct16c_ptr p) +{ + uint16_t f; + f = capn_read16(p.p, 0); + return f; +} + +capn_text TestLists_Struct16c_get_pad(TestLists_Struct16c_ptr p) +{ + capn_text pad; + pad = capn_get_text(p.p, 0, capn_val0); + return pad; +} + +void TestLists_Struct16c_set_f(TestLists_Struct16c_ptr p, uint16_t f) +{ + capn_write16(p.p, 0, f); +} + +void TestLists_Struct16c_set_pad(TestLists_Struct16c_ptr p, capn_text pad) +{ + capn_set_text(p.p, 0, pad); +} + +TestLists_Struct32c_ptr new_TestLists_Struct32c(struct capn_segment *s) { + TestLists_Struct32c_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestLists_Struct32c_list new_TestLists_Struct32c_list(struct capn_segment *s, int len) { + TestLists_Struct32c_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestLists_Struct32c(struct TestLists_Struct32c *s capnp_unused, TestLists_Struct32c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_read32(p.p, 0); + s->pad = capn_get_text(p.p, 0, capn_val0); +} +void write_TestLists_Struct32c(const struct TestLists_Struct32c *s capnp_unused, TestLists_Struct32c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write32(p.p, 0, s->f); + capn_set_text(p.p, 0, s->pad); +} +void get_TestLists_Struct32c(struct TestLists_Struct32c *s, TestLists_Struct32c_list l, int i) { + TestLists_Struct32c_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct32c(s, p); +} +void set_TestLists_Struct32c(const struct TestLists_Struct32c *s, TestLists_Struct32c_list l, int i) { + TestLists_Struct32c_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct32c(s, p); +} + +uint32_t TestLists_Struct32c_get_f(TestLists_Struct32c_ptr p) +{ + uint32_t f; + f = capn_read32(p.p, 0); + return f; +} + +capn_text TestLists_Struct32c_get_pad(TestLists_Struct32c_ptr p) +{ + capn_text pad; + pad = capn_get_text(p.p, 0, capn_val0); + return pad; +} + +void TestLists_Struct32c_set_f(TestLists_Struct32c_ptr p, uint32_t f) +{ + capn_write32(p.p, 0, f); +} + +void TestLists_Struct32c_set_pad(TestLists_Struct32c_ptr p, capn_text pad) +{ + capn_set_text(p.p, 0, pad); +} + +TestLists_Struct64c_ptr new_TestLists_Struct64c(struct capn_segment *s) { + TestLists_Struct64c_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestLists_Struct64c_list new_TestLists_Struct64c_list(struct capn_segment *s, int len) { + TestLists_Struct64c_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestLists_Struct64c(struct TestLists_Struct64c *s capnp_unused, TestLists_Struct64c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_read64(p.p, 0); + s->pad = capn_get_text(p.p, 0, capn_val0); +} +void write_TestLists_Struct64c(const struct TestLists_Struct64c *s capnp_unused, TestLists_Struct64c_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, s->f); + capn_set_text(p.p, 0, s->pad); +} +void get_TestLists_Struct64c(struct TestLists_Struct64c *s, TestLists_Struct64c_list l, int i) { + TestLists_Struct64c_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_Struct64c(s, p); +} +void set_TestLists_Struct64c(const struct TestLists_Struct64c *s, TestLists_Struct64c_list l, int i) { + TestLists_Struct64c_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_Struct64c(s, p); +} + +uint64_t TestLists_Struct64c_get_f(TestLists_Struct64c_ptr p) +{ + uint64_t f; + f = capn_read64(p.p, 0); + return f; +} + +capn_text TestLists_Struct64c_get_pad(TestLists_Struct64c_ptr p) +{ + capn_text pad; + pad = capn_get_text(p.p, 0, capn_val0); + return pad; +} + +void TestLists_Struct64c_set_f(TestLists_Struct64c_ptr p, uint64_t f) +{ + capn_write64(p.p, 0, f); +} + +void TestLists_Struct64c_set_pad(TestLists_Struct64c_ptr p, capn_text pad) +{ + capn_set_text(p.p, 0, pad); +} + +TestLists_StructPc_ptr new_TestLists_StructPc(struct capn_segment *s) { + TestLists_StructPc_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestLists_StructPc_list new_TestLists_StructPc_list(struct capn_segment *s, int len) { + TestLists_StructPc_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestLists_StructPc(struct TestLists_StructPc *s capnp_unused, TestLists_StructPc_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->f = capn_get_text(p.p, 0, capn_val0); + s->pad = capn_read64(p.p, 0); +} +void write_TestLists_StructPc(const struct TestLists_StructPc *s capnp_unused, TestLists_StructPc_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->f); + capn_write64(p.p, 0, s->pad); +} +void get_TestLists_StructPc(struct TestLists_StructPc *s, TestLists_StructPc_list l, int i) { + TestLists_StructPc_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLists_StructPc(s, p); +} +void set_TestLists_StructPc(const struct TestLists_StructPc *s, TestLists_StructPc_list l, int i) { + TestLists_StructPc_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLists_StructPc(s, p); +} + +capn_text TestLists_StructPc_get_f(TestLists_StructPc_ptr p) +{ + capn_text f; + f = capn_get_text(p.p, 0, capn_val0); + return f; +} + +uint64_t TestLists_StructPc_get_pad(TestLists_StructPc_ptr p) +{ + uint64_t pad; + pad = capn_read64(p.p, 0); + return pad; +} + +void TestLists_StructPc_set_f(TestLists_StructPc_ptr p, capn_text f) +{ + capn_set_text(p.p, 0, f); +} + +void TestLists_StructPc_set_pad(TestLists_StructPc_ptr p, uint64_t pad) +{ + capn_write64(p.p, 0, pad); +} + +TestFieldZeroIsBit_ptr new_TestFieldZeroIsBit(struct capn_segment *s) { + TestFieldZeroIsBit_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestFieldZeroIsBit_list new_TestFieldZeroIsBit_list(struct capn_segment *s, int len) { + TestFieldZeroIsBit_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestFieldZeroIsBit(struct TestFieldZeroIsBit *s capnp_unused, TestFieldZeroIsBit_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->bit = (capn_read8(p.p, 0) & 1) != 0; + s->secondBit = (capn_read8(p.p, 0) & 2) != 2; + s->thirdField = capn_read8(p.p, 1) ^ 123u; +} +void write_TestFieldZeroIsBit(const struct TestFieldZeroIsBit *s capnp_unused, TestFieldZeroIsBit_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write1(p.p, 0, s->bit != 0); + capn_write1(p.p, 1, s->secondBit != 1); + capn_write8(p.p, 1, s->thirdField ^ 123u); +} +void get_TestFieldZeroIsBit(struct TestFieldZeroIsBit *s, TestFieldZeroIsBit_list l, int i) { + TestFieldZeroIsBit_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestFieldZeroIsBit(s, p); +} +void set_TestFieldZeroIsBit(const struct TestFieldZeroIsBit *s, TestFieldZeroIsBit_list l, int i) { + TestFieldZeroIsBit_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestFieldZeroIsBit(s, p); +} + +unsigned TestFieldZeroIsBit_get_bit(TestFieldZeroIsBit_ptr p) +{ + unsigned bit; + bit = (capn_read8(p.p, 0) & 1) != 0; + return bit; +} + +unsigned TestFieldZeroIsBit_get_secondBit(TestFieldZeroIsBit_ptr p) +{ + unsigned secondBit; + secondBit = (capn_read8(p.p, 0) & 2) != 2; + return secondBit; +} + +uint8_t TestFieldZeroIsBit_get_thirdField(TestFieldZeroIsBit_ptr p) +{ + uint8_t thirdField; + thirdField = capn_read8(p.p, 1) ^ 123u; + return thirdField; +} + +void TestFieldZeroIsBit_set_bit(TestFieldZeroIsBit_ptr p, unsigned bit) +{ + capn_write1(p.p, 0, bit != 0); +} + +void TestFieldZeroIsBit_set_secondBit(TestFieldZeroIsBit_ptr p, unsigned secondBit) +{ + capn_write1(p.p, 1, secondBit != 1); +} + +void TestFieldZeroIsBit_set_thirdField(TestFieldZeroIsBit_ptr p, uint8_t thirdField) +{ + capn_write8(p.p, 1, thirdField ^ 123u); +} +static TestLists_ptr capn_val24 = {{1,0,0,0,0,10,0,(char*)&capn_buf[8232],(struct capn_segment*)&capn_seg}}; + +TestListDefaults_ptr new_TestListDefaults(struct capn_segment *s) { + TestListDefaults_ptr p; + p.p = capn_new_struct(s, 0, 1); + return p; +} +TestListDefaults_list new_TestListDefaults_list(struct capn_segment *s, int len) { + TestListDefaults_list p; + p.p = capn_new_list(s, len, 0, 1); + return p; +} +void read_TestListDefaults(struct TestListDefaults *s capnp_unused, TestListDefaults_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->lists.p = capn_getp(p.p, 0, 0); + if (!s->lists.p.type) { + s->lists = capn_val24; + } +} +void write_TestListDefaults(const struct TestListDefaults *s capnp_unused, TestListDefaults_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_setp(p.p, 0, (s->lists.p.data != capn_val24.p.data) ? s->lists.p : capn_null); +} +void get_TestListDefaults(struct TestListDefaults *s, TestListDefaults_list l, int i) { + TestListDefaults_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestListDefaults(s, p); +} +void set_TestListDefaults(const struct TestListDefaults *s, TestListDefaults_list l, int i) { + TestListDefaults_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestListDefaults(s, p); +} + +TestLists_ptr TestListDefaults_get_lists(TestListDefaults_ptr p) +{ + TestLists_ptr lists; + lists.p = capn_getp(p.p, 0, 0); +if (!lists.p.type) { + lists = capn_val24; +} + return lists; +} + +void TestListDefaults_set_lists(TestListDefaults_ptr p, TestLists_ptr lists) +{ + capn_setp(p.p, 0, (lists.p.data != capn_val24.p.data) ? lists.p : capn_null); +} + +TestLateUnion_ptr new_TestLateUnion(struct capn_segment *s) { + TestLateUnion_ptr p; + p.p = capn_new_struct(s, 24, 3); + return p; +} +TestLateUnion_list new_TestLateUnion_list(struct capn_segment *s, int len) { + TestLateUnion_list p; + p.p = capn_new_list(s, len, 24, 3); + return p; +} +void read_TestLateUnion(struct TestLateUnion *s capnp_unused, TestLateUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->foo = (int32_t) ((int32_t)capn_read32(p.p, 0)); + s->bar = capn_get_text(p.p, 0, capn_val0); + s->baz = (int16_t) ((int16_t)capn_read16(p.p, 4)); + s->theUnion_which = (enum TestLateUnion_theUnion_which)(int) capn_read16(p.p, 6); + switch (s->theUnion_which) { + case TestLateUnion_theUnion_grault: + s->theUnion.grault = capn_to_f32(capn_read32(p.p, 8)); + break; + case TestLateUnion_theUnion_qux: + s->theUnion.qux = capn_get_text(p.p, 1, capn_val0); + break; + case TestLateUnion_theUnion_corge: + s->theUnion.corge.p = capn_getp(p.p, 1, 0); + break; + default: + break; + } + s->anotherUnion_which = (enum TestLateUnion_anotherUnion_which)(int) capn_read16(p.p, 12); + switch (s->anotherUnion_which) { + case TestLateUnion_anotherUnion_grault: + s->anotherUnion.grault = capn_to_f32(capn_read32(p.p, 16)); + break; + case TestLateUnion_anotherUnion_qux: + s->anotherUnion.qux = capn_get_text(p.p, 2, capn_val0); + break; + case TestLateUnion_anotherUnion_corge: + s->anotherUnion.corge.p = capn_getp(p.p, 2, 0); + break; + default: + break; + } +} +void write_TestLateUnion(const struct TestLateUnion *s capnp_unused, TestLateUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write32(p.p, 0, (uint32_t) (s->foo)); + capn_set_text(p.p, 0, s->bar); + capn_write16(p.p, 4, (uint16_t) (s->baz)); + capn_write16(p.p, 6, s->theUnion_which); + switch (s->theUnion_which) { + case TestLateUnion_theUnion_grault: + capn_write32(p.p, 8, capn_from_f32(s->theUnion.grault)); + break; + case TestLateUnion_theUnion_qux: + capn_set_text(p.p, 1, s->theUnion.qux); + break; + case TestLateUnion_theUnion_corge: + capn_setp(p.p, 1, s->theUnion.corge.p); + break; + default: + break; + } + capn_write16(p.p, 12, s->anotherUnion_which); + switch (s->anotherUnion_which) { + case TestLateUnion_anotherUnion_grault: + capn_write32(p.p, 16, capn_from_f32(s->anotherUnion.grault)); + break; + case TestLateUnion_anotherUnion_qux: + capn_set_text(p.p, 2, s->anotherUnion.qux); + break; + case TestLateUnion_anotherUnion_corge: + capn_setp(p.p, 2, s->anotherUnion.corge.p); + break; + default: + break; + } +} +void get_TestLateUnion(struct TestLateUnion *s, TestLateUnion_list l, int i) { + TestLateUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestLateUnion(s, p); +} +void set_TestLateUnion(const struct TestLateUnion *s, TestLateUnion_list l, int i) { + TestLateUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestLateUnion(s, p); +} + +int32_t TestLateUnion_get_foo(TestLateUnion_ptr p) +{ + int32_t foo; + foo = (int32_t) ((int32_t)capn_read32(p.p, 0)); + return foo; +} + +capn_text TestLateUnion_get_bar(TestLateUnion_ptr p) +{ + capn_text bar; + bar = capn_get_text(p.p, 0, capn_val0); + return bar; +} + +int16_t TestLateUnion_get_baz(TestLateUnion_ptr p) +{ + int16_t baz; + baz = (int16_t) ((int16_t)capn_read16(p.p, 4)); + return baz; +} + +void TestLateUnion_set_foo(TestLateUnion_ptr p, int32_t foo) +{ + capn_write32(p.p, 0, (uint32_t) (foo)); +} + +void TestLateUnion_set_bar(TestLateUnion_ptr p, capn_text bar) +{ + capn_set_text(p.p, 0, bar); +} + +void TestLateUnion_set_baz(TestLateUnion_ptr p, int16_t baz) +{ + capn_write16(p.p, 4, (uint16_t) (baz)); +} + +TestOldVersion_ptr new_TestOldVersion(struct capn_segment *s) { + TestOldVersion_ptr p; + p.p = capn_new_struct(s, 8, 2); + return p; +} +TestOldVersion_list new_TestOldVersion_list(struct capn_segment *s, int len) { + TestOldVersion_list p; + p.p = capn_new_list(s, len, 8, 2); + return p; +} +void read_TestOldVersion(struct TestOldVersion *s capnp_unused, TestOldVersion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->old1 = (int64_t) ((int64_t)(capn_read64(p.p, 0))); + s->old2 = capn_get_text(p.p, 0, capn_val0); + s->old3.p = capn_getp(p.p, 1, 0); +} +void write_TestOldVersion(const struct TestOldVersion *s capnp_unused, TestOldVersion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, (uint64_t) (s->old1)); + capn_set_text(p.p, 0, s->old2); + capn_setp(p.p, 1, s->old3.p); +} +void get_TestOldVersion(struct TestOldVersion *s, TestOldVersion_list l, int i) { + TestOldVersion_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestOldVersion(s, p); +} +void set_TestOldVersion(const struct TestOldVersion *s, TestOldVersion_list l, int i) { + TestOldVersion_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestOldVersion(s, p); +} + +int64_t TestOldVersion_get_old1(TestOldVersion_ptr p) +{ + int64_t old1; + old1 = (int64_t) ((int64_t)(capn_read64(p.p, 0))); + return old1; +} + +capn_text TestOldVersion_get_old2(TestOldVersion_ptr p) +{ + capn_text old2; + old2 = capn_get_text(p.p, 0, capn_val0); + return old2; +} + +TestOldVersion_ptr TestOldVersion_get_old3(TestOldVersion_ptr p) +{ + TestOldVersion_ptr old3; + old3.p = capn_getp(p.p, 1, 0); + return old3; +} + +void TestOldVersion_set_old1(TestOldVersion_ptr p, int64_t old1) +{ + capn_write64(p.p, 0, (uint64_t) (old1)); +} + +void TestOldVersion_set_old2(TestOldVersion_ptr p, capn_text old2) +{ + capn_set_text(p.p, 0, old2); +} + +void TestOldVersion_set_old3(TestOldVersion_ptr p, TestOldVersion_ptr old3) +{ + capn_setp(p.p, 1, old3.p); +} +static capn_text capn_val25 = {3,(char*)&capn_buf[9264],(struct capn_segment*)&capn_seg}; + +TestNewVersion_ptr new_TestNewVersion(struct capn_segment *s) { + TestNewVersion_ptr p; + p.p = capn_new_struct(s, 16, 3); + return p; +} +TestNewVersion_list new_TestNewVersion_list(struct capn_segment *s, int len) { + TestNewVersion_list p; + p.p = capn_new_list(s, len, 16, 3); + return p; +} +void read_TestNewVersion(struct TestNewVersion *s capnp_unused, TestNewVersion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->old1 = (int64_t) ((int64_t)(capn_read64(p.p, 0))); + s->old2 = capn_get_text(p.p, 0, capn_val0); + s->old3.p = capn_getp(p.p, 1, 0); + s->new1 = (int64_t) ((int64_t)(capn_read64(p.p, 8)) ^ ((int64_t)((uint64_t) 0u << 32) ^ 0x3dbu)); + s->new2 = capn_get_text(p.p, 2, capn_val25); +} +void write_TestNewVersion(const struct TestNewVersion *s capnp_unused, TestNewVersion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write64(p.p, 0, (uint64_t) (s->old1)); + capn_set_text(p.p, 0, s->old2); + capn_setp(p.p, 1, s->old3.p); + capn_write64(p.p, 8, (uint64_t) (s->new1 ^ ((int64_t)((uint64_t) 0u << 32) ^ 0x3dbu))); + capn_set_text(p.p, 2, (s->new2.str != capn_val25.str) ? s->new2 : capn_val0); +} +void get_TestNewVersion(struct TestNewVersion *s, TestNewVersion_list l, int i) { + TestNewVersion_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestNewVersion(s, p); +} +void set_TestNewVersion(const struct TestNewVersion *s, TestNewVersion_list l, int i) { + TestNewVersion_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestNewVersion(s, p); +} + +int64_t TestNewVersion_get_old1(TestNewVersion_ptr p) +{ + int64_t old1; + old1 = (int64_t) ((int64_t)(capn_read64(p.p, 0))); + return old1; +} + +capn_text TestNewVersion_get_old2(TestNewVersion_ptr p) +{ + capn_text old2; + old2 = capn_get_text(p.p, 0, capn_val0); + return old2; +} + +TestNewVersion_ptr TestNewVersion_get_old3(TestNewVersion_ptr p) +{ + TestNewVersion_ptr old3; + old3.p = capn_getp(p.p, 1, 0); + return old3; +} + +int64_t TestNewVersion_get_new1(TestNewVersion_ptr p) +{ + int64_t new1; + new1 = (int64_t) ((int64_t)(capn_read64(p.p, 8)) ^ ((int64_t)((uint64_t) 0u << 32) ^ 0x3dbu)); + return new1; +} + +capn_text TestNewVersion_get_new2(TestNewVersion_ptr p) +{ + capn_text new2; + new2 = capn_get_text(p.p, 2, capn_val25); + return new2; +} + +void TestNewVersion_set_old1(TestNewVersion_ptr p, int64_t old1) +{ + capn_write64(p.p, 0, (uint64_t) (old1)); +} + +void TestNewVersion_set_old2(TestNewVersion_ptr p, capn_text old2) +{ + capn_set_text(p.p, 0, old2); +} + +void TestNewVersion_set_old3(TestNewVersion_ptr p, TestNewVersion_ptr old3) +{ + capn_setp(p.p, 1, old3.p); +} + +void TestNewVersion_set_new1(TestNewVersion_ptr p, int64_t new1) +{ + capn_write64(p.p, 8, (uint64_t) (new1 ^ ((int64_t)((uint64_t) 0u << 32) ^ 0x3dbu))); +} + +void TestNewVersion_set_new2(TestNewVersion_ptr p, capn_text new2) +{ + capn_set_text(p.p, 2, (new2.str != capn_val25.str) ? new2 : capn_val0); +} + +TestStructUnion_ptr new_TestStructUnion(struct capn_segment *s) { + TestStructUnion_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestStructUnion_list new_TestStructUnion_list(struct capn_segment *s, int len) { + TestStructUnion_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestStructUnion(struct TestStructUnion *s capnp_unused, TestStructUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->un_which = (enum TestStructUnion_un_which)(int) capn_read16(p.p, 0); + switch (s->un_which) { + case TestStructUnion_un__struct: + case TestStructUnion_un_object: + s->un.object.p = capn_getp(p.p, 0, 0); + break; + default: + break; + } +} +void write_TestStructUnion(const struct TestStructUnion *s capnp_unused, TestStructUnion_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, s->un_which); + switch (s->un_which) { + case TestStructUnion_un__struct: + case TestStructUnion_un_object: + capn_setp(p.p, 0, s->un.object.p); + break; + default: + break; + } +} +void get_TestStructUnion(struct TestStructUnion *s, TestStructUnion_list l, int i) { + TestStructUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestStructUnion(s, p); +} +void set_TestStructUnion(const struct TestStructUnion *s, TestStructUnion_list l, int i) { + TestStructUnion_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestStructUnion(s, p); +} + +TestStructUnion_SomeStruct_ptr new_TestStructUnion_SomeStruct(struct capn_segment *s) { + TestStructUnion_SomeStruct_ptr p; + p.p = capn_new_struct(s, 0, 2); + return p; +} +TestStructUnion_SomeStruct_list new_TestStructUnion_SomeStruct_list(struct capn_segment *s, int len) { + TestStructUnion_SomeStruct_list p; + p.p = capn_new_list(s, len, 0, 2); + return p; +} +void read_TestStructUnion_SomeStruct(struct TestStructUnion_SomeStruct *s capnp_unused, TestStructUnion_SomeStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->someText = capn_get_text(p.p, 0, capn_val0); + s->moreText = capn_get_text(p.p, 1, capn_val0); +} +void write_TestStructUnion_SomeStruct(const struct TestStructUnion_SomeStruct *s capnp_unused, TestStructUnion_SomeStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->someText); + capn_set_text(p.p, 1, s->moreText); +} +void get_TestStructUnion_SomeStruct(struct TestStructUnion_SomeStruct *s, TestStructUnion_SomeStruct_list l, int i) { + TestStructUnion_SomeStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestStructUnion_SomeStruct(s, p); +} +void set_TestStructUnion_SomeStruct(const struct TestStructUnion_SomeStruct *s, TestStructUnion_SomeStruct_list l, int i) { + TestStructUnion_SomeStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestStructUnion_SomeStruct(s, p); +} + +capn_text TestStructUnion_SomeStruct_get_someText(TestStructUnion_SomeStruct_ptr p) +{ + capn_text someText; + someText = capn_get_text(p.p, 0, capn_val0); + return someText; +} + +capn_text TestStructUnion_SomeStruct_get_moreText(TestStructUnion_SomeStruct_ptr p) +{ + capn_text moreText; + moreText = capn_get_text(p.p, 1, capn_val0); + return moreText; +} + +void TestStructUnion_SomeStruct_set_someText(TestStructUnion_SomeStruct_ptr p, capn_text someText) +{ + capn_set_text(p.p, 0, someText); +} + +void TestStructUnion_SomeStruct_set_moreText(TestStructUnion_SomeStruct_ptr p, capn_text moreText) +{ + capn_set_text(p.p, 1, moreText); +} + +TestPrintInlineStructs_ptr new_TestPrintInlineStructs(struct capn_segment *s) { + TestPrintInlineStructs_ptr p; + p.p = capn_new_struct(s, 0, 2); + return p; +} +TestPrintInlineStructs_list new_TestPrintInlineStructs_list(struct capn_segment *s, int len) { + TestPrintInlineStructs_list p; + p.p = capn_new_list(s, len, 0, 2); + return p; +} +void read_TestPrintInlineStructs(struct TestPrintInlineStructs *s capnp_unused, TestPrintInlineStructs_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->someText = capn_get_text(p.p, 0, capn_val0); + s->structList.p = capn_getp(p.p, 1, 0); +} +void write_TestPrintInlineStructs(const struct TestPrintInlineStructs *s capnp_unused, TestPrintInlineStructs_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->someText); + capn_setp(p.p, 1, s->structList.p); +} +void get_TestPrintInlineStructs(struct TestPrintInlineStructs *s, TestPrintInlineStructs_list l, int i) { + TestPrintInlineStructs_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestPrintInlineStructs(s, p); +} +void set_TestPrintInlineStructs(const struct TestPrintInlineStructs *s, TestPrintInlineStructs_list l, int i) { + TestPrintInlineStructs_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestPrintInlineStructs(s, p); +} + +capn_text TestPrintInlineStructs_get_someText(TestPrintInlineStructs_ptr p) +{ + capn_text someText; + someText = capn_get_text(p.p, 0, capn_val0); + return someText; +} + +TestPrintInlineStructs_InlineStruct_list TestPrintInlineStructs_get_structList(TestPrintInlineStructs_ptr p) +{ + TestPrintInlineStructs_InlineStruct_list structList; + structList.p = capn_getp(p.p, 1, 0); + return structList; +} + +void TestPrintInlineStructs_set_someText(TestPrintInlineStructs_ptr p, capn_text someText) +{ + capn_set_text(p.p, 0, someText); +} + +void TestPrintInlineStructs_set_structList(TestPrintInlineStructs_ptr p, TestPrintInlineStructs_InlineStruct_list structList) +{ + capn_setp(p.p, 1, structList.p); +} + +TestPrintInlineStructs_InlineStruct_ptr new_TestPrintInlineStructs_InlineStruct(struct capn_segment *s) { + TestPrintInlineStructs_InlineStruct_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestPrintInlineStructs_InlineStruct_list new_TestPrintInlineStructs_InlineStruct_list(struct capn_segment *s, int len) { + TestPrintInlineStructs_InlineStruct_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestPrintInlineStructs_InlineStruct(struct TestPrintInlineStructs_InlineStruct *s capnp_unused, TestPrintInlineStructs_InlineStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->int32Field = (int32_t) ((int32_t)capn_read32(p.p, 0)); + s->textField = capn_get_text(p.p, 0, capn_val0); +} +void write_TestPrintInlineStructs_InlineStruct(const struct TestPrintInlineStructs_InlineStruct *s capnp_unused, TestPrintInlineStructs_InlineStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write32(p.p, 0, (uint32_t) (s->int32Field)); + capn_set_text(p.p, 0, s->textField); +} +void get_TestPrintInlineStructs_InlineStruct(struct TestPrintInlineStructs_InlineStruct *s, TestPrintInlineStructs_InlineStruct_list l, int i) { + TestPrintInlineStructs_InlineStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestPrintInlineStructs_InlineStruct(s, p); +} +void set_TestPrintInlineStructs_InlineStruct(const struct TestPrintInlineStructs_InlineStruct *s, TestPrintInlineStructs_InlineStruct_list l, int i) { + TestPrintInlineStructs_InlineStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestPrintInlineStructs_InlineStruct(s, p); +} + +int32_t TestPrintInlineStructs_InlineStruct_get_int32Field(TestPrintInlineStructs_InlineStruct_ptr p) +{ + int32_t int32Field; + int32Field = (int32_t) ((int32_t)capn_read32(p.p, 0)); + return int32Field; +} + +capn_text TestPrintInlineStructs_InlineStruct_get_textField(TestPrintInlineStructs_InlineStruct_ptr p) +{ + capn_text textField; + textField = capn_get_text(p.p, 0, capn_val0); + return textField; +} + +void TestPrintInlineStructs_InlineStruct_set_int32Field(TestPrintInlineStructs_InlineStruct_ptr p, int32_t int32Field) +{ + capn_write32(p.p, 0, (uint32_t) (int32Field)); +} + +void TestPrintInlineStructs_InlineStruct_set_textField(TestPrintInlineStructs_InlineStruct_ptr p, capn_text textField) +{ + capn_set_text(p.p, 0, textField); +} + +TestWholeFloatDefault_ptr new_TestWholeFloatDefault(struct capn_segment *s) { + TestWholeFloatDefault_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestWholeFloatDefault_list new_TestWholeFloatDefault_list(struct capn_segment *s, int len) { + TestWholeFloatDefault_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestWholeFloatDefault(struct TestWholeFloatDefault *s capnp_unused, TestWholeFloatDefault_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->field = capn_to_f32(capn_read32(p.p, 0) ^ 0x42f60000u); + s->bigField = capn_to_f32(capn_read32(p.p, 4) ^ 0x71c9f2cau); +} +void write_TestWholeFloatDefault(const struct TestWholeFloatDefault *s capnp_unused, TestWholeFloatDefault_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write32(p.p, 0, capn_from_f32(s->field) ^ 0x42f60000u); + capn_write32(p.p, 4, capn_from_f32(s->bigField) ^ 0x71c9f2cau); +} +void get_TestWholeFloatDefault(struct TestWholeFloatDefault *s, TestWholeFloatDefault_list l, int i) { + TestWholeFloatDefault_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestWholeFloatDefault(s, p); +} +void set_TestWholeFloatDefault(const struct TestWholeFloatDefault *s, TestWholeFloatDefault_list l, int i) { + TestWholeFloatDefault_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestWholeFloatDefault(s, p); +} + +float TestWholeFloatDefault_get_field(TestWholeFloatDefault_ptr p) +{ + float field; + field = capn_to_f32(capn_read32(p.p, 0) ^ 0x42f60000u); + return field; +} + +float TestWholeFloatDefault_get_bigField(TestWholeFloatDefault_ptr p) +{ + float bigField; + bigField = capn_to_f32(capn_read32(p.p, 4) ^ 0x71c9f2cau); + return bigField; +} + +void TestWholeFloatDefault_set_field(TestWholeFloatDefault_ptr p, float field) +{ + capn_write32(p.p, 0, capn_from_f32(field) ^ 0x42f60000u); +} + +void TestWholeFloatDefault_set_bigField(TestWholeFloatDefault_ptr p, float bigField) +{ + capn_write32(p.p, 4, capn_from_f32(bigField) ^ 0x71c9f2cau); +} + +TestEmptyStruct_ptr new_TestEmptyStruct(struct capn_segment *s) { + TestEmptyStruct_ptr p; + p.p = capn_new_struct(s, 0, 0); + return p; +} +TestEmptyStruct_list new_TestEmptyStruct_list(struct capn_segment *s, int len) { + TestEmptyStruct_list p; + p.p = capn_new_list(s, len, 0, 0); + return p; +} +void read_TestEmptyStruct(struct TestEmptyStruct *s capnp_unused, TestEmptyStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void write_TestEmptyStruct(const struct TestEmptyStruct *s capnp_unused, TestEmptyStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void get_TestEmptyStruct(struct TestEmptyStruct *s, TestEmptyStruct_list l, int i) { + TestEmptyStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestEmptyStruct(s, p); +} +void set_TestEmptyStruct(const struct TestEmptyStruct *s, TestEmptyStruct_list l, int i) { + TestEmptyStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestEmptyStruct(s, p); +} + +TestConstants_ptr new_TestConstants(struct capn_segment *s) { + TestConstants_ptr p; + p.p = capn_new_struct(s, 0, 0); + return p; +} +TestConstants_list new_TestConstants_list(struct capn_segment *s, int len) { + TestConstants_list p; + p.p = capn_new_list(s, len, 0, 0); + return p; +} +void read_TestConstants(struct TestConstants *s capnp_unused, TestConstants_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void write_TestConstants(const struct TestConstants *s capnp_unused, TestConstants_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void get_TestConstants(struct TestConstants *s, TestConstants_list l, int i) { + TestConstants_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestConstants(s, p); +} +void set_TestConstants(const struct TestConstants *s, TestConstants_list l, int i) { + TestConstants_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestConstants(s, p); +} + +TestSturdyRef_ptr new_TestSturdyRef(struct capn_segment *s) { + TestSturdyRef_ptr p; + p.p = capn_new_struct(s, 0, 2); + return p; +} +TestSturdyRef_list new_TestSturdyRef_list(struct capn_segment *s, int len) { + TestSturdyRef_list p; + p.p = capn_new_list(s, len, 0, 2); + return p; +} +void read_TestSturdyRef(struct TestSturdyRef *s capnp_unused, TestSturdyRef_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->hostId.p = capn_getp(p.p, 0, 0); + s->objectId = capn_getp(p.p, 1, 0); +} +void write_TestSturdyRef(const struct TestSturdyRef *s capnp_unused, TestSturdyRef_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_setp(p.p, 0, s->hostId.p); + capn_setp(p.p, 1, s->objectId); +} +void get_TestSturdyRef(struct TestSturdyRef *s, TestSturdyRef_list l, int i) { + TestSturdyRef_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestSturdyRef(s, p); +} +void set_TestSturdyRef(const struct TestSturdyRef *s, TestSturdyRef_list l, int i) { + TestSturdyRef_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestSturdyRef(s, p); +} + +TestSturdyRefHostId_ptr TestSturdyRef_get_hostId(TestSturdyRef_ptr p) +{ + TestSturdyRefHostId_ptr hostId; + hostId.p = capn_getp(p.p, 0, 0); + return hostId; +} + +capn_ptr TestSturdyRef_get_objectId(TestSturdyRef_ptr p) +{ + capn_ptr objectId; + objectId = capn_getp(p.p, 1, 0); + return objectId; +} + +void TestSturdyRef_set_hostId(TestSturdyRef_ptr p, TestSturdyRefHostId_ptr hostId) +{ + capn_setp(p.p, 0, hostId.p); +} + +void TestSturdyRef_set_objectId(TestSturdyRef_ptr p, capn_ptr objectId) +{ + capn_setp(p.p, 1, objectId); +} + +TestSturdyRefHostId_ptr new_TestSturdyRefHostId(struct capn_segment *s) { + TestSturdyRefHostId_ptr p; + p.p = capn_new_struct(s, 0, 1); + return p; +} +TestSturdyRefHostId_list new_TestSturdyRefHostId_list(struct capn_segment *s, int len) { + TestSturdyRefHostId_list p; + p.p = capn_new_list(s, len, 0, 1); + return p; +} +void read_TestSturdyRefHostId(struct TestSturdyRefHostId *s capnp_unused, TestSturdyRefHostId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->host = capn_get_text(p.p, 0, capn_val0); +} +void write_TestSturdyRefHostId(const struct TestSturdyRefHostId *s capnp_unused, TestSturdyRefHostId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_set_text(p.p, 0, s->host); +} +void get_TestSturdyRefHostId(struct TestSturdyRefHostId *s, TestSturdyRefHostId_list l, int i) { + TestSturdyRefHostId_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestSturdyRefHostId(s, p); +} +void set_TestSturdyRefHostId(const struct TestSturdyRefHostId *s, TestSturdyRefHostId_list l, int i) { + TestSturdyRefHostId_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestSturdyRefHostId(s, p); +} + +capn_text TestSturdyRefHostId_get_host(TestSturdyRefHostId_ptr p) +{ + capn_text host; + host = capn_get_text(p.p, 0, capn_val0); + return host; +} + +void TestSturdyRefHostId_set_host(TestSturdyRefHostId_ptr p, capn_text host) +{ + capn_set_text(p.p, 0, host); +} + +TestSturdyRefObjectId_ptr new_TestSturdyRefObjectId(struct capn_segment *s) { + TestSturdyRefObjectId_ptr p; + p.p = capn_new_struct(s, 8, 0); + return p; +} +TestSturdyRefObjectId_list new_TestSturdyRefObjectId_list(struct capn_segment *s, int len) { + TestSturdyRefObjectId_list p; + p.p = capn_new_list(s, len, 8, 0); + return p; +} +void read_TestSturdyRefObjectId(struct TestSturdyRefObjectId *s capnp_unused, TestSturdyRefObjectId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->tag = (enum TestSturdyRefObjectId_Tag)(int) capn_read16(p.p, 0); +} +void write_TestSturdyRefObjectId(const struct TestSturdyRefObjectId *s capnp_unused, TestSturdyRefObjectId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 0, (uint16_t) (s->tag)); +} +void get_TestSturdyRefObjectId(struct TestSturdyRefObjectId *s, TestSturdyRefObjectId_list l, int i) { + TestSturdyRefObjectId_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestSturdyRefObjectId(s, p); +} +void set_TestSturdyRefObjectId(const struct TestSturdyRefObjectId *s, TestSturdyRefObjectId_list l, int i) { + TestSturdyRefObjectId_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestSturdyRefObjectId(s, p); +} + +enum TestSturdyRefObjectId_Tag TestSturdyRefObjectId_get_tag(TestSturdyRefObjectId_ptr p) +{ + enum TestSturdyRefObjectId_Tag tag; + tag = (enum TestSturdyRefObjectId_Tag)(int) capn_read16(p.p, 0); + return tag; +} + +void TestSturdyRefObjectId_set_tag(TestSturdyRefObjectId_ptr p, enum TestSturdyRefObjectId_Tag tag) +{ + capn_write16(p.p, 0, (uint16_t) (tag)); +} + +TestProvisionId_ptr new_TestProvisionId(struct capn_segment *s) { + TestProvisionId_ptr p; + p.p = capn_new_struct(s, 0, 0); + return p; +} +TestProvisionId_list new_TestProvisionId_list(struct capn_segment *s, int len) { + TestProvisionId_list p; + p.p = capn_new_list(s, len, 0, 0); + return p; +} +void read_TestProvisionId(struct TestProvisionId *s capnp_unused, TestProvisionId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void write_TestProvisionId(const struct TestProvisionId *s capnp_unused, TestProvisionId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void get_TestProvisionId(struct TestProvisionId *s, TestProvisionId_list l, int i) { + TestProvisionId_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestProvisionId(s, p); +} +void set_TestProvisionId(const struct TestProvisionId *s, TestProvisionId_list l, int i) { + TestProvisionId_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestProvisionId(s, p); +} + +TestRecipientId_ptr new_TestRecipientId(struct capn_segment *s) { + TestRecipientId_ptr p; + p.p = capn_new_struct(s, 0, 0); + return p; +} +TestRecipientId_list new_TestRecipientId_list(struct capn_segment *s, int len) { + TestRecipientId_list p; + p.p = capn_new_list(s, len, 0, 0); + return p; +} +void read_TestRecipientId(struct TestRecipientId *s capnp_unused, TestRecipientId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void write_TestRecipientId(const struct TestRecipientId *s capnp_unused, TestRecipientId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void get_TestRecipientId(struct TestRecipientId *s, TestRecipientId_list l, int i) { + TestRecipientId_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestRecipientId(s, p); +} +void set_TestRecipientId(const struct TestRecipientId *s, TestRecipientId_list l, int i) { + TestRecipientId_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestRecipientId(s, p); +} + +TestThirdPartyCapId_ptr new_TestThirdPartyCapId(struct capn_segment *s) { + TestThirdPartyCapId_ptr p; + p.p = capn_new_struct(s, 0, 0); + return p; +} +TestThirdPartyCapId_list new_TestThirdPartyCapId_list(struct capn_segment *s, int len) { + TestThirdPartyCapId_list p; + p.p = capn_new_list(s, len, 0, 0); + return p; +} +void read_TestThirdPartyCapId(struct TestThirdPartyCapId *s capnp_unused, TestThirdPartyCapId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void write_TestThirdPartyCapId(const struct TestThirdPartyCapId *s capnp_unused, TestThirdPartyCapId_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void get_TestThirdPartyCapId(struct TestThirdPartyCapId *s, TestThirdPartyCapId_list l, int i) { + TestThirdPartyCapId_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestThirdPartyCapId(s, p); +} +void set_TestThirdPartyCapId(const struct TestThirdPartyCapId *s, TestThirdPartyCapId_list l, int i) { + TestThirdPartyCapId_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestThirdPartyCapId(s, p); +} + +TestJoinResult_ptr new_TestJoinResult(struct capn_segment *s) { + TestJoinResult_ptr p; + p.p = capn_new_struct(s, 0, 0); + return p; +} +TestJoinResult_list new_TestJoinResult_list(struct capn_segment *s, int len) { + TestJoinResult_list p; + p.p = capn_new_list(s, len, 0, 0); + return p; +} +void read_TestJoinResult(struct TestJoinResult *s capnp_unused, TestJoinResult_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void write_TestJoinResult(const struct TestJoinResult *s capnp_unused, TestJoinResult_ptr p) { + capn_resolve(&p.p); + capnp_use(s); +} +void get_TestJoinResult(struct TestJoinResult *s, TestJoinResult_list l, int i) { + TestJoinResult_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestJoinResult(s, p); +} +void set_TestJoinResult(const struct TestJoinResult *s, TestJoinResult_list l, int i) { + TestJoinResult_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestJoinResult(s, p); +} + +TestNameAnnotation_ptr new_TestNameAnnotation(struct capn_segment *s) { + TestNameAnnotation_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestNameAnnotation_list new_TestNameAnnotation_list(struct capn_segment *s, int len) { + TestNameAnnotation_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestNameAnnotation(struct TestNameAnnotation *s capnp_unused, TestNameAnnotation_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->which = (enum TestNameAnnotation_which)(int) capn_read16(p.p, 2); + switch (s->which) { + case TestNameAnnotation_badFieldName: + s->badFieldName = (capn_read8(p.p, 0) & 1) != 0; + break; + case TestNameAnnotation_bar: + s->bar = (int8_t) ((int8_t)capn_read8(p.p, 0)); + break; + default: + break; + } + s->anotherBadFieldName = (enum TestNameAnnotation_BadlyNamedEnum)(int) capn_read16(p.p, 4); + s->badlyNamedUnion_which = (enum TestNameAnnotation_badlyNamedUnion_which)(int) capn_read16(p.p, 6); + switch (s->badlyNamedUnion_which) { + case TestNameAnnotation_badlyNamedUnion_baz: + s->badlyNamedUnion.baz.p = capn_getp(p.p, 0, 0); + break; + case TestNameAnnotation_badlyNamedUnion_badlyNamedGroup: + break; + default: + break; + } +} +void write_TestNameAnnotation(const struct TestNameAnnotation *s capnp_unused, TestNameAnnotation_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write16(p.p, 2, s->which); + switch (s->which) { + case TestNameAnnotation_badFieldName: + capn_write1(p.p, 0, s->badFieldName != 0); + break; + case TestNameAnnotation_bar: + capn_write8(p.p, 0, (uint8_t) (s->bar)); + break; + default: + break; + } + capn_write16(p.p, 4, (uint16_t) (s->anotherBadFieldName)); + capn_write16(p.p, 6, s->badlyNamedUnion_which); + switch (s->badlyNamedUnion_which) { + case TestNameAnnotation_badlyNamedUnion_baz: + capn_setp(p.p, 0, s->badlyNamedUnion.baz.p); + break; + case TestNameAnnotation_badlyNamedUnion_badlyNamedGroup: + break; + default: + break; + } +} +void get_TestNameAnnotation(struct TestNameAnnotation *s, TestNameAnnotation_list l, int i) { + TestNameAnnotation_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestNameAnnotation(s, p); +} +void set_TestNameAnnotation(const struct TestNameAnnotation *s, TestNameAnnotation_list l, int i) { + TestNameAnnotation_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestNameAnnotation(s, p); +} + +TestNameAnnotation_NestedStruct_ptr new_TestNameAnnotation_NestedStruct(struct capn_segment *s) { + TestNameAnnotation_NestedStruct_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +TestNameAnnotation_NestedStruct_list new_TestNameAnnotation_NestedStruct_list(struct capn_segment *s, int len) { + TestNameAnnotation_NestedStruct_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_TestNameAnnotation_NestedStruct(struct TestNameAnnotation_NestedStruct *s capnp_unused, TestNameAnnotation_NestedStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + s->badNestedFieldName = (capn_read8(p.p, 0) & 1) != 0; + s->anotherBadNestedFieldName.p = capn_getp(p.p, 0, 0); +} +void write_TestNameAnnotation_NestedStruct(const struct TestNameAnnotation_NestedStruct *s capnp_unused, TestNameAnnotation_NestedStruct_ptr p) { + capn_resolve(&p.p); + capnp_use(s); + capn_write1(p.p, 0, s->badNestedFieldName != 0); + capn_setp(p.p, 0, s->anotherBadNestedFieldName.p); +} +void get_TestNameAnnotation_NestedStruct(struct TestNameAnnotation_NestedStruct *s, TestNameAnnotation_NestedStruct_list l, int i) { + TestNameAnnotation_NestedStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + read_TestNameAnnotation_NestedStruct(s, p); +} +void set_TestNameAnnotation_NestedStruct(const struct TestNameAnnotation_NestedStruct *s, TestNameAnnotation_NestedStruct_list l, int i) { + TestNameAnnotation_NestedStruct_ptr p; + p.p = capn_getp(l.p, i, 0); + write_TestNameAnnotation_NestedStruct(s, p); +} + +unsigned TestNameAnnotation_NestedStruct_get_badNestedFieldName(TestNameAnnotation_NestedStruct_ptr p) +{ + unsigned badNestedFieldName; + badNestedFieldName = (capn_read8(p.p, 0) & 1) != 0; + return badNestedFieldName; +} + +TestNameAnnotation_NestedStruct_ptr TestNameAnnotation_NestedStruct_get_anotherBadNestedFieldName(TestNameAnnotation_NestedStruct_ptr p) +{ + TestNameAnnotation_NestedStruct_ptr anotherBadNestedFieldName; + anotherBadNestedFieldName.p = capn_getp(p.p, 0, 0); + return anotherBadNestedFieldName; +} + +void TestNameAnnotation_NestedStruct_set_badNestedFieldName(TestNameAnnotation_NestedStruct_ptr p, unsigned badNestedFieldName) +{ + capn_write1(p.p, 0, badNestedFieldName != 0); +} + +void TestNameAnnotation_NestedStruct_set_anotherBadNestedFieldName(TestNameAnnotation_NestedStruct_ptr p, TestNameAnnotation_NestedStruct_ptr anotherBadNestedFieldName) +{ + capn_setp(p.p, 0, anotherBadNestedFieldName.p); +} diff --git a/src/subprojects/c-capnproto/compiler/test.capnp.h b/src/subprojects/c-capnproto/compiler/test.capnp.h new file mode 100644 index 00000000..a33dfd58 --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/test.capnp.h @@ -0,0 +1,2056 @@ +#ifndef CAPN_D508EEBDC2DC42B8 +#define CAPN_D508EEBDC2DC42B8 +/* AUTO GENERATED - DO NOT EDIT */ +#include + +#if CAPN_VERSION != 1 +#error "version mismatch between capnp_c.h and generated code" +#endif + +#ifndef capnp_nowarn +# ifdef __GNUC__ +# define capnp_nowarn __extension__ +# else +# define capnp_nowarn +# endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +struct TestAllTypes; +struct TestDefaults; +struct TestAnyPointer; +struct TestOutOfOrder; +struct TestUnion; +struct TestUnnamedUnion; +struct TestUnionInUnion; +struct TestGroups; +struct TestInterleavedGroups; +struct TestUnionDefaults; +struct TestNestedTypes; +struct TestNestedTypes_NestedStruct; +struct TestUsing; +struct TestLists; +struct TestLists_Struct0; +struct TestLists_Struct1; +struct TestLists_Struct8; +struct TestLists_Struct16; +struct TestLists_Struct32; +struct TestLists_Struct64; +struct TestLists_StructP; +struct TestLists_Struct0c; +struct TestLists_Struct1c; +struct TestLists_Struct8c; +struct TestLists_Struct16c; +struct TestLists_Struct32c; +struct TestLists_Struct64c; +struct TestLists_StructPc; +struct TestFieldZeroIsBit; +struct TestListDefaults; +struct TestLateUnion; +struct TestOldVersion; +struct TestNewVersion; +struct TestStructUnion; +struct TestStructUnion_SomeStruct; +struct TestPrintInlineStructs; +struct TestPrintInlineStructs_InlineStruct; +struct TestWholeFloatDefault; +struct TestEmptyStruct; +struct TestConstants; +struct TestSturdyRef; +struct TestSturdyRefHostId; +struct TestSturdyRefObjectId; +struct TestProvisionId; +struct TestRecipientId; +struct TestThirdPartyCapId; +struct TestJoinResult; +struct TestNameAnnotation; +struct TestNameAnnotation_NestedStruct; + +typedef struct {capn_ptr p;} TestAllTypes_ptr; +typedef struct {capn_ptr p;} TestDefaults_ptr; +typedef struct {capn_ptr p;} TestAnyPointer_ptr; +typedef struct {capn_ptr p;} TestOutOfOrder_ptr; +typedef struct {capn_ptr p;} TestUnion_ptr; +typedef struct {capn_ptr p;} TestUnnamedUnion_ptr; +typedef struct {capn_ptr p;} TestUnionInUnion_ptr; +typedef struct {capn_ptr p;} TestGroups_ptr; +typedef struct {capn_ptr p;} TestInterleavedGroups_ptr; +typedef struct {capn_ptr p;} TestUnionDefaults_ptr; +typedef struct {capn_ptr p;} TestNestedTypes_ptr; +typedef struct {capn_ptr p;} TestNestedTypes_NestedStruct_ptr; +typedef struct {capn_ptr p;} TestUsing_ptr; +typedef struct {capn_ptr p;} TestLists_ptr; +typedef struct {capn_ptr p;} TestLists_Struct0_ptr; +typedef struct {capn_ptr p;} TestLists_Struct1_ptr; +typedef struct {capn_ptr p;} TestLists_Struct8_ptr; +typedef struct {capn_ptr p;} TestLists_Struct16_ptr; +typedef struct {capn_ptr p;} TestLists_Struct32_ptr; +typedef struct {capn_ptr p;} TestLists_Struct64_ptr; +typedef struct {capn_ptr p;} TestLists_StructP_ptr; +typedef struct {capn_ptr p;} TestLists_Struct0c_ptr; +typedef struct {capn_ptr p;} TestLists_Struct1c_ptr; +typedef struct {capn_ptr p;} TestLists_Struct8c_ptr; +typedef struct {capn_ptr p;} TestLists_Struct16c_ptr; +typedef struct {capn_ptr p;} TestLists_Struct32c_ptr; +typedef struct {capn_ptr p;} TestLists_Struct64c_ptr; +typedef struct {capn_ptr p;} TestLists_StructPc_ptr; +typedef struct {capn_ptr p;} TestFieldZeroIsBit_ptr; +typedef struct {capn_ptr p;} TestListDefaults_ptr; +typedef struct {capn_ptr p;} TestLateUnion_ptr; +typedef struct {capn_ptr p;} TestOldVersion_ptr; +typedef struct {capn_ptr p;} TestNewVersion_ptr; +typedef struct {capn_ptr p;} TestStructUnion_ptr; +typedef struct {capn_ptr p;} TestStructUnion_SomeStruct_ptr; +typedef struct {capn_ptr p;} TestPrintInlineStructs_ptr; +typedef struct {capn_ptr p;} TestPrintInlineStructs_InlineStruct_ptr; +typedef struct {capn_ptr p;} TestWholeFloatDefault_ptr; +typedef struct {capn_ptr p;} TestEmptyStruct_ptr; +typedef struct {capn_ptr p;} TestConstants_ptr; +typedef struct {capn_ptr p;} TestSturdyRef_ptr; +typedef struct {capn_ptr p;} TestSturdyRefHostId_ptr; +typedef struct {capn_ptr p;} TestSturdyRefObjectId_ptr; +typedef struct {capn_ptr p;} TestProvisionId_ptr; +typedef struct {capn_ptr p;} TestRecipientId_ptr; +typedef struct {capn_ptr p;} TestThirdPartyCapId_ptr; +typedef struct {capn_ptr p;} TestJoinResult_ptr; +typedef struct {capn_ptr p;} TestNameAnnotation_ptr; +typedef struct {capn_ptr p;} TestNameAnnotation_NestedStruct_ptr; + +typedef struct {capn_ptr p;} TestAllTypes_list; +typedef struct {capn_ptr p;} TestDefaults_list; +typedef struct {capn_ptr p;} TestAnyPointer_list; +typedef struct {capn_ptr p;} TestOutOfOrder_list; +typedef struct {capn_ptr p;} TestUnion_list; +typedef struct {capn_ptr p;} TestUnnamedUnion_list; +typedef struct {capn_ptr p;} TestUnionInUnion_list; +typedef struct {capn_ptr p;} TestGroups_list; +typedef struct {capn_ptr p;} TestInterleavedGroups_list; +typedef struct {capn_ptr p;} TestUnionDefaults_list; +typedef struct {capn_ptr p;} TestNestedTypes_list; +typedef struct {capn_ptr p;} TestNestedTypes_NestedStruct_list; +typedef struct {capn_ptr p;} TestUsing_list; +typedef struct {capn_ptr p;} TestLists_list; +typedef struct {capn_ptr p;} TestLists_Struct0_list; +typedef struct {capn_ptr p;} TestLists_Struct1_list; +typedef struct {capn_ptr p;} TestLists_Struct8_list; +typedef struct {capn_ptr p;} TestLists_Struct16_list; +typedef struct {capn_ptr p;} TestLists_Struct32_list; +typedef struct {capn_ptr p;} TestLists_Struct64_list; +typedef struct {capn_ptr p;} TestLists_StructP_list; +typedef struct {capn_ptr p;} TestLists_Struct0c_list; +typedef struct {capn_ptr p;} TestLists_Struct1c_list; +typedef struct {capn_ptr p;} TestLists_Struct8c_list; +typedef struct {capn_ptr p;} TestLists_Struct16c_list; +typedef struct {capn_ptr p;} TestLists_Struct32c_list; +typedef struct {capn_ptr p;} TestLists_Struct64c_list; +typedef struct {capn_ptr p;} TestLists_StructPc_list; +typedef struct {capn_ptr p;} TestFieldZeroIsBit_list; +typedef struct {capn_ptr p;} TestListDefaults_list; +typedef struct {capn_ptr p;} TestLateUnion_list; +typedef struct {capn_ptr p;} TestOldVersion_list; +typedef struct {capn_ptr p;} TestNewVersion_list; +typedef struct {capn_ptr p;} TestStructUnion_list; +typedef struct {capn_ptr p;} TestStructUnion_SomeStruct_list; +typedef struct {capn_ptr p;} TestPrintInlineStructs_list; +typedef struct {capn_ptr p;} TestPrintInlineStructs_InlineStruct_list; +typedef struct {capn_ptr p;} TestWholeFloatDefault_list; +typedef struct {capn_ptr p;} TestEmptyStruct_list; +typedef struct {capn_ptr p;} TestConstants_list; +typedef struct {capn_ptr p;} TestSturdyRef_list; +typedef struct {capn_ptr p;} TestSturdyRefHostId_list; +typedef struct {capn_ptr p;} TestSturdyRefObjectId_list; +typedef struct {capn_ptr p;} TestProvisionId_list; +typedef struct {capn_ptr p;} TestRecipientId_list; +typedef struct {capn_ptr p;} TestThirdPartyCapId_list; +typedef struct {capn_ptr p;} TestJoinResult_list; +typedef struct {capn_ptr p;} TestNameAnnotation_list; +typedef struct {capn_ptr p;} TestNameAnnotation_NestedStruct_list; + +enum TestEnum { + TestEnum_foo = 0, + TestEnum_bar = 1, + TestEnum_baz = 2, + TestEnum_qux = 3, + TestEnum_quux = 4, + TestEnum_corge = 5, + TestEnum_grault = 6, + TestEnum_garply = 7 +}; + +enum TestNestedTypes_NestedEnum { + TestNestedTypes_NestedEnum_foo = 0, + TestNestedTypes_NestedEnum_bar = 1 +}; + +enum TestNestedTypes_NestedStruct_NestedEnum { + TestNestedTypes_NestedStruct_NestedEnum_baz = 0, + TestNestedTypes_NestedStruct_NestedEnum_qux = 1, + TestNestedTypes_NestedStruct_NestedEnum_quux = 2 +}; + +enum TestSturdyRefObjectId_Tag { + TestSturdyRefObjectId_Tag_testInterface = 0, + TestSturdyRefObjectId_Tag_testExtends = 1, + TestSturdyRefObjectId_Tag_testPipeline = 2, + TestSturdyRefObjectId_Tag_testTailCallee = 3, + TestSturdyRefObjectId_Tag_testTailCaller = 4, + TestSturdyRefObjectId_Tag_testMoreStuff = 5 +}; + +enum TestNameAnnotation_BadlyNamedEnum { + TestNameAnnotation_BadlyNamedEnum_foo = 0, + TestNameAnnotation_BadlyNamedEnum_bar = 1, + TestNameAnnotation_BadlyNamedEnum_baz = 2 +}; + +enum TestNameAnnotation_NestedStruct_DeeplyNestedEnum { + TestNameAnnotation_NestedStruct_DeeplyNestedEnum_quux = 0, + TestNameAnnotation_NestedStruct_DeeplyNestedEnum_corge = 1, + TestNameAnnotation_NestedStruct_DeeplyNestedEnum_grault = 2 +}; +extern union capn_conv_f32 TestWholeFloatDefault_constant; +extern union capn_conv_f32 TestWholeFloatDefault_bigConstant; +extern unsigned TestConstants_boolConst; +extern int8_t TestConstants_int8Const; +extern int16_t TestConstants_int16Const; +extern int32_t TestConstants_int32Const; +extern int64_t TestConstants_int64Const; +extern uint8_t TestConstants_uint8Const; +extern uint16_t TestConstants_uint16Const; +extern uint32_t TestConstants_uint32Const; +extern uint64_t TestConstants_uint64Const; +extern union capn_conv_f32 TestConstants_float32Const; +extern union capn_conv_f64 TestConstants_float64Const; +extern capn_text TestConstants_textConst; +extern capn_data TestConstants_dataConst; +extern TestAllTypes_ptr TestConstants_structConst; +extern enum TestEnum TestConstants_enumConst; +extern capn_ptr TestConstants_voidListConst; +extern capn_list1 TestConstants_boolListConst; +extern capn_list8 TestConstants_int8ListConst; +extern capn_list16 TestConstants_int16ListConst; +extern capn_list32 TestConstants_int32ListConst; +extern capn_list64 TestConstants_int64ListConst; +extern capn_list8 TestConstants_uint8ListConst; +extern capn_list16 TestConstants_uint16ListConst; +extern capn_list32 TestConstants_uint32ListConst; +extern capn_list64 TestConstants_uint64ListConst; +extern capn_list32 TestConstants_float32ListConst; +extern capn_list64 TestConstants_float64ListConst; +extern capn_ptr TestConstants_textListConst; +extern capn_ptr TestConstants_dataListConst; +extern TestAllTypes_list TestConstants_structListConst; +extern capn_list16 TestConstants_enumListConst; +extern uint32_t globalInt; +extern capn_text globalText; +extern TestAllTypes_ptr globalStruct; +extern TestPrintInlineStructs_ptr globalPrintableStruct; +extern TestAllTypes_ptr derivedConstant; + +struct TestAllTypes { + unsigned boolField : 1; + int8_t int8Field; + int16_t int16Field; + int32_t int32Field; + int64_t int64Field; + uint8_t uInt8Field; + uint16_t uInt16Field; + uint32_t uInt32Field; + uint64_t uInt64Field; + float float32Field; + double float64Field; + capn_text textField; + capn_data dataField; + TestAllTypes_ptr structField; + enum TestEnum enumField; + capn_ptr voidList; + capn_list1 boolList; + capn_list8 int8List; + capn_list16 int16List; + capn_list32 int32List; + capn_list64 int64List; + capn_list8 uInt8List; + capn_list16 uInt16List; + capn_list32 uInt32List; + capn_list64 uInt64List; + capn_list32 float32List; + capn_list64 float64List; + capn_ptr textList; + capn_ptr dataList; + TestAllTypes_list structList; + capn_list16 enumList; + capn_ptr interfaceList; +}; + +static const size_t TestAllTypes_word_count = 6; + +static const size_t TestAllTypes_pointer_count = 20; + +static const size_t TestAllTypes_struct_bytes_count = 208; + + +unsigned TestAllTypes_get_boolField(TestAllTypes_ptr p); + +int8_t TestAllTypes_get_int8Field(TestAllTypes_ptr p); + +int16_t TestAllTypes_get_int16Field(TestAllTypes_ptr p); + +int32_t TestAllTypes_get_int32Field(TestAllTypes_ptr p); + +int64_t TestAllTypes_get_int64Field(TestAllTypes_ptr p); + +uint8_t TestAllTypes_get_uInt8Field(TestAllTypes_ptr p); + +uint16_t TestAllTypes_get_uInt16Field(TestAllTypes_ptr p); + +uint32_t TestAllTypes_get_uInt32Field(TestAllTypes_ptr p); + +uint64_t TestAllTypes_get_uInt64Field(TestAllTypes_ptr p); + +float TestAllTypes_get_float32Field(TestAllTypes_ptr p); + +double TestAllTypes_get_float64Field(TestAllTypes_ptr p); + +capn_text TestAllTypes_get_textField(TestAllTypes_ptr p); + +capn_data TestAllTypes_get_dataField(TestAllTypes_ptr p); + +TestAllTypes_ptr TestAllTypes_get_structField(TestAllTypes_ptr p); + +enum TestEnum TestAllTypes_get_enumField(TestAllTypes_ptr p); + +capn_ptr TestAllTypes_get_voidList(TestAllTypes_ptr p); + +capn_list1 TestAllTypes_get_boolList(TestAllTypes_ptr p); + +capn_list8 TestAllTypes_get_int8List(TestAllTypes_ptr p); + +capn_list16 TestAllTypes_get_int16List(TestAllTypes_ptr p); + +capn_list32 TestAllTypes_get_int32List(TestAllTypes_ptr p); + +capn_list64 TestAllTypes_get_int64List(TestAllTypes_ptr p); + +capn_list8 TestAllTypes_get_uInt8List(TestAllTypes_ptr p); + +capn_list16 TestAllTypes_get_uInt16List(TestAllTypes_ptr p); + +capn_list32 TestAllTypes_get_uInt32List(TestAllTypes_ptr p); + +capn_list64 TestAllTypes_get_uInt64List(TestAllTypes_ptr p); + +capn_list32 TestAllTypes_get_float32List(TestAllTypes_ptr p); + +capn_list64 TestAllTypes_get_float64List(TestAllTypes_ptr p); + +capn_ptr TestAllTypes_get_textList(TestAllTypes_ptr p); + +capn_ptr TestAllTypes_get_dataList(TestAllTypes_ptr p); + +TestAllTypes_list TestAllTypes_get_structList(TestAllTypes_ptr p); + +capn_list16 TestAllTypes_get_enumList(TestAllTypes_ptr p); + +capn_ptr TestAllTypes_get_interfaceList(TestAllTypes_ptr p); + +void TestAllTypes_set_boolField(TestAllTypes_ptr p, unsigned boolField); + +void TestAllTypes_set_int8Field(TestAllTypes_ptr p, int8_t int8Field); + +void TestAllTypes_set_int16Field(TestAllTypes_ptr p, int16_t int16Field); + +void TestAllTypes_set_int32Field(TestAllTypes_ptr p, int32_t int32Field); + +void TestAllTypes_set_int64Field(TestAllTypes_ptr p, int64_t int64Field); + +void TestAllTypes_set_uInt8Field(TestAllTypes_ptr p, uint8_t uInt8Field); + +void TestAllTypes_set_uInt16Field(TestAllTypes_ptr p, uint16_t uInt16Field); + +void TestAllTypes_set_uInt32Field(TestAllTypes_ptr p, uint32_t uInt32Field); + +void TestAllTypes_set_uInt64Field(TestAllTypes_ptr p, uint64_t uInt64Field); + +void TestAllTypes_set_float32Field(TestAllTypes_ptr p, float float32Field); + +void TestAllTypes_set_float64Field(TestAllTypes_ptr p, double float64Field); + +void TestAllTypes_set_textField(TestAllTypes_ptr p, capn_text textField); + +void TestAllTypes_set_dataField(TestAllTypes_ptr p, capn_data dataField); + +void TestAllTypes_set_structField(TestAllTypes_ptr p, TestAllTypes_ptr structField); + +void TestAllTypes_set_enumField(TestAllTypes_ptr p, enum TestEnum enumField); + +void TestAllTypes_set_voidList(TestAllTypes_ptr p, capn_ptr voidList); + +void TestAllTypes_set_boolList(TestAllTypes_ptr p, capn_list1 boolList); + +void TestAllTypes_set_int8List(TestAllTypes_ptr p, capn_list8 int8List); + +void TestAllTypes_set_int16List(TestAllTypes_ptr p, capn_list16 int16List); + +void TestAllTypes_set_int32List(TestAllTypes_ptr p, capn_list32 int32List); + +void TestAllTypes_set_int64List(TestAllTypes_ptr p, capn_list64 int64List); + +void TestAllTypes_set_uInt8List(TestAllTypes_ptr p, capn_list8 uInt8List); + +void TestAllTypes_set_uInt16List(TestAllTypes_ptr p, capn_list16 uInt16List); + +void TestAllTypes_set_uInt32List(TestAllTypes_ptr p, capn_list32 uInt32List); + +void TestAllTypes_set_uInt64List(TestAllTypes_ptr p, capn_list64 uInt64List); + +void TestAllTypes_set_float32List(TestAllTypes_ptr p, capn_list32 float32List); + +void TestAllTypes_set_float64List(TestAllTypes_ptr p, capn_list64 float64List); + +void TestAllTypes_set_textList(TestAllTypes_ptr p, capn_ptr textList); + +void TestAllTypes_set_dataList(TestAllTypes_ptr p, capn_ptr dataList); + +void TestAllTypes_set_structList(TestAllTypes_ptr p, TestAllTypes_list structList); + +void TestAllTypes_set_enumList(TestAllTypes_ptr p, capn_list16 enumList); + +void TestAllTypes_set_interfaceList(TestAllTypes_ptr p, capn_ptr interfaceList); + +struct TestDefaults { + unsigned boolField : 1; + int8_t int8Field; + int16_t int16Field; + int32_t int32Field; + int64_t int64Field; + uint8_t uInt8Field; + uint16_t uInt16Field; + uint32_t uInt32Field; + uint64_t uInt64Field; + float float32Field; + double float64Field; + capn_text textField; + capn_data dataField; + TestAllTypes_ptr structField; + enum TestEnum enumField; + capn_ptr voidList; + capn_list1 boolList; + capn_list8 int8List; + capn_list16 int16List; + capn_list32 int32List; + capn_list64 int64List; + capn_list8 uInt8List; + capn_list16 uInt16List; + capn_list32 uInt32List; + capn_list64 uInt64List; + capn_list32 float32List; + capn_list64 float64List; + capn_ptr textList; + capn_ptr dataList; + TestAllTypes_list structList; + capn_list16 enumList; + capn_ptr interfaceList; +}; + +static const size_t TestDefaults_word_count = 6; + +static const size_t TestDefaults_pointer_count = 20; + +static const size_t TestDefaults_struct_bytes_count = 208; + + +unsigned TestDefaults_get_boolField(TestDefaults_ptr p); + +int8_t TestDefaults_get_int8Field(TestDefaults_ptr p); + +int16_t TestDefaults_get_int16Field(TestDefaults_ptr p); + +int32_t TestDefaults_get_int32Field(TestDefaults_ptr p); + +int64_t TestDefaults_get_int64Field(TestDefaults_ptr p); + +uint8_t TestDefaults_get_uInt8Field(TestDefaults_ptr p); + +uint16_t TestDefaults_get_uInt16Field(TestDefaults_ptr p); + +uint32_t TestDefaults_get_uInt32Field(TestDefaults_ptr p); + +uint64_t TestDefaults_get_uInt64Field(TestDefaults_ptr p); + +float TestDefaults_get_float32Field(TestDefaults_ptr p); + +double TestDefaults_get_float64Field(TestDefaults_ptr p); + +capn_text TestDefaults_get_textField(TestDefaults_ptr p); + +capn_data TestDefaults_get_dataField(TestDefaults_ptr p); + +TestAllTypes_ptr TestDefaults_get_structField(TestDefaults_ptr p); + +enum TestEnum TestDefaults_get_enumField(TestDefaults_ptr p); + +capn_ptr TestDefaults_get_voidList(TestDefaults_ptr p); + +capn_list1 TestDefaults_get_boolList(TestDefaults_ptr p); + +capn_list8 TestDefaults_get_int8List(TestDefaults_ptr p); + +capn_list16 TestDefaults_get_int16List(TestDefaults_ptr p); + +capn_list32 TestDefaults_get_int32List(TestDefaults_ptr p); + +capn_list64 TestDefaults_get_int64List(TestDefaults_ptr p); + +capn_list8 TestDefaults_get_uInt8List(TestDefaults_ptr p); + +capn_list16 TestDefaults_get_uInt16List(TestDefaults_ptr p); + +capn_list32 TestDefaults_get_uInt32List(TestDefaults_ptr p); + +capn_list64 TestDefaults_get_uInt64List(TestDefaults_ptr p); + +capn_list32 TestDefaults_get_float32List(TestDefaults_ptr p); + +capn_list64 TestDefaults_get_float64List(TestDefaults_ptr p); + +capn_ptr TestDefaults_get_textList(TestDefaults_ptr p); + +capn_ptr TestDefaults_get_dataList(TestDefaults_ptr p); + +TestAllTypes_list TestDefaults_get_structList(TestDefaults_ptr p); + +capn_list16 TestDefaults_get_enumList(TestDefaults_ptr p); + +capn_ptr TestDefaults_get_interfaceList(TestDefaults_ptr p); + +void TestDefaults_set_boolField(TestDefaults_ptr p, unsigned boolField); + +void TestDefaults_set_int8Field(TestDefaults_ptr p, int8_t int8Field); + +void TestDefaults_set_int16Field(TestDefaults_ptr p, int16_t int16Field); + +void TestDefaults_set_int32Field(TestDefaults_ptr p, int32_t int32Field); + +void TestDefaults_set_int64Field(TestDefaults_ptr p, int64_t int64Field); + +void TestDefaults_set_uInt8Field(TestDefaults_ptr p, uint8_t uInt8Field); + +void TestDefaults_set_uInt16Field(TestDefaults_ptr p, uint16_t uInt16Field); + +void TestDefaults_set_uInt32Field(TestDefaults_ptr p, uint32_t uInt32Field); + +void TestDefaults_set_uInt64Field(TestDefaults_ptr p, uint64_t uInt64Field); + +void TestDefaults_set_float32Field(TestDefaults_ptr p, float float32Field); + +void TestDefaults_set_float64Field(TestDefaults_ptr p, double float64Field); + +void TestDefaults_set_textField(TestDefaults_ptr p, capn_text textField); + +void TestDefaults_set_dataField(TestDefaults_ptr p, capn_data dataField); + +void TestDefaults_set_structField(TestDefaults_ptr p, TestAllTypes_ptr structField); + +void TestDefaults_set_enumField(TestDefaults_ptr p, enum TestEnum enumField); + +void TestDefaults_set_voidList(TestDefaults_ptr p, capn_ptr voidList); + +void TestDefaults_set_boolList(TestDefaults_ptr p, capn_list1 boolList); + +void TestDefaults_set_int8List(TestDefaults_ptr p, capn_list8 int8List); + +void TestDefaults_set_int16List(TestDefaults_ptr p, capn_list16 int16List); + +void TestDefaults_set_int32List(TestDefaults_ptr p, capn_list32 int32List); + +void TestDefaults_set_int64List(TestDefaults_ptr p, capn_list64 int64List); + +void TestDefaults_set_uInt8List(TestDefaults_ptr p, capn_list8 uInt8List); + +void TestDefaults_set_uInt16List(TestDefaults_ptr p, capn_list16 uInt16List); + +void TestDefaults_set_uInt32List(TestDefaults_ptr p, capn_list32 uInt32List); + +void TestDefaults_set_uInt64List(TestDefaults_ptr p, capn_list64 uInt64List); + +void TestDefaults_set_float32List(TestDefaults_ptr p, capn_list32 float32List); + +void TestDefaults_set_float64List(TestDefaults_ptr p, capn_list64 float64List); + +void TestDefaults_set_textList(TestDefaults_ptr p, capn_ptr textList); + +void TestDefaults_set_dataList(TestDefaults_ptr p, capn_ptr dataList); + +void TestDefaults_set_structList(TestDefaults_ptr p, TestAllTypes_list structList); + +void TestDefaults_set_enumList(TestDefaults_ptr p, capn_list16 enumList); + +void TestDefaults_set_interfaceList(TestDefaults_ptr p, capn_ptr interfaceList); + +struct TestAnyPointer { + capn_ptr anyPointerField; +}; + +static const size_t TestAnyPointer_word_count = 0; + +static const size_t TestAnyPointer_pointer_count = 1; + +static const size_t TestAnyPointer_struct_bytes_count = 8; + + +capn_ptr TestAnyPointer_get_anyPointerField(TestAnyPointer_ptr p); + +void TestAnyPointer_set_anyPointerField(TestAnyPointer_ptr p, capn_ptr anyPointerField); + +struct TestOutOfOrder { + capn_text foo; + capn_text bar; + capn_text baz; + capn_text qux; + capn_text quux; + capn_text corge; + capn_text grault; + capn_text garply; + capn_text waldo; +}; + +static const size_t TestOutOfOrder_word_count = 0; + +static const size_t TestOutOfOrder_pointer_count = 9; + +static const size_t TestOutOfOrder_struct_bytes_count = 72; + + +capn_text TestOutOfOrder_get_foo(TestOutOfOrder_ptr p); + +capn_text TestOutOfOrder_get_bar(TestOutOfOrder_ptr p); + +capn_text TestOutOfOrder_get_baz(TestOutOfOrder_ptr p); + +capn_text TestOutOfOrder_get_qux(TestOutOfOrder_ptr p); + +capn_text TestOutOfOrder_get_quux(TestOutOfOrder_ptr p); + +capn_text TestOutOfOrder_get_corge(TestOutOfOrder_ptr p); + +capn_text TestOutOfOrder_get_grault(TestOutOfOrder_ptr p); + +capn_text TestOutOfOrder_get_garply(TestOutOfOrder_ptr p); + +capn_text TestOutOfOrder_get_waldo(TestOutOfOrder_ptr p); + +void TestOutOfOrder_set_foo(TestOutOfOrder_ptr p, capn_text foo); + +void TestOutOfOrder_set_bar(TestOutOfOrder_ptr p, capn_text bar); + +void TestOutOfOrder_set_baz(TestOutOfOrder_ptr p, capn_text baz); + +void TestOutOfOrder_set_qux(TestOutOfOrder_ptr p, capn_text qux); + +void TestOutOfOrder_set_quux(TestOutOfOrder_ptr p, capn_text quux); + +void TestOutOfOrder_set_corge(TestOutOfOrder_ptr p, capn_text corge); + +void TestOutOfOrder_set_grault(TestOutOfOrder_ptr p, capn_text grault); + +void TestOutOfOrder_set_garply(TestOutOfOrder_ptr p, capn_text garply); + +void TestOutOfOrder_set_waldo(TestOutOfOrder_ptr p, capn_text waldo); +enum TestUnion_union0_which { + TestUnion_union0_u0f0s0 = 0, + TestUnion_union0_u0f0s1 = 1, + TestUnion_union0_u0f0s8 = 2, + TestUnion_union0_u0f0s16 = 3, + TestUnion_union0_u0f0s32 = 4, + TestUnion_union0_u0f0s64 = 5, + TestUnion_union0_u0f0sp = 6, + TestUnion_union0_u0f1s0 = 7, + TestUnion_union0_u0f1s1 = 8, + TestUnion_union0_u0f1s8 = 9, + TestUnion_union0_u0f1s16 = 10, + TestUnion_union0_u0f1s32 = 11, + TestUnion_union0_u0f1s64 = 12, + TestUnion_union0_u0f1sp = 13 +}; +enum TestUnion_union1_which { + TestUnion_union1_u1f0s0 = 0, + TestUnion_union1_u1f0s1 = 1, + TestUnion_union1_u1f1s1 = 2, + TestUnion_union1_u1f0s8 = 3, + TestUnion_union1_u1f1s8 = 4, + TestUnion_union1_u1f0s16 = 5, + TestUnion_union1_u1f1s16 = 6, + TestUnion_union1_u1f0s32 = 7, + TestUnion_union1_u1f1s32 = 8, + TestUnion_union1_u1f0s64 = 9, + TestUnion_union1_u1f1s64 = 10, + TestUnion_union1_u1f0sp = 11, + TestUnion_union1_u1f1sp = 12, + TestUnion_union1_u1f2s0 = 13, + TestUnion_union1_u1f2s1 = 14, + TestUnion_union1_u1f2s8 = 15, + TestUnion_union1_u1f2s16 = 16, + TestUnion_union1_u1f2s32 = 17, + TestUnion_union1_u1f2s64 = 18, + TestUnion_union1_u1f2sp = 19 +}; +enum TestUnion_union2_which { + TestUnion_union2_u2f0s64 = 4, + TestUnion_union2_u2f0s32 = 3, + TestUnion_union2_u2f0s16 = 2, + TestUnion_union2_u2f0s8 = 1, + TestUnion_union2_u2f0s1 = 0 +}; +enum TestUnion_union3_which { + TestUnion_union3_u3f0s64 = 4, + TestUnion_union3_u3f0s32 = 3, + TestUnion_union3_u3f0s16 = 2, + TestUnion_union3_u3f0s8 = 1, + TestUnion_union3_u3f0s1 = 0 +}; + +struct TestUnion { + enum TestUnion_union0_which union0_which; + capnp_nowarn union { + unsigned u0f0s1 : 1; + int8_t u0f0s8; + int16_t u0f0s16; + int32_t u0f0s32; + int64_t u0f0s64; + capn_text u0f0sp; + unsigned u0f1s1 : 1; + int8_t u0f1s8; + int16_t u0f1s16; + int32_t u0f1s32; + int64_t u0f1s64; + capn_text u0f1sp; + } union0; + unsigned bit0 : 1; + enum TestUnion_union1_which union1_which; + capnp_nowarn union { + unsigned u1f0s1 : 1; + unsigned u1f1s1 : 1; + int8_t u1f0s8; + int8_t u1f1s8; + int16_t u1f0s16; + int16_t u1f1s16; + int32_t u1f0s32; + int32_t u1f1s32; + int64_t u1f0s64; + int64_t u1f1s64; + capn_text u1f0sp; + capn_text u1f1sp; + unsigned u1f2s1 : 1; + int8_t u1f2s8; + int16_t u1f2s16; + int32_t u1f2s32; + int64_t u1f2s64; + capn_text u1f2sp; + } union1; + unsigned bit2 : 1; + unsigned bit3 : 1; + unsigned bit4 : 1; + unsigned bit5 : 1; + unsigned bit6 : 1; + unsigned bit7 : 1; + enum TestUnion_union2_which union2_which; + capnp_nowarn union { + int64_t u2f0s64; + int32_t u2f0s32; + int16_t u2f0s16; + int8_t u2f0s8; + unsigned u2f0s1 : 1; + } union2; + enum TestUnion_union3_which union3_which; + capnp_nowarn union { + int64_t u3f0s64; + int32_t u3f0s32; + int16_t u3f0s16; + int8_t u3f0s8; + unsigned u3f0s1 : 1; + } union3; + uint8_t byte0; +}; + +static const size_t TestUnion_word_count = 8; + +static const size_t TestUnion_pointer_count = 2; + +static const size_t TestUnion_struct_bytes_count = 80; + + +unsigned TestUnion_get_bit0(TestUnion_ptr p); + +unsigned TestUnion_get_bit2(TestUnion_ptr p); + +unsigned TestUnion_get_bit3(TestUnion_ptr p); + +unsigned TestUnion_get_bit4(TestUnion_ptr p); + +unsigned TestUnion_get_bit5(TestUnion_ptr p); + +unsigned TestUnion_get_bit6(TestUnion_ptr p); + +unsigned TestUnion_get_bit7(TestUnion_ptr p); + +uint8_t TestUnion_get_byte0(TestUnion_ptr p); + +void TestUnion_set_bit0(TestUnion_ptr p, unsigned bit0); + +void TestUnion_set_bit2(TestUnion_ptr p, unsigned bit2); + +void TestUnion_set_bit3(TestUnion_ptr p, unsigned bit3); + +void TestUnion_set_bit4(TestUnion_ptr p, unsigned bit4); + +void TestUnion_set_bit5(TestUnion_ptr p, unsigned bit5); + +void TestUnion_set_bit6(TestUnion_ptr p, unsigned bit6); + +void TestUnion_set_bit7(TestUnion_ptr p, unsigned bit7); + +void TestUnion_set_byte0(TestUnion_ptr p, uint8_t byte0); +enum TestUnnamedUnion_which { + TestUnnamedUnion_foo = 0, + TestUnnamedUnion_bar = 1 +}; + +struct TestUnnamedUnion { + capn_text before; + enum TestUnnamedUnion_which which; + capnp_nowarn union { + uint16_t foo; + uint32_t bar; + }; + uint16_t middle; + capn_text after; +}; + +static const size_t TestUnnamedUnion_word_count = 2; + +static const size_t TestUnnamedUnion_pointer_count = 2; + +static const size_t TestUnnamedUnion_struct_bytes_count = 32; + + +capn_text TestUnnamedUnion_get_before(TestUnnamedUnion_ptr p); + +void TestUnnamedUnion_set_before(TestUnnamedUnion_ptr p, capn_text before); +enum TestUnionInUnion_outer_inner_which { + TestUnionInUnion_outer_inner_foo = 0, + TestUnionInUnion_outer_inner_bar = 1 +}; +enum TestUnionInUnion_outer_which { + TestUnionInUnion_outer_inner = 0, + TestUnionInUnion_outer_baz = 1 +}; + +struct TestUnionInUnion { + enum TestUnionInUnion_outer_which outer_which; + capnp_nowarn union { + capnp_nowarn struct { + enum TestUnionInUnion_outer_inner_which which; + capnp_nowarn union { + int32_t foo; + int32_t bar; + }; + } inner; + int32_t baz; + } outer; +}; + +static const size_t TestUnionInUnion_word_count = 2; + +static const size_t TestUnionInUnion_pointer_count = 0; + +static const size_t TestUnionInUnion_struct_bytes_count = 16; + +enum TestGroups_groups_which { + TestGroups_groups_foo = 0, + TestGroups_groups_bar = 2, + TestGroups_groups_baz = 1 +}; + +struct TestGroups { + enum TestGroups_groups_which groups_which; + capnp_nowarn union { + capnp_nowarn struct { + int32_t corge; + int64_t grault; + capn_text garply; + } foo; + capnp_nowarn struct { + int32_t corge; + capn_text grault; + int64_t garply; + } bar; + capnp_nowarn struct { + int32_t corge; + capn_text grault; + capn_text garply; + } baz; + } groups; +}; + +static const size_t TestGroups_word_count = 2; + +static const size_t TestGroups_pointer_count = 2; + +static const size_t TestGroups_struct_bytes_count = 32; + +enum TestInterleavedGroups_group1_which { + TestInterleavedGroups_group1_qux = 0, + TestInterleavedGroups_group1_corge = 1, + TestInterleavedGroups_group1_fred = 2 +}; +enum TestInterleavedGroups_group2_which { + TestInterleavedGroups_group2_qux = 0, + TestInterleavedGroups_group2_corge = 1, + TestInterleavedGroups_group2_fred = 2 +}; + +struct TestInterleavedGroups { + capnp_nowarn struct { + uint32_t foo; + uint64_t bar; + enum TestInterleavedGroups_group1_which which; + capnp_nowarn union { + uint16_t qux; + capnp_nowarn struct { + uint64_t grault; + uint16_t garply; + capn_text plugh; + capn_text xyzzy; + } corge; + capn_text fred; + }; + capn_text waldo; + } group1; + capnp_nowarn struct { + uint32_t foo; + uint64_t bar; + enum TestInterleavedGroups_group2_which which; + capnp_nowarn union { + uint16_t qux; + capnp_nowarn struct { + uint64_t grault; + uint16_t garply; + capn_text plugh; + capn_text xyzzy; + } corge; + capn_text fred; + }; + capn_text waldo; + } group2; +}; + +static const size_t TestInterleavedGroups_word_count = 6; + +static const size_t TestInterleavedGroups_pointer_count = 6; + +static const size_t TestInterleavedGroups_struct_bytes_count = 96; + + +struct TestUnionDefaults { + TestUnion_ptr s16s8s64s8Set; + TestUnion_ptr s0sps1s32Set; + TestUnnamedUnion_ptr unnamed1; + TestUnnamedUnion_ptr unnamed2; +}; + +static const size_t TestUnionDefaults_word_count = 0; + +static const size_t TestUnionDefaults_pointer_count = 4; + +static const size_t TestUnionDefaults_struct_bytes_count = 32; + + +TestUnion_ptr TestUnionDefaults_get_s16s8s64s8Set(TestUnionDefaults_ptr p); + +TestUnion_ptr TestUnionDefaults_get_s0sps1s32Set(TestUnionDefaults_ptr p); + +TestUnnamedUnion_ptr TestUnionDefaults_get_unnamed1(TestUnionDefaults_ptr p); + +TestUnnamedUnion_ptr TestUnionDefaults_get_unnamed2(TestUnionDefaults_ptr p); + +void TestUnionDefaults_set_s16s8s64s8Set(TestUnionDefaults_ptr p, TestUnion_ptr s16s8s64s8Set); + +void TestUnionDefaults_set_s0sps1s32Set(TestUnionDefaults_ptr p, TestUnion_ptr s0sps1s32Set); + +void TestUnionDefaults_set_unnamed1(TestUnionDefaults_ptr p, TestUnnamedUnion_ptr unnamed1); + +void TestUnionDefaults_set_unnamed2(TestUnionDefaults_ptr p, TestUnnamedUnion_ptr unnamed2); + +struct TestNestedTypes { + TestNestedTypes_NestedStruct_ptr nestedStruct; + enum TestNestedTypes_NestedEnum outerNestedEnum; + enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum; +}; + +static const size_t TestNestedTypes_word_count = 1; + +static const size_t TestNestedTypes_pointer_count = 1; + +static const size_t TestNestedTypes_struct_bytes_count = 16; + + +TestNestedTypes_NestedStruct_ptr TestNestedTypes_get_nestedStruct(TestNestedTypes_ptr p); + +enum TestNestedTypes_NestedEnum TestNestedTypes_get_outerNestedEnum(TestNestedTypes_ptr p); + +enum TestNestedTypes_NestedStruct_NestedEnum TestNestedTypes_get_innerNestedEnum(TestNestedTypes_ptr p); + +void TestNestedTypes_set_nestedStruct(TestNestedTypes_ptr p, TestNestedTypes_NestedStruct_ptr nestedStruct); + +void TestNestedTypes_set_outerNestedEnum(TestNestedTypes_ptr p, enum TestNestedTypes_NestedEnum outerNestedEnum); + +void TestNestedTypes_set_innerNestedEnum(TestNestedTypes_ptr p, enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum); + +struct TestNestedTypes_NestedStruct { + enum TestNestedTypes_NestedEnum outerNestedEnum; + enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum; +}; + +static const size_t TestNestedTypes_NestedStruct_word_count = 1; + +static const size_t TestNestedTypes_NestedStruct_pointer_count = 0; + +static const size_t TestNestedTypes_NestedStruct_struct_bytes_count = 8; + + +enum TestNestedTypes_NestedEnum TestNestedTypes_NestedStruct_get_outerNestedEnum(TestNestedTypes_NestedStruct_ptr p); + +enum TestNestedTypes_NestedStruct_NestedEnum TestNestedTypes_NestedStruct_get_innerNestedEnum(TestNestedTypes_NestedStruct_ptr p); + +void TestNestedTypes_NestedStruct_set_outerNestedEnum(TestNestedTypes_NestedStruct_ptr p, enum TestNestedTypes_NestedEnum outerNestedEnum); + +void TestNestedTypes_NestedStruct_set_innerNestedEnum(TestNestedTypes_NestedStruct_ptr p, enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum); + +struct TestUsing { + enum TestNestedTypes_NestedEnum outerNestedEnum; + enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum; +}; + +static const size_t TestUsing_word_count = 1; + +static const size_t TestUsing_pointer_count = 0; + +static const size_t TestUsing_struct_bytes_count = 8; + + +enum TestNestedTypes_NestedEnum TestUsing_get_outerNestedEnum(TestUsing_ptr p); + +enum TestNestedTypes_NestedStruct_NestedEnum TestUsing_get_innerNestedEnum(TestUsing_ptr p); + +void TestUsing_set_outerNestedEnum(TestUsing_ptr p, enum TestNestedTypes_NestedEnum outerNestedEnum); + +void TestUsing_set_innerNestedEnum(TestUsing_ptr p, enum TestNestedTypes_NestedStruct_NestedEnum innerNestedEnum); + +struct TestLists { + TestLists_Struct0_list list0; + TestLists_Struct1_list list1; + TestLists_Struct8_list list8; + TestLists_Struct16_list list16; + TestLists_Struct32_list list32; + TestLists_Struct64_list list64; + TestLists_StructP_list listP; + capn_ptr int32ListList; + capn_ptr textListList; + capn_ptr structListList; +}; + +static const size_t TestLists_word_count = 0; + +static const size_t TestLists_pointer_count = 10; + +static const size_t TestLists_struct_bytes_count = 80; + + +TestLists_Struct0_list TestLists_get_list0(TestLists_ptr p); + +TestLists_Struct1_list TestLists_get_list1(TestLists_ptr p); + +TestLists_Struct8_list TestLists_get_list8(TestLists_ptr p); + +TestLists_Struct16_list TestLists_get_list16(TestLists_ptr p); + +TestLists_Struct32_list TestLists_get_list32(TestLists_ptr p); + +TestLists_Struct64_list TestLists_get_list64(TestLists_ptr p); + +TestLists_StructP_list TestLists_get_listP(TestLists_ptr p); + +capn_ptr TestLists_get_int32ListList(TestLists_ptr p); + +capn_ptr TestLists_get_textListList(TestLists_ptr p); + +capn_ptr TestLists_get_structListList(TestLists_ptr p); + +void TestLists_set_list0(TestLists_ptr p, TestLists_Struct0_list list0); + +void TestLists_set_list1(TestLists_ptr p, TestLists_Struct1_list list1); + +void TestLists_set_list8(TestLists_ptr p, TestLists_Struct8_list list8); + +void TestLists_set_list16(TestLists_ptr p, TestLists_Struct16_list list16); + +void TestLists_set_list32(TestLists_ptr p, TestLists_Struct32_list list32); + +void TestLists_set_list64(TestLists_ptr p, TestLists_Struct64_list list64); + +void TestLists_set_listP(TestLists_ptr p, TestLists_StructP_list listP); + +void TestLists_set_int32ListList(TestLists_ptr p, capn_ptr int32ListList); + +void TestLists_set_textListList(TestLists_ptr p, capn_ptr textListList); + +void TestLists_set_structListList(TestLists_ptr p, capn_ptr structListList); + +capnp_nowarn struct TestLists_Struct0 { +}; + +static const size_t TestLists_Struct0_word_count = 0; + +static const size_t TestLists_Struct0_pointer_count = 0; + +static const size_t TestLists_Struct0_struct_bytes_count = 0; + + +struct TestLists_Struct1 { + unsigned f : 1; +}; + +static const size_t TestLists_Struct1_word_count = 1; + +static const size_t TestLists_Struct1_pointer_count = 0; + +static const size_t TestLists_Struct1_struct_bytes_count = 8; + + +unsigned TestLists_Struct1_get_f(TestLists_Struct1_ptr p); + +void TestLists_Struct1_set_f(TestLists_Struct1_ptr p, unsigned f); + +struct TestLists_Struct8 { + uint8_t f; +}; + +static const size_t TestLists_Struct8_word_count = 1; + +static const size_t TestLists_Struct8_pointer_count = 0; + +static const size_t TestLists_Struct8_struct_bytes_count = 8; + + +uint8_t TestLists_Struct8_get_f(TestLists_Struct8_ptr p); + +void TestLists_Struct8_set_f(TestLists_Struct8_ptr p, uint8_t f); + +struct TestLists_Struct16 { + uint16_t f; +}; + +static const size_t TestLists_Struct16_word_count = 1; + +static const size_t TestLists_Struct16_pointer_count = 0; + +static const size_t TestLists_Struct16_struct_bytes_count = 8; + + +uint16_t TestLists_Struct16_get_f(TestLists_Struct16_ptr p); + +void TestLists_Struct16_set_f(TestLists_Struct16_ptr p, uint16_t f); + +struct TestLists_Struct32 { + uint32_t f; +}; + +static const size_t TestLists_Struct32_word_count = 1; + +static const size_t TestLists_Struct32_pointer_count = 0; + +static const size_t TestLists_Struct32_struct_bytes_count = 8; + + +uint32_t TestLists_Struct32_get_f(TestLists_Struct32_ptr p); + +void TestLists_Struct32_set_f(TestLists_Struct32_ptr p, uint32_t f); + +struct TestLists_Struct64 { + uint64_t f; +}; + +static const size_t TestLists_Struct64_word_count = 1; + +static const size_t TestLists_Struct64_pointer_count = 0; + +static const size_t TestLists_Struct64_struct_bytes_count = 8; + + +uint64_t TestLists_Struct64_get_f(TestLists_Struct64_ptr p); + +void TestLists_Struct64_set_f(TestLists_Struct64_ptr p, uint64_t f); + +struct TestLists_StructP { + capn_text f; +}; + +static const size_t TestLists_StructP_word_count = 0; + +static const size_t TestLists_StructP_pointer_count = 1; + +static const size_t TestLists_StructP_struct_bytes_count = 8; + + +capn_text TestLists_StructP_get_f(TestLists_StructP_ptr p); + +void TestLists_StructP_set_f(TestLists_StructP_ptr p, capn_text f); + +struct TestLists_Struct0c { + capn_text pad; +}; + +static const size_t TestLists_Struct0c_word_count = 0; + +static const size_t TestLists_Struct0c_pointer_count = 1; + +static const size_t TestLists_Struct0c_struct_bytes_count = 8; + + +capn_text TestLists_Struct0c_get_pad(TestLists_Struct0c_ptr p); + +void TestLists_Struct0c_set_pad(TestLists_Struct0c_ptr p, capn_text pad); + +struct TestLists_Struct1c { + unsigned f : 1; + capn_text pad; +}; + +static const size_t TestLists_Struct1c_word_count = 1; + +static const size_t TestLists_Struct1c_pointer_count = 1; + +static const size_t TestLists_Struct1c_struct_bytes_count = 16; + + +unsigned TestLists_Struct1c_get_f(TestLists_Struct1c_ptr p); + +capn_text TestLists_Struct1c_get_pad(TestLists_Struct1c_ptr p); + +void TestLists_Struct1c_set_f(TestLists_Struct1c_ptr p, unsigned f); + +void TestLists_Struct1c_set_pad(TestLists_Struct1c_ptr p, capn_text pad); + +struct TestLists_Struct8c { + uint8_t f; + capn_text pad; +}; + +static const size_t TestLists_Struct8c_word_count = 1; + +static const size_t TestLists_Struct8c_pointer_count = 1; + +static const size_t TestLists_Struct8c_struct_bytes_count = 16; + + +uint8_t TestLists_Struct8c_get_f(TestLists_Struct8c_ptr p); + +capn_text TestLists_Struct8c_get_pad(TestLists_Struct8c_ptr p); + +void TestLists_Struct8c_set_f(TestLists_Struct8c_ptr p, uint8_t f); + +void TestLists_Struct8c_set_pad(TestLists_Struct8c_ptr p, capn_text pad); + +struct TestLists_Struct16c { + uint16_t f; + capn_text pad; +}; + +static const size_t TestLists_Struct16c_word_count = 1; + +static const size_t TestLists_Struct16c_pointer_count = 1; + +static const size_t TestLists_Struct16c_struct_bytes_count = 16; + + +uint16_t TestLists_Struct16c_get_f(TestLists_Struct16c_ptr p); + +capn_text TestLists_Struct16c_get_pad(TestLists_Struct16c_ptr p); + +void TestLists_Struct16c_set_f(TestLists_Struct16c_ptr p, uint16_t f); + +void TestLists_Struct16c_set_pad(TestLists_Struct16c_ptr p, capn_text pad); + +struct TestLists_Struct32c { + uint32_t f; + capn_text pad; +}; + +static const size_t TestLists_Struct32c_word_count = 1; + +static const size_t TestLists_Struct32c_pointer_count = 1; + +static const size_t TestLists_Struct32c_struct_bytes_count = 16; + + +uint32_t TestLists_Struct32c_get_f(TestLists_Struct32c_ptr p); + +capn_text TestLists_Struct32c_get_pad(TestLists_Struct32c_ptr p); + +void TestLists_Struct32c_set_f(TestLists_Struct32c_ptr p, uint32_t f); + +void TestLists_Struct32c_set_pad(TestLists_Struct32c_ptr p, capn_text pad); + +struct TestLists_Struct64c { + uint64_t f; + capn_text pad; +}; + +static const size_t TestLists_Struct64c_word_count = 1; + +static const size_t TestLists_Struct64c_pointer_count = 1; + +static const size_t TestLists_Struct64c_struct_bytes_count = 16; + + +uint64_t TestLists_Struct64c_get_f(TestLists_Struct64c_ptr p); + +capn_text TestLists_Struct64c_get_pad(TestLists_Struct64c_ptr p); + +void TestLists_Struct64c_set_f(TestLists_Struct64c_ptr p, uint64_t f); + +void TestLists_Struct64c_set_pad(TestLists_Struct64c_ptr p, capn_text pad); + +struct TestLists_StructPc { + capn_text f; + uint64_t pad; +}; + +static const size_t TestLists_StructPc_word_count = 1; + +static const size_t TestLists_StructPc_pointer_count = 1; + +static const size_t TestLists_StructPc_struct_bytes_count = 16; + + +capn_text TestLists_StructPc_get_f(TestLists_StructPc_ptr p); + +uint64_t TestLists_StructPc_get_pad(TestLists_StructPc_ptr p); + +void TestLists_StructPc_set_f(TestLists_StructPc_ptr p, capn_text f); + +void TestLists_StructPc_set_pad(TestLists_StructPc_ptr p, uint64_t pad); + +struct TestFieldZeroIsBit { + unsigned bit : 1; + unsigned secondBit : 1; + uint8_t thirdField; +}; + +static const size_t TestFieldZeroIsBit_word_count = 1; + +static const size_t TestFieldZeroIsBit_pointer_count = 0; + +static const size_t TestFieldZeroIsBit_struct_bytes_count = 8; + + +unsigned TestFieldZeroIsBit_get_bit(TestFieldZeroIsBit_ptr p); + +unsigned TestFieldZeroIsBit_get_secondBit(TestFieldZeroIsBit_ptr p); + +uint8_t TestFieldZeroIsBit_get_thirdField(TestFieldZeroIsBit_ptr p); + +void TestFieldZeroIsBit_set_bit(TestFieldZeroIsBit_ptr p, unsigned bit); + +void TestFieldZeroIsBit_set_secondBit(TestFieldZeroIsBit_ptr p, unsigned secondBit); + +void TestFieldZeroIsBit_set_thirdField(TestFieldZeroIsBit_ptr p, uint8_t thirdField); + +struct TestListDefaults { + TestLists_ptr lists; +}; + +static const size_t TestListDefaults_word_count = 0; + +static const size_t TestListDefaults_pointer_count = 1; + +static const size_t TestListDefaults_struct_bytes_count = 8; + + +TestLists_ptr TestListDefaults_get_lists(TestListDefaults_ptr p); + +void TestListDefaults_set_lists(TestListDefaults_ptr p, TestLists_ptr lists); +enum TestLateUnion_theUnion_which { + TestLateUnion_theUnion_qux = 0, + TestLateUnion_theUnion_corge = 1, + TestLateUnion_theUnion_grault = 2 +}; +enum TestLateUnion_anotherUnion_which { + TestLateUnion_anotherUnion_qux = 0, + TestLateUnion_anotherUnion_corge = 1, + TestLateUnion_anotherUnion_grault = 2 +}; + +struct TestLateUnion { + int32_t foo; + capn_text bar; + int16_t baz; + enum TestLateUnion_theUnion_which theUnion_which; + capnp_nowarn union { + capn_text qux; + capn_list32 corge; + float grault; + } theUnion; + enum TestLateUnion_anotherUnion_which anotherUnion_which; + capnp_nowarn union { + capn_text qux; + capn_list32 corge; + float grault; + } anotherUnion; +}; + +static const size_t TestLateUnion_word_count = 3; + +static const size_t TestLateUnion_pointer_count = 3; + +static const size_t TestLateUnion_struct_bytes_count = 48; + + +int32_t TestLateUnion_get_foo(TestLateUnion_ptr p); + +capn_text TestLateUnion_get_bar(TestLateUnion_ptr p); + +int16_t TestLateUnion_get_baz(TestLateUnion_ptr p); + +void TestLateUnion_set_foo(TestLateUnion_ptr p, int32_t foo); + +void TestLateUnion_set_bar(TestLateUnion_ptr p, capn_text bar); + +void TestLateUnion_set_baz(TestLateUnion_ptr p, int16_t baz); + +struct TestOldVersion { + int64_t old1; + capn_text old2; + TestOldVersion_ptr old3; +}; + +static const size_t TestOldVersion_word_count = 1; + +static const size_t TestOldVersion_pointer_count = 2; + +static const size_t TestOldVersion_struct_bytes_count = 24; + + +int64_t TestOldVersion_get_old1(TestOldVersion_ptr p); + +capn_text TestOldVersion_get_old2(TestOldVersion_ptr p); + +TestOldVersion_ptr TestOldVersion_get_old3(TestOldVersion_ptr p); + +void TestOldVersion_set_old1(TestOldVersion_ptr p, int64_t old1); + +void TestOldVersion_set_old2(TestOldVersion_ptr p, capn_text old2); + +void TestOldVersion_set_old3(TestOldVersion_ptr p, TestOldVersion_ptr old3); + +struct TestNewVersion { + int64_t old1; + capn_text old2; + TestNewVersion_ptr old3; + int64_t new1; + capn_text new2; +}; + +static const size_t TestNewVersion_word_count = 2; + +static const size_t TestNewVersion_pointer_count = 3; + +static const size_t TestNewVersion_struct_bytes_count = 40; + + +int64_t TestNewVersion_get_old1(TestNewVersion_ptr p); + +capn_text TestNewVersion_get_old2(TestNewVersion_ptr p); + +TestNewVersion_ptr TestNewVersion_get_old3(TestNewVersion_ptr p); + +int64_t TestNewVersion_get_new1(TestNewVersion_ptr p); + +capn_text TestNewVersion_get_new2(TestNewVersion_ptr p); + +void TestNewVersion_set_old1(TestNewVersion_ptr p, int64_t old1); + +void TestNewVersion_set_old2(TestNewVersion_ptr p, capn_text old2); + +void TestNewVersion_set_old3(TestNewVersion_ptr p, TestNewVersion_ptr old3); + +void TestNewVersion_set_new1(TestNewVersion_ptr p, int64_t new1); + +void TestNewVersion_set_new2(TestNewVersion_ptr p, capn_text new2); +enum TestStructUnion_un_which { + TestStructUnion_un__struct = 0, + TestStructUnion_un_object = 1 +}; + +struct TestStructUnion { + enum TestStructUnion_un_which un_which; + capnp_nowarn union { + TestStructUnion_SomeStruct_ptr _struct; + TestAnyPointer_ptr object; + } un; +}; + +static const size_t TestStructUnion_word_count = 1; + +static const size_t TestStructUnion_pointer_count = 1; + +static const size_t TestStructUnion_struct_bytes_count = 16; + + +struct TestStructUnion_SomeStruct { + capn_text someText; + capn_text moreText; +}; + +static const size_t TestStructUnion_SomeStruct_word_count = 0; + +static const size_t TestStructUnion_SomeStruct_pointer_count = 2; + +static const size_t TestStructUnion_SomeStruct_struct_bytes_count = 16; + + +capn_text TestStructUnion_SomeStruct_get_someText(TestStructUnion_SomeStruct_ptr p); + +capn_text TestStructUnion_SomeStruct_get_moreText(TestStructUnion_SomeStruct_ptr p); + +void TestStructUnion_SomeStruct_set_someText(TestStructUnion_SomeStruct_ptr p, capn_text someText); + +void TestStructUnion_SomeStruct_set_moreText(TestStructUnion_SomeStruct_ptr p, capn_text moreText); + +struct TestPrintInlineStructs { + capn_text someText; + TestPrintInlineStructs_InlineStruct_list structList; +}; + +static const size_t TestPrintInlineStructs_word_count = 0; + +static const size_t TestPrintInlineStructs_pointer_count = 2; + +static const size_t TestPrintInlineStructs_struct_bytes_count = 16; + + +capn_text TestPrintInlineStructs_get_someText(TestPrintInlineStructs_ptr p); + +TestPrintInlineStructs_InlineStruct_list TestPrintInlineStructs_get_structList(TestPrintInlineStructs_ptr p); + +void TestPrintInlineStructs_set_someText(TestPrintInlineStructs_ptr p, capn_text someText); + +void TestPrintInlineStructs_set_structList(TestPrintInlineStructs_ptr p, TestPrintInlineStructs_InlineStruct_list structList); + +struct TestPrintInlineStructs_InlineStruct { + int32_t int32Field; + capn_text textField; +}; + +static const size_t TestPrintInlineStructs_InlineStruct_word_count = 1; + +static const size_t TestPrintInlineStructs_InlineStruct_pointer_count = 1; + +static const size_t TestPrintInlineStructs_InlineStruct_struct_bytes_count = 16; + + +int32_t TestPrintInlineStructs_InlineStruct_get_int32Field(TestPrintInlineStructs_InlineStruct_ptr p); + +capn_text TestPrintInlineStructs_InlineStruct_get_textField(TestPrintInlineStructs_InlineStruct_ptr p); + +void TestPrintInlineStructs_InlineStruct_set_int32Field(TestPrintInlineStructs_InlineStruct_ptr p, int32_t int32Field); + +void TestPrintInlineStructs_InlineStruct_set_textField(TestPrintInlineStructs_InlineStruct_ptr p, capn_text textField); + +struct TestWholeFloatDefault { + float field; + float bigField; +}; + +static const size_t TestWholeFloatDefault_word_count = 1; + +static const size_t TestWholeFloatDefault_pointer_count = 0; + +static const size_t TestWholeFloatDefault_struct_bytes_count = 8; + + +float TestWholeFloatDefault_get_field(TestWholeFloatDefault_ptr p); + +float TestWholeFloatDefault_get_bigField(TestWholeFloatDefault_ptr p); + +void TestWholeFloatDefault_set_field(TestWholeFloatDefault_ptr p, float field); + +void TestWholeFloatDefault_set_bigField(TestWholeFloatDefault_ptr p, float bigField); + +capnp_nowarn struct TestEmptyStruct { +}; + +static const size_t TestEmptyStruct_word_count = 0; + +static const size_t TestEmptyStruct_pointer_count = 0; + +static const size_t TestEmptyStruct_struct_bytes_count = 0; + + +capnp_nowarn struct TestConstants { +}; + +static const size_t TestConstants_word_count = 0; + +static const size_t TestConstants_pointer_count = 0; + +static const size_t TestConstants_struct_bytes_count = 0; + + +struct TestSturdyRef { + TestSturdyRefHostId_ptr hostId; + capn_ptr objectId; +}; + +static const size_t TestSturdyRef_word_count = 0; + +static const size_t TestSturdyRef_pointer_count = 2; + +static const size_t TestSturdyRef_struct_bytes_count = 16; + + +TestSturdyRefHostId_ptr TestSturdyRef_get_hostId(TestSturdyRef_ptr p); + +capn_ptr TestSturdyRef_get_objectId(TestSturdyRef_ptr p); + +void TestSturdyRef_set_hostId(TestSturdyRef_ptr p, TestSturdyRefHostId_ptr hostId); + +void TestSturdyRef_set_objectId(TestSturdyRef_ptr p, capn_ptr objectId); + +struct TestSturdyRefHostId { + capn_text host; +}; + +static const size_t TestSturdyRefHostId_word_count = 0; + +static const size_t TestSturdyRefHostId_pointer_count = 1; + +static const size_t TestSturdyRefHostId_struct_bytes_count = 8; + + +capn_text TestSturdyRefHostId_get_host(TestSturdyRefHostId_ptr p); + +void TestSturdyRefHostId_set_host(TestSturdyRefHostId_ptr p, capn_text host); + +struct TestSturdyRefObjectId { + enum TestSturdyRefObjectId_Tag tag; +}; + +static const size_t TestSturdyRefObjectId_word_count = 1; + +static const size_t TestSturdyRefObjectId_pointer_count = 0; + +static const size_t TestSturdyRefObjectId_struct_bytes_count = 8; + + +enum TestSturdyRefObjectId_Tag TestSturdyRefObjectId_get_tag(TestSturdyRefObjectId_ptr p); + +void TestSturdyRefObjectId_set_tag(TestSturdyRefObjectId_ptr p, enum TestSturdyRefObjectId_Tag tag); + +capnp_nowarn struct TestProvisionId { +}; + +static const size_t TestProvisionId_word_count = 0; + +static const size_t TestProvisionId_pointer_count = 0; + +static const size_t TestProvisionId_struct_bytes_count = 0; + + +capnp_nowarn struct TestRecipientId { +}; + +static const size_t TestRecipientId_word_count = 0; + +static const size_t TestRecipientId_pointer_count = 0; + +static const size_t TestRecipientId_struct_bytes_count = 0; + + +capnp_nowarn struct TestThirdPartyCapId { +}; + +static const size_t TestThirdPartyCapId_word_count = 0; + +static const size_t TestThirdPartyCapId_pointer_count = 0; + +static const size_t TestThirdPartyCapId_struct_bytes_count = 0; + + +capnp_nowarn struct TestJoinResult { +}; + +static const size_t TestJoinResult_word_count = 0; + +static const size_t TestJoinResult_pointer_count = 0; + +static const size_t TestJoinResult_struct_bytes_count = 0; + +enum TestNameAnnotation_which { + TestNameAnnotation_badFieldName = 0, + TestNameAnnotation_bar = 1 +}; +enum TestNameAnnotation_badlyNamedUnion_which { + TestNameAnnotation_badlyNamedUnion_badlyNamedGroup = 0, + TestNameAnnotation_badlyNamedUnion_baz = 1 +}; + +struct TestNameAnnotation { + enum TestNameAnnotation_which which; + capnp_nowarn union { + unsigned badFieldName : 1; + int8_t bar; + }; + enum TestNameAnnotation_BadlyNamedEnum anotherBadFieldName; + enum TestNameAnnotation_badlyNamedUnion_which badlyNamedUnion_which; + capnp_nowarn union { + /* struct { -empty- } badlyNamedGroup; */ + TestNameAnnotation_NestedStruct_ptr baz; + } badlyNamedUnion; +}; + +static const size_t TestNameAnnotation_word_count = 1; + +static const size_t TestNameAnnotation_pointer_count = 1; + +static const size_t TestNameAnnotation_struct_bytes_count = 16; + + +struct TestNameAnnotation_NestedStruct { + unsigned badNestedFieldName : 1; + TestNameAnnotation_NestedStruct_ptr anotherBadNestedFieldName; +}; + +static const size_t TestNameAnnotation_NestedStruct_word_count = 1; + +static const size_t TestNameAnnotation_NestedStruct_pointer_count = 1; + +static const size_t TestNameAnnotation_NestedStruct_struct_bytes_count = 16; + + +unsigned TestNameAnnotation_NestedStruct_get_badNestedFieldName(TestNameAnnotation_NestedStruct_ptr p); + +TestNameAnnotation_NestedStruct_ptr TestNameAnnotation_NestedStruct_get_anotherBadNestedFieldName(TestNameAnnotation_NestedStruct_ptr p); + +void TestNameAnnotation_NestedStruct_set_badNestedFieldName(TestNameAnnotation_NestedStruct_ptr p, unsigned badNestedFieldName); + +void TestNameAnnotation_NestedStruct_set_anotherBadNestedFieldName(TestNameAnnotation_NestedStruct_ptr p, TestNameAnnotation_NestedStruct_ptr anotherBadNestedFieldName); + +TestAllTypes_ptr new_TestAllTypes(struct capn_segment*); +TestDefaults_ptr new_TestDefaults(struct capn_segment*); +TestAnyPointer_ptr new_TestAnyPointer(struct capn_segment*); +TestOutOfOrder_ptr new_TestOutOfOrder(struct capn_segment*); +TestUnion_ptr new_TestUnion(struct capn_segment*); +TestUnnamedUnion_ptr new_TestUnnamedUnion(struct capn_segment*); +TestUnionInUnion_ptr new_TestUnionInUnion(struct capn_segment*); +TestGroups_ptr new_TestGroups(struct capn_segment*); +TestInterleavedGroups_ptr new_TestInterleavedGroups(struct capn_segment*); +TestUnionDefaults_ptr new_TestUnionDefaults(struct capn_segment*); +TestNestedTypes_ptr new_TestNestedTypes(struct capn_segment*); +TestNestedTypes_NestedStruct_ptr new_TestNestedTypes_NestedStruct(struct capn_segment*); +TestUsing_ptr new_TestUsing(struct capn_segment*); +TestLists_ptr new_TestLists(struct capn_segment*); +TestLists_Struct0_ptr new_TestLists_Struct0(struct capn_segment*); +TestLists_Struct1_ptr new_TestLists_Struct1(struct capn_segment*); +TestLists_Struct8_ptr new_TestLists_Struct8(struct capn_segment*); +TestLists_Struct16_ptr new_TestLists_Struct16(struct capn_segment*); +TestLists_Struct32_ptr new_TestLists_Struct32(struct capn_segment*); +TestLists_Struct64_ptr new_TestLists_Struct64(struct capn_segment*); +TestLists_StructP_ptr new_TestLists_StructP(struct capn_segment*); +TestLists_Struct0c_ptr new_TestLists_Struct0c(struct capn_segment*); +TestLists_Struct1c_ptr new_TestLists_Struct1c(struct capn_segment*); +TestLists_Struct8c_ptr new_TestLists_Struct8c(struct capn_segment*); +TestLists_Struct16c_ptr new_TestLists_Struct16c(struct capn_segment*); +TestLists_Struct32c_ptr new_TestLists_Struct32c(struct capn_segment*); +TestLists_Struct64c_ptr new_TestLists_Struct64c(struct capn_segment*); +TestLists_StructPc_ptr new_TestLists_StructPc(struct capn_segment*); +TestFieldZeroIsBit_ptr new_TestFieldZeroIsBit(struct capn_segment*); +TestListDefaults_ptr new_TestListDefaults(struct capn_segment*); +TestLateUnion_ptr new_TestLateUnion(struct capn_segment*); +TestOldVersion_ptr new_TestOldVersion(struct capn_segment*); +TestNewVersion_ptr new_TestNewVersion(struct capn_segment*); +TestStructUnion_ptr new_TestStructUnion(struct capn_segment*); +TestStructUnion_SomeStruct_ptr new_TestStructUnion_SomeStruct(struct capn_segment*); +TestPrintInlineStructs_ptr new_TestPrintInlineStructs(struct capn_segment*); +TestPrintInlineStructs_InlineStruct_ptr new_TestPrintInlineStructs_InlineStruct(struct capn_segment*); +TestWholeFloatDefault_ptr new_TestWholeFloatDefault(struct capn_segment*); +TestEmptyStruct_ptr new_TestEmptyStruct(struct capn_segment*); +TestConstants_ptr new_TestConstants(struct capn_segment*); +TestSturdyRef_ptr new_TestSturdyRef(struct capn_segment*); +TestSturdyRefHostId_ptr new_TestSturdyRefHostId(struct capn_segment*); +TestSturdyRefObjectId_ptr new_TestSturdyRefObjectId(struct capn_segment*); +TestProvisionId_ptr new_TestProvisionId(struct capn_segment*); +TestRecipientId_ptr new_TestRecipientId(struct capn_segment*); +TestThirdPartyCapId_ptr new_TestThirdPartyCapId(struct capn_segment*); +TestJoinResult_ptr new_TestJoinResult(struct capn_segment*); +TestNameAnnotation_ptr new_TestNameAnnotation(struct capn_segment*); +TestNameAnnotation_NestedStruct_ptr new_TestNameAnnotation_NestedStruct(struct capn_segment*); + +TestAllTypes_list new_TestAllTypes_list(struct capn_segment*, int len); +TestDefaults_list new_TestDefaults_list(struct capn_segment*, int len); +TestAnyPointer_list new_TestAnyPointer_list(struct capn_segment*, int len); +TestOutOfOrder_list new_TestOutOfOrder_list(struct capn_segment*, int len); +TestUnion_list new_TestUnion_list(struct capn_segment*, int len); +TestUnnamedUnion_list new_TestUnnamedUnion_list(struct capn_segment*, int len); +TestUnionInUnion_list new_TestUnionInUnion_list(struct capn_segment*, int len); +TestGroups_list new_TestGroups_list(struct capn_segment*, int len); +TestInterleavedGroups_list new_TestInterleavedGroups_list(struct capn_segment*, int len); +TestUnionDefaults_list new_TestUnionDefaults_list(struct capn_segment*, int len); +TestNestedTypes_list new_TestNestedTypes_list(struct capn_segment*, int len); +TestNestedTypes_NestedStruct_list new_TestNestedTypes_NestedStruct_list(struct capn_segment*, int len); +TestUsing_list new_TestUsing_list(struct capn_segment*, int len); +TestLists_list new_TestLists_list(struct capn_segment*, int len); +TestLists_Struct0_list new_TestLists_Struct0_list(struct capn_segment*, int len); +TestLists_Struct1_list new_TestLists_Struct1_list(struct capn_segment*, int len); +TestLists_Struct8_list new_TestLists_Struct8_list(struct capn_segment*, int len); +TestLists_Struct16_list new_TestLists_Struct16_list(struct capn_segment*, int len); +TestLists_Struct32_list new_TestLists_Struct32_list(struct capn_segment*, int len); +TestLists_Struct64_list new_TestLists_Struct64_list(struct capn_segment*, int len); +TestLists_StructP_list new_TestLists_StructP_list(struct capn_segment*, int len); +TestLists_Struct0c_list new_TestLists_Struct0c_list(struct capn_segment*, int len); +TestLists_Struct1c_list new_TestLists_Struct1c_list(struct capn_segment*, int len); +TestLists_Struct8c_list new_TestLists_Struct8c_list(struct capn_segment*, int len); +TestLists_Struct16c_list new_TestLists_Struct16c_list(struct capn_segment*, int len); +TestLists_Struct32c_list new_TestLists_Struct32c_list(struct capn_segment*, int len); +TestLists_Struct64c_list new_TestLists_Struct64c_list(struct capn_segment*, int len); +TestLists_StructPc_list new_TestLists_StructPc_list(struct capn_segment*, int len); +TestFieldZeroIsBit_list new_TestFieldZeroIsBit_list(struct capn_segment*, int len); +TestListDefaults_list new_TestListDefaults_list(struct capn_segment*, int len); +TestLateUnion_list new_TestLateUnion_list(struct capn_segment*, int len); +TestOldVersion_list new_TestOldVersion_list(struct capn_segment*, int len); +TestNewVersion_list new_TestNewVersion_list(struct capn_segment*, int len); +TestStructUnion_list new_TestStructUnion_list(struct capn_segment*, int len); +TestStructUnion_SomeStruct_list new_TestStructUnion_SomeStruct_list(struct capn_segment*, int len); +TestPrintInlineStructs_list new_TestPrintInlineStructs_list(struct capn_segment*, int len); +TestPrintInlineStructs_InlineStruct_list new_TestPrintInlineStructs_InlineStruct_list(struct capn_segment*, int len); +TestWholeFloatDefault_list new_TestWholeFloatDefault_list(struct capn_segment*, int len); +TestEmptyStruct_list new_TestEmptyStruct_list(struct capn_segment*, int len); +TestConstants_list new_TestConstants_list(struct capn_segment*, int len); +TestSturdyRef_list new_TestSturdyRef_list(struct capn_segment*, int len); +TestSturdyRefHostId_list new_TestSturdyRefHostId_list(struct capn_segment*, int len); +TestSturdyRefObjectId_list new_TestSturdyRefObjectId_list(struct capn_segment*, int len); +TestProvisionId_list new_TestProvisionId_list(struct capn_segment*, int len); +TestRecipientId_list new_TestRecipientId_list(struct capn_segment*, int len); +TestThirdPartyCapId_list new_TestThirdPartyCapId_list(struct capn_segment*, int len); +TestJoinResult_list new_TestJoinResult_list(struct capn_segment*, int len); +TestNameAnnotation_list new_TestNameAnnotation_list(struct capn_segment*, int len); +TestNameAnnotation_NestedStruct_list new_TestNameAnnotation_NestedStruct_list(struct capn_segment*, int len); + +void read_TestAllTypes(struct TestAllTypes*, TestAllTypes_ptr); +void read_TestDefaults(struct TestDefaults*, TestDefaults_ptr); +void read_TestAnyPointer(struct TestAnyPointer*, TestAnyPointer_ptr); +void read_TestOutOfOrder(struct TestOutOfOrder*, TestOutOfOrder_ptr); +void read_TestUnion(struct TestUnion*, TestUnion_ptr); +void read_TestUnnamedUnion(struct TestUnnamedUnion*, TestUnnamedUnion_ptr); +void read_TestUnionInUnion(struct TestUnionInUnion*, TestUnionInUnion_ptr); +void read_TestGroups(struct TestGroups*, TestGroups_ptr); +void read_TestInterleavedGroups(struct TestInterleavedGroups*, TestInterleavedGroups_ptr); +void read_TestUnionDefaults(struct TestUnionDefaults*, TestUnionDefaults_ptr); +void read_TestNestedTypes(struct TestNestedTypes*, TestNestedTypes_ptr); +void read_TestNestedTypes_NestedStruct(struct TestNestedTypes_NestedStruct*, TestNestedTypes_NestedStruct_ptr); +void read_TestUsing(struct TestUsing*, TestUsing_ptr); +void read_TestLists(struct TestLists*, TestLists_ptr); +void read_TestLists_Struct0(struct TestLists_Struct0*, TestLists_Struct0_ptr); +void read_TestLists_Struct1(struct TestLists_Struct1*, TestLists_Struct1_ptr); +void read_TestLists_Struct8(struct TestLists_Struct8*, TestLists_Struct8_ptr); +void read_TestLists_Struct16(struct TestLists_Struct16*, TestLists_Struct16_ptr); +void read_TestLists_Struct32(struct TestLists_Struct32*, TestLists_Struct32_ptr); +void read_TestLists_Struct64(struct TestLists_Struct64*, TestLists_Struct64_ptr); +void read_TestLists_StructP(struct TestLists_StructP*, TestLists_StructP_ptr); +void read_TestLists_Struct0c(struct TestLists_Struct0c*, TestLists_Struct0c_ptr); +void read_TestLists_Struct1c(struct TestLists_Struct1c*, TestLists_Struct1c_ptr); +void read_TestLists_Struct8c(struct TestLists_Struct8c*, TestLists_Struct8c_ptr); +void read_TestLists_Struct16c(struct TestLists_Struct16c*, TestLists_Struct16c_ptr); +void read_TestLists_Struct32c(struct TestLists_Struct32c*, TestLists_Struct32c_ptr); +void read_TestLists_Struct64c(struct TestLists_Struct64c*, TestLists_Struct64c_ptr); +void read_TestLists_StructPc(struct TestLists_StructPc*, TestLists_StructPc_ptr); +void read_TestFieldZeroIsBit(struct TestFieldZeroIsBit*, TestFieldZeroIsBit_ptr); +void read_TestListDefaults(struct TestListDefaults*, TestListDefaults_ptr); +void read_TestLateUnion(struct TestLateUnion*, TestLateUnion_ptr); +void read_TestOldVersion(struct TestOldVersion*, TestOldVersion_ptr); +void read_TestNewVersion(struct TestNewVersion*, TestNewVersion_ptr); +void read_TestStructUnion(struct TestStructUnion*, TestStructUnion_ptr); +void read_TestStructUnion_SomeStruct(struct TestStructUnion_SomeStruct*, TestStructUnion_SomeStruct_ptr); +void read_TestPrintInlineStructs(struct TestPrintInlineStructs*, TestPrintInlineStructs_ptr); +void read_TestPrintInlineStructs_InlineStruct(struct TestPrintInlineStructs_InlineStruct*, TestPrintInlineStructs_InlineStruct_ptr); +void read_TestWholeFloatDefault(struct TestWholeFloatDefault*, TestWholeFloatDefault_ptr); +void read_TestEmptyStruct(struct TestEmptyStruct*, TestEmptyStruct_ptr); +void read_TestConstants(struct TestConstants*, TestConstants_ptr); +void read_TestSturdyRef(struct TestSturdyRef*, TestSturdyRef_ptr); +void read_TestSturdyRefHostId(struct TestSturdyRefHostId*, TestSturdyRefHostId_ptr); +void read_TestSturdyRefObjectId(struct TestSturdyRefObjectId*, TestSturdyRefObjectId_ptr); +void read_TestProvisionId(struct TestProvisionId*, TestProvisionId_ptr); +void read_TestRecipientId(struct TestRecipientId*, TestRecipientId_ptr); +void read_TestThirdPartyCapId(struct TestThirdPartyCapId*, TestThirdPartyCapId_ptr); +void read_TestJoinResult(struct TestJoinResult*, TestJoinResult_ptr); +void read_TestNameAnnotation(struct TestNameAnnotation*, TestNameAnnotation_ptr); +void read_TestNameAnnotation_NestedStruct(struct TestNameAnnotation_NestedStruct*, TestNameAnnotation_NestedStruct_ptr); + +void write_TestAllTypes(const struct TestAllTypes*, TestAllTypes_ptr); +void write_TestDefaults(const struct TestDefaults*, TestDefaults_ptr); +void write_TestAnyPointer(const struct TestAnyPointer*, TestAnyPointer_ptr); +void write_TestOutOfOrder(const struct TestOutOfOrder*, TestOutOfOrder_ptr); +void write_TestUnion(const struct TestUnion*, TestUnion_ptr); +void write_TestUnnamedUnion(const struct TestUnnamedUnion*, TestUnnamedUnion_ptr); +void write_TestUnionInUnion(const struct TestUnionInUnion*, TestUnionInUnion_ptr); +void write_TestGroups(const struct TestGroups*, TestGroups_ptr); +void write_TestInterleavedGroups(const struct TestInterleavedGroups*, TestInterleavedGroups_ptr); +void write_TestUnionDefaults(const struct TestUnionDefaults*, TestUnionDefaults_ptr); +void write_TestNestedTypes(const struct TestNestedTypes*, TestNestedTypes_ptr); +void write_TestNestedTypes_NestedStruct(const struct TestNestedTypes_NestedStruct*, TestNestedTypes_NestedStruct_ptr); +void write_TestUsing(const struct TestUsing*, TestUsing_ptr); +void write_TestLists(const struct TestLists*, TestLists_ptr); +void write_TestLists_Struct0(const struct TestLists_Struct0*, TestLists_Struct0_ptr); +void write_TestLists_Struct1(const struct TestLists_Struct1*, TestLists_Struct1_ptr); +void write_TestLists_Struct8(const struct TestLists_Struct8*, TestLists_Struct8_ptr); +void write_TestLists_Struct16(const struct TestLists_Struct16*, TestLists_Struct16_ptr); +void write_TestLists_Struct32(const struct TestLists_Struct32*, TestLists_Struct32_ptr); +void write_TestLists_Struct64(const struct TestLists_Struct64*, TestLists_Struct64_ptr); +void write_TestLists_StructP(const struct TestLists_StructP*, TestLists_StructP_ptr); +void write_TestLists_Struct0c(const struct TestLists_Struct0c*, TestLists_Struct0c_ptr); +void write_TestLists_Struct1c(const struct TestLists_Struct1c*, TestLists_Struct1c_ptr); +void write_TestLists_Struct8c(const struct TestLists_Struct8c*, TestLists_Struct8c_ptr); +void write_TestLists_Struct16c(const struct TestLists_Struct16c*, TestLists_Struct16c_ptr); +void write_TestLists_Struct32c(const struct TestLists_Struct32c*, TestLists_Struct32c_ptr); +void write_TestLists_Struct64c(const struct TestLists_Struct64c*, TestLists_Struct64c_ptr); +void write_TestLists_StructPc(const struct TestLists_StructPc*, TestLists_StructPc_ptr); +void write_TestFieldZeroIsBit(const struct TestFieldZeroIsBit*, TestFieldZeroIsBit_ptr); +void write_TestListDefaults(const struct TestListDefaults*, TestListDefaults_ptr); +void write_TestLateUnion(const struct TestLateUnion*, TestLateUnion_ptr); +void write_TestOldVersion(const struct TestOldVersion*, TestOldVersion_ptr); +void write_TestNewVersion(const struct TestNewVersion*, TestNewVersion_ptr); +void write_TestStructUnion(const struct TestStructUnion*, TestStructUnion_ptr); +void write_TestStructUnion_SomeStruct(const struct TestStructUnion_SomeStruct*, TestStructUnion_SomeStruct_ptr); +void write_TestPrintInlineStructs(const struct TestPrintInlineStructs*, TestPrintInlineStructs_ptr); +void write_TestPrintInlineStructs_InlineStruct(const struct TestPrintInlineStructs_InlineStruct*, TestPrintInlineStructs_InlineStruct_ptr); +void write_TestWholeFloatDefault(const struct TestWholeFloatDefault*, TestWholeFloatDefault_ptr); +void write_TestEmptyStruct(const struct TestEmptyStruct*, TestEmptyStruct_ptr); +void write_TestConstants(const struct TestConstants*, TestConstants_ptr); +void write_TestSturdyRef(const struct TestSturdyRef*, TestSturdyRef_ptr); +void write_TestSturdyRefHostId(const struct TestSturdyRefHostId*, TestSturdyRefHostId_ptr); +void write_TestSturdyRefObjectId(const struct TestSturdyRefObjectId*, TestSturdyRefObjectId_ptr); +void write_TestProvisionId(const struct TestProvisionId*, TestProvisionId_ptr); +void write_TestRecipientId(const struct TestRecipientId*, TestRecipientId_ptr); +void write_TestThirdPartyCapId(const struct TestThirdPartyCapId*, TestThirdPartyCapId_ptr); +void write_TestJoinResult(const struct TestJoinResult*, TestJoinResult_ptr); +void write_TestNameAnnotation(const struct TestNameAnnotation*, TestNameAnnotation_ptr); +void write_TestNameAnnotation_NestedStruct(const struct TestNameAnnotation_NestedStruct*, TestNameAnnotation_NestedStruct_ptr); + +void get_TestAllTypes(struct TestAllTypes*, TestAllTypes_list, int i); +void get_TestDefaults(struct TestDefaults*, TestDefaults_list, int i); +void get_TestAnyPointer(struct TestAnyPointer*, TestAnyPointer_list, int i); +void get_TestOutOfOrder(struct TestOutOfOrder*, TestOutOfOrder_list, int i); +void get_TestUnion(struct TestUnion*, TestUnion_list, int i); +void get_TestUnnamedUnion(struct TestUnnamedUnion*, TestUnnamedUnion_list, int i); +void get_TestUnionInUnion(struct TestUnionInUnion*, TestUnionInUnion_list, int i); +void get_TestGroups(struct TestGroups*, TestGroups_list, int i); +void get_TestInterleavedGroups(struct TestInterleavedGroups*, TestInterleavedGroups_list, int i); +void get_TestUnionDefaults(struct TestUnionDefaults*, TestUnionDefaults_list, int i); +void get_TestNestedTypes(struct TestNestedTypes*, TestNestedTypes_list, int i); +void get_TestNestedTypes_NestedStruct(struct TestNestedTypes_NestedStruct*, TestNestedTypes_NestedStruct_list, int i); +void get_TestUsing(struct TestUsing*, TestUsing_list, int i); +void get_TestLists(struct TestLists*, TestLists_list, int i); +void get_TestLists_Struct0(struct TestLists_Struct0*, TestLists_Struct0_list, int i); +void get_TestLists_Struct1(struct TestLists_Struct1*, TestLists_Struct1_list, int i); +void get_TestLists_Struct8(struct TestLists_Struct8*, TestLists_Struct8_list, int i); +void get_TestLists_Struct16(struct TestLists_Struct16*, TestLists_Struct16_list, int i); +void get_TestLists_Struct32(struct TestLists_Struct32*, TestLists_Struct32_list, int i); +void get_TestLists_Struct64(struct TestLists_Struct64*, TestLists_Struct64_list, int i); +void get_TestLists_StructP(struct TestLists_StructP*, TestLists_StructP_list, int i); +void get_TestLists_Struct0c(struct TestLists_Struct0c*, TestLists_Struct0c_list, int i); +void get_TestLists_Struct1c(struct TestLists_Struct1c*, TestLists_Struct1c_list, int i); +void get_TestLists_Struct8c(struct TestLists_Struct8c*, TestLists_Struct8c_list, int i); +void get_TestLists_Struct16c(struct TestLists_Struct16c*, TestLists_Struct16c_list, int i); +void get_TestLists_Struct32c(struct TestLists_Struct32c*, TestLists_Struct32c_list, int i); +void get_TestLists_Struct64c(struct TestLists_Struct64c*, TestLists_Struct64c_list, int i); +void get_TestLists_StructPc(struct TestLists_StructPc*, TestLists_StructPc_list, int i); +void get_TestFieldZeroIsBit(struct TestFieldZeroIsBit*, TestFieldZeroIsBit_list, int i); +void get_TestListDefaults(struct TestListDefaults*, TestListDefaults_list, int i); +void get_TestLateUnion(struct TestLateUnion*, TestLateUnion_list, int i); +void get_TestOldVersion(struct TestOldVersion*, TestOldVersion_list, int i); +void get_TestNewVersion(struct TestNewVersion*, TestNewVersion_list, int i); +void get_TestStructUnion(struct TestStructUnion*, TestStructUnion_list, int i); +void get_TestStructUnion_SomeStruct(struct TestStructUnion_SomeStruct*, TestStructUnion_SomeStruct_list, int i); +void get_TestPrintInlineStructs(struct TestPrintInlineStructs*, TestPrintInlineStructs_list, int i); +void get_TestPrintInlineStructs_InlineStruct(struct TestPrintInlineStructs_InlineStruct*, TestPrintInlineStructs_InlineStruct_list, int i); +void get_TestWholeFloatDefault(struct TestWholeFloatDefault*, TestWholeFloatDefault_list, int i); +void get_TestEmptyStruct(struct TestEmptyStruct*, TestEmptyStruct_list, int i); +void get_TestConstants(struct TestConstants*, TestConstants_list, int i); +void get_TestSturdyRef(struct TestSturdyRef*, TestSturdyRef_list, int i); +void get_TestSturdyRefHostId(struct TestSturdyRefHostId*, TestSturdyRefHostId_list, int i); +void get_TestSturdyRefObjectId(struct TestSturdyRefObjectId*, TestSturdyRefObjectId_list, int i); +void get_TestProvisionId(struct TestProvisionId*, TestProvisionId_list, int i); +void get_TestRecipientId(struct TestRecipientId*, TestRecipientId_list, int i); +void get_TestThirdPartyCapId(struct TestThirdPartyCapId*, TestThirdPartyCapId_list, int i); +void get_TestJoinResult(struct TestJoinResult*, TestJoinResult_list, int i); +void get_TestNameAnnotation(struct TestNameAnnotation*, TestNameAnnotation_list, int i); +void get_TestNameAnnotation_NestedStruct(struct TestNameAnnotation_NestedStruct*, TestNameAnnotation_NestedStruct_list, int i); + +void set_TestAllTypes(const struct TestAllTypes*, TestAllTypes_list, int i); +void set_TestDefaults(const struct TestDefaults*, TestDefaults_list, int i); +void set_TestAnyPointer(const struct TestAnyPointer*, TestAnyPointer_list, int i); +void set_TestOutOfOrder(const struct TestOutOfOrder*, TestOutOfOrder_list, int i); +void set_TestUnion(const struct TestUnion*, TestUnion_list, int i); +void set_TestUnnamedUnion(const struct TestUnnamedUnion*, TestUnnamedUnion_list, int i); +void set_TestUnionInUnion(const struct TestUnionInUnion*, TestUnionInUnion_list, int i); +void set_TestGroups(const struct TestGroups*, TestGroups_list, int i); +void set_TestInterleavedGroups(const struct TestInterleavedGroups*, TestInterleavedGroups_list, int i); +void set_TestUnionDefaults(const struct TestUnionDefaults*, TestUnionDefaults_list, int i); +void set_TestNestedTypes(const struct TestNestedTypes*, TestNestedTypes_list, int i); +void set_TestNestedTypes_NestedStruct(const struct TestNestedTypes_NestedStruct*, TestNestedTypes_NestedStruct_list, int i); +void set_TestUsing(const struct TestUsing*, TestUsing_list, int i); +void set_TestLists(const struct TestLists*, TestLists_list, int i); +void set_TestLists_Struct0(const struct TestLists_Struct0*, TestLists_Struct0_list, int i); +void set_TestLists_Struct1(const struct TestLists_Struct1*, TestLists_Struct1_list, int i); +void set_TestLists_Struct8(const struct TestLists_Struct8*, TestLists_Struct8_list, int i); +void set_TestLists_Struct16(const struct TestLists_Struct16*, TestLists_Struct16_list, int i); +void set_TestLists_Struct32(const struct TestLists_Struct32*, TestLists_Struct32_list, int i); +void set_TestLists_Struct64(const struct TestLists_Struct64*, TestLists_Struct64_list, int i); +void set_TestLists_StructP(const struct TestLists_StructP*, TestLists_StructP_list, int i); +void set_TestLists_Struct0c(const struct TestLists_Struct0c*, TestLists_Struct0c_list, int i); +void set_TestLists_Struct1c(const struct TestLists_Struct1c*, TestLists_Struct1c_list, int i); +void set_TestLists_Struct8c(const struct TestLists_Struct8c*, TestLists_Struct8c_list, int i); +void set_TestLists_Struct16c(const struct TestLists_Struct16c*, TestLists_Struct16c_list, int i); +void set_TestLists_Struct32c(const struct TestLists_Struct32c*, TestLists_Struct32c_list, int i); +void set_TestLists_Struct64c(const struct TestLists_Struct64c*, TestLists_Struct64c_list, int i); +void set_TestLists_StructPc(const struct TestLists_StructPc*, TestLists_StructPc_list, int i); +void set_TestFieldZeroIsBit(const struct TestFieldZeroIsBit*, TestFieldZeroIsBit_list, int i); +void set_TestListDefaults(const struct TestListDefaults*, TestListDefaults_list, int i); +void set_TestLateUnion(const struct TestLateUnion*, TestLateUnion_list, int i); +void set_TestOldVersion(const struct TestOldVersion*, TestOldVersion_list, int i); +void set_TestNewVersion(const struct TestNewVersion*, TestNewVersion_list, int i); +void set_TestStructUnion(const struct TestStructUnion*, TestStructUnion_list, int i); +void set_TestStructUnion_SomeStruct(const struct TestStructUnion_SomeStruct*, TestStructUnion_SomeStruct_list, int i); +void set_TestPrintInlineStructs(const struct TestPrintInlineStructs*, TestPrintInlineStructs_list, int i); +void set_TestPrintInlineStructs_InlineStruct(const struct TestPrintInlineStructs_InlineStruct*, TestPrintInlineStructs_InlineStruct_list, int i); +void set_TestWholeFloatDefault(const struct TestWholeFloatDefault*, TestWholeFloatDefault_list, int i); +void set_TestEmptyStruct(const struct TestEmptyStruct*, TestEmptyStruct_list, int i); +void set_TestConstants(const struct TestConstants*, TestConstants_list, int i); +void set_TestSturdyRef(const struct TestSturdyRef*, TestSturdyRef_list, int i); +void set_TestSturdyRefHostId(const struct TestSturdyRefHostId*, TestSturdyRefHostId_list, int i); +void set_TestSturdyRefObjectId(const struct TestSturdyRefObjectId*, TestSturdyRefObjectId_list, int i); +void set_TestProvisionId(const struct TestProvisionId*, TestProvisionId_list, int i); +void set_TestRecipientId(const struct TestRecipientId*, TestRecipientId_list, int i); +void set_TestThirdPartyCapId(const struct TestThirdPartyCapId*, TestThirdPartyCapId_list, int i); +void set_TestJoinResult(const struct TestJoinResult*, TestJoinResult_list, int i); +void set_TestNameAnnotation(const struct TestNameAnnotation*, TestNameAnnotation_list, int i); +void set_TestNameAnnotation_NestedStruct(const struct TestNameAnnotation_NestedStruct*, TestNameAnnotation_NestedStruct_list, int i); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/subprojects/c-capnproto/compiler/update-notes.md b/src/subprojects/c-capnproto/compiler/update-notes.md new file mode 100755 index 00000000..5645850e --- /dev/null +++ b/src/subprojects/c-capnproto/compiler/update-notes.md @@ -0,0 +1,18 @@ + +occasionally, it may be required to sync with upstream capn proto changes. some quick notes on the process i've used here, assuming the updated capnproto repo is at CAPNP_CPP: + + $ cp ${CAPNP_CPP}/c++/src/capnp/test.capnp . + $ cp ${CAPNP_CPP}/c++/src/capnp/schema.capnp . + $ cp ${CAPNP_CPP}/c++/src/capnp/c++.capnp . + +fix up `schema.capnp` to reference the in-tree copy of `c++.capnp` (ie, `using Cxx = import "c++.capnp";` at the top of the file) + +then, regenerate the schema support: + + $ capnp compile -o ./capnpc-c compiler/schema.capnp + +now try to regenerate again, based on the previously regenerated schema. + +you can always check the capnpc formatted output during debugging: + + $ capnp compile -ocapnpc-capnpc compiler/schema.capnp diff --git a/src/subprojects/c-capnproto/configure.ac b/src/subprojects/c-capnproto/configure.ac new file mode 100755 index 00000000..96975e1e --- /dev/null +++ b/src/subprojects/c-capnproto/configure.ac @@ -0,0 +1,53 @@ +AC_PREREQ(2.60) + +AC_INIT(c-capnproto, 0.3, []) +AC_CONFIG_SRCDIR(lib/capnp_c.h) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([ac]) + +AC_CANONICAL_BUILD() +AC_CANONICAL_HOST() +AC_CANONICAL_TARGET() + +AM_INIT_AUTOMAKE(1.11) +AM_SILENT_RULES([yes]) +AC_CONFIG_HEADERS([config.h]) + +AC_USE_SYSTEM_EXTENSIONS + +LT_INIT + +AC_LANG([C]) +AC_PROG_CC +AC_PROG_CXX + +AC_PROG_INSTALL +AC_PROG_LN_S + +AC_ARG_ENABLE(werror, + AS_HELP_STRING([--enable-werror], [enable -Werror (for developers only)])) +if test x"${enable_werror}" = x"yes" ; then + WERROR="-Werror" +fi +AC_SUBST(WERROR) + +AC_ARG_WITH(capnpdir, + AS_HELP_STRING([--with-capnpdir=DIR], [directory to install c.capnp file in (default: $includedir/capnp)])) +if test x"${with_capnpdir}" != x ; then + capnpdir="${with_capnpdir}" +else + capnpdir="${includedir}/capnp" +fi +AC_SUBST(capnpdir) + +#PKG_CHECK_MODULES(CAPNP, [capnp >= 0.5.2], [], [ +# AC_MSG_ERROR([capnproto base package (0.5.2 or newer) not found]) +#]) + +AC_CONFIG_SUBDIRS([gtest/googletest]) + +AC_CONFIG_FILES([ + Makefile + c-capnproto.pc +]) +AC_OUTPUT diff --git a/src/subprojects/c-capnproto/dk b/src/subprojects/c-capnproto/dk new file mode 100755 index 00000000..d84e696e --- /dev/null +++ b/src/subprojects/c-capnproto/dk @@ -0,0 +1,701 @@ +#!/bin/sh +# Recommendation: Place this file in source control. +# Auto-generated by `./dk dksdk.project.new` of dktool. +# +# Invoking: ./dk +# That works in Powershell on Windows, and in Unix. Copy-and-paste works! +# +# Purpose: Install CMake if not already. Then invoke CMake. + +set -euf + +# --- Imports of dkml-runtime-common's crossplatform-functions.sh --- + +# Get standard locations of Unix system binaries like `/usr/bin/mv` (or `/bin/mv`). +# +# Will not return anything in `/usr/local/bin` or `/usr/sbin`. Use when you do not +# know whether the PATH has been set correctly, or when you do not know if the +# system binary exists. +# +# At some point in the future, this function will error out if the required system binaries +# do not exist. Most system binaries are common to all Unix/Linux/macOS installations but +# some (like `comm`) may need to be installed for proper functioning of DKML. +# +# Outputs: +# - env:DKMLSYS_MV - Location of `mv` +# - env:DKMLSYS_CHMOD - Location of `chmod` +# - env:DKMLSYS_UNAME - Location of `uname` +# - env:DKMLSYS_ENV - Location of `env` +# - env:DKMLSYS_AWK - Location of `awk` +# - env:DKMLSYS_SED - Location of `sed` +# - env:DKMLSYS_COMM - Location of `comm` +# - env:DKMLSYS_INSTALL - Location of `install` +# - env:DKMLSYS_RM - Location of `rm` +# - env:DKMLSYS_SORT - Location of `sort` +# - env:DKMLSYS_CAT - Location of `cat` +# - env:DKMLSYS_STAT - Location of `stat` +# - env:DKMLSYS_GREP - Location of `grep` +# - env:DKMLSYS_CURL - Location of `curl` (empty if not found) +# - env:DKMLSYS_WGET - Location of `wget` (empty if not found) +# - env:DKMLSYS_TR - Location of `tr` +autodetect_system_binaries() { + if [ -z "${DKMLSYS_MV:-}" ]; then + if [ -x /usr/bin/mv ]; then + DKMLSYS_MV=/usr/bin/mv + else + DKMLSYS_MV=/bin/mv + fi + fi + if [ -z "${DKMLSYS_CHMOD:-}" ]; then + if [ -x /usr/bin/chmod ]; then + DKMLSYS_CHMOD=/usr/bin/chmod + else + DKMLSYS_CHMOD=/bin/chmod + fi + fi + if [ -z "${DKMLSYS_UNAME:-}" ]; then + if [ -x /usr/bin/uname ]; then + DKMLSYS_UNAME=/usr/bin/uname + else + DKMLSYS_UNAME=/bin/uname + fi + fi + if [ -z "${DKMLSYS_ENV:-}" ]; then + if [ -x /usr/bin/env ]; then + DKMLSYS_ENV=/usr/bin/env + else + DKMLSYS_ENV=/bin/env + fi + fi + if [ -z "${DKMLSYS_AWK:-}" ]; then + if [ -x /usr/bin/awk ]; then + DKMLSYS_AWK=/usr/bin/awk + else + DKMLSYS_AWK=/bin/awk + fi + fi + if [ -z "${DKMLSYS_SED:-}" ]; then + if [ -x /usr/bin/sed ]; then + DKMLSYS_SED=/usr/bin/sed + else + DKMLSYS_SED=/bin/sed + fi + fi + if [ -z "${DKMLSYS_COMM:-}" ]; then + if [ -x /usr/bin/comm ]; then + DKMLSYS_COMM=/usr/bin/comm + else + DKMLSYS_COMM=/bin/comm + fi + fi + if [ -z "${DKMLSYS_INSTALL:-}" ]; then + if [ -x /usr/bin/install ]; then + DKMLSYS_INSTALL=/usr/bin/install + else + DKMLSYS_INSTALL=/bin/install + fi + fi + if [ -z "${DKMLSYS_RM:-}" ]; then + if [ -x /usr/bin/rm ]; then + DKMLSYS_RM=/usr/bin/rm + else + DKMLSYS_RM=/bin/rm + fi + fi + if [ -z "${DKMLSYS_SORT:-}" ]; then + if [ -x /usr/bin/sort ]; then + DKMLSYS_SORT=/usr/bin/sort + else + DKMLSYS_SORT=/bin/sort + fi + fi + if [ -z "${DKMLSYS_CAT:-}" ]; then + if [ -x /usr/bin/cat ]; then + DKMLSYS_CAT=/usr/bin/cat + else + DKMLSYS_CAT=/bin/cat + fi + fi + if [ -z "${DKMLSYS_STAT:-}" ]; then + if [ -x /usr/bin/stat ]; then + DKMLSYS_STAT=/usr/bin/stat + else + DKMLSYS_STAT=/bin/stat + fi + fi + if [ -z "${DKMLSYS_GREP:-}" ]; then + if [ -x /usr/bin/grep ]; then + DKMLSYS_GREP=/usr/bin/grep + else + DKMLSYS_GREP=/bin/grep + fi + fi + if [ -z "${DKMLSYS_CURL:-}" ]; then + if [ -x /usr/bin/curl ]; then + DKMLSYS_CURL=/usr/bin/curl + elif [ -x /bin/curl ]; then + DKMLSYS_CURL=/bin/curl + else + DKMLSYS_CURL= + fi + fi + if [ -z "${DKMLSYS_WGET:-}" ]; then + if [ -x /usr/bin/wget ]; then + DKMLSYS_WGET=/usr/bin/wget + elif [ -x /bin/wget ]; then + DKMLSYS_WGET=/bin/wget + else + DKMLSYS_WGET= + fi + fi + if [ -z "${DKMLSYS_TR:-}" ]; then + if [ -x /usr/bin/tr ]; then + DKMLSYS_TR=/usr/bin/tr + else + DKMLSYS_TR=/bin/tr + fi + fi + export DKMLSYS_MV DKMLSYS_CHMOD DKMLSYS_UNAME DKMLSYS_ENV DKMLSYS_AWK DKMLSYS_SED DKMLSYS_COMM DKMLSYS_INSTALL + export DKMLSYS_RM DKMLSYS_SORT DKMLSYS_CAT DKMLSYS_STAT DKMLSYS_GREP DKMLSYS_CURL DKMLSYS_WGET DKMLSYS_TR +} + +# Is a Windows build machine if we are in a MSYS2 or Cygwin environment. +# +# Better alternatives +# ------------------- +# +# 1. If you are checking to see if you should do a cygpath, then just guard it +# like so: +# if [ -x /usr/bin/cygpath ]; then +# do_something $(/usr/bin/cygpath ...) ... +# fi +# This clearly guards what you are about to do (cygpath) with what you will +# need (cygpath). +# 2. is_arg_windows_platform +is_unixy_windows_build_machine() { + if is_msys2_msys_build_machine || is_cygwin_build_machine; then + return 0 + fi + return 1 +} + +# Is a MSYS2 environment with the MSYS or MINGW64 subsystem? +# * MSYS2 can also do MinGW 32-bit and 64-bit subsystems. Used by Diskuv OCaml +# * MINGW64 used by Git Bash (aka. GitHub Actions `shell: bash`) +# https://www.msys2.org/docs/environments/ +is_msys2_msys_build_machine() { + if [ -e /usr/bin/msys-2.0.dll ] && { + [ "${MSYSTEM:-}" = "MSYS" ] || [ "${MSYSTEM:-}" = "MINGW64" ] || [ "${MSYSTEM:-}" = "UCRT64" ] || [ "${MSYSTEM:-}" = "CLANG64" ] || [ "${MSYSTEM:-}" = "MINGW32" ] || [ "${MSYSTEM:-}" = "CLANG32" ] || [ "${MSYSTEM:-}" = "CLANGARM64" ] + }; then + return 0 + fi + return 1 +} + +is_cygwin_build_machine() { + if [ -e /usr/bin/cygwin1.dll ]; then + return 0 + fi + return 1 +} + +# Tries to find the host ABI. +# +# Beware: This function uses `uname` probing which is inaccurate during +# cross-compilation. +# +# Outputs: +# - env:BUILDHOST_ARCH will contain the host ABI. +autodetect_buildhost_arch() { + # Set DKMLSYS_* + autodetect_system_binaries + + autodetect_buildhost_arch_SYSTEM=$("$DKMLSYS_UNAME" -s) + autodetect_buildhost_arch_MACHINE=$("$DKMLSYS_UNAME" -m) + # list from https://en.wikipedia.org/wiki/Uname and https://stackoverflow.com/questions/45125516/possible-values-for-uname-m + case "${autodetect_buildhost_arch_SYSTEM}-${autodetect_buildhost_arch_MACHINE}" in + Linux-armv7*) + BUILDHOST_ARCH=linux_arm32v7;; + Linux-armv6* | Linux-arm) + BUILDHOST_ARCH=linux_arm32v6;; + Linux-aarch64 | Linux-arm64 | Linux-armv8*) + BUILDHOST_ARCH=linux_arm64;; + Linux-i386 | Linux-i686) + BUILDHOST_ARCH=linux_x86;; + Linux-x86_64) + BUILDHOST_ARCH=linux_x86_64;; + Darwin-arm64) + BUILDHOST_ARCH=darwin_arm64;; + Darwin-x86_64) + BUILDHOST_ARCH=darwin_x86_64;; + *-i386 | *-i686) + if is_unixy_windows_build_machine; then + BUILDHOST_ARCH=windows_x86 + else + printf "%s\n" "FATAL: Unsupported build machine type obtained from 'uname -s' and 'uname -m': $autodetect_buildhost_arch_SYSTEM and $autodetect_buildhost_arch_MACHINE" >&2 + exit 1 + fi + ;; + *-x86_64) + if is_unixy_windows_build_machine; then + BUILDHOST_ARCH=windows_x86_64 + else + printf "%s\n" "FATAL: Unsupported build machine type obtained from 'uname -s' and 'uname -m': $autodetect_buildhost_arch_SYSTEM and $autodetect_buildhost_arch_MACHINE" >&2 + exit 1 + fi + ;; + *) + # Since: + # 1) MSYS2 does not run on ARM/ARM64 (https://www.msys2.org/docs/environments/) + # 2) MSVC does not use ARM/ARM64 as host machine (https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-160) + # we do not support Windows ARM/ARM64 as a build machine + printf "%s\n" "FATAL: Unsupported build machine type obtained from 'uname -s' and 'uname -m': $autodetect_buildhost_arch_SYSTEM and $autodetect_buildhost_arch_MACHINE" >&2 + exit 1 + ;; + esac +} + +# A function that will try to print an ISO8601 timestamp, but will fallback to +# the system default. Always uses UTC timezone. +try_iso8601_timestamp() { + date -u -Iseconds 2>/dev/null || TZ=UTC date +} + +# A function that will print the command and possibly time it (if and only if it uses a full path to +# an executable, so that 'time' does not fail on internal shell functions). +# If --return-error-code is the first argument or LOG_TRACE_RETURN_ERROR_CODE=ON, then instead of exiting the +# function will return the error code. +log_trace() { + log_trace_RETURN=${LOG_TRACE_RETURN_ERROR_CODE:-OFF} + + log_trace_1="$1" + if [ "$log_trace_1" = "--return-error-code" ]; then + shift + log_trace_RETURN=ON + fi + + if [ "${DKML_BUILD_TRACE:-OFF}" = ON ]; then + printf "[%s] %s\n" "$(try_iso8601_timestamp)" "+ $*" >&2 + if [ -x "$1" ]; then + time "$@" + else + "$@" + fi + else + # use judgement so we essentially have log at an INFO level + case "$1" in + rm|cp) + # debug level. only show when DKML_BUILD_TRACE=ON + ;; + git|make|ocaml_configure|ocaml_make|make_host|make_target) + # info level. and can show entire command without polluting the screen + printf "[%s] %s\n" "$(try_iso8601_timestamp)" "$*" >&2 + ;; + *) printf "[%s] %s\n" "$(try_iso8601_timestamp)" "$1" >&2 + esac + "$@" + fi + log_trace_ec="$?" + if [ "$log_trace_ec" -ne 0 ]; then + if [ "$log_trace_RETURN" = ON ]; then + return "$log_trace_ec" + else + printf "FATAL: Command failed with exit code %s: %s\n" "$log_trace_ec" "$*" >&2 + exit "$log_trace_ec" + fi + fi +} + +# [sha256compute FILE] writes the SHA256 checksum (hex encoded) of file FILE to the standard output. +sha256compute() { + sha256compute_FILE="$1" + shift + # For reasons unclear doing the following in MSYS2: + # sha256sum 'Z:\source\README.md' + # will produce a backslash like: + # \5518c76ed7234a153941fb7bc94b6e91d9cb8f1c4e22daf169a59b5878c3fc8a *Z:\\source\\README.md + # So always cygpath the filename if available + if [ -x /usr/bin/cygpath ]; then + sha256compute_FILE=$(/usr/bin/cygpath -a "$sha256compute_FILE") + fi + + if [ -x /usr/bin/shasum ]; then + /usr/bin/shasum -a 256 "$sha256compute_FILE" | awk '{print $1}' + elif [ -x /usr/bin/sha256sum ]; then + /usr/bin/sha256sum "$sha256compute_FILE" | awk '{print $1}' + else + printf "FATAL: %s\n" "No sha256 checksum utility found" >&2 + exit 107 + fi +} + +# [sha256check FILE SUM] checks that the file FILE has a SHA256 checksum (hex encoded) of SUM. +# The function will return nonzero (and exit with failure if `set -e` is enabled) if the checksum does not match. +sha256check() { + sha256check_FILE="$1" + shift + sha256check_SUM="$1" + shift + if [ -x /usr/bin/shasum ]; then + printf "%s %s" "$sha256check_SUM" "$sha256check_FILE" | /usr/bin/shasum -a 256 -c >&2 + elif [ -x /usr/bin/sha256sum ]; then + printf "%s %s" "$sha256check_SUM" "$sha256check_FILE" | /usr/bin/sha256sum -c >&2 + else + printf "FATAL: %s\n" "No sha256 checksum utility found" >&2 + exit 107 + fi +} + +# [downloadfile URL FILE SUM] downloads from URL into FILE and verifies the SHA256 checksum of SUM. +# If the FILE already exists with the correct checksum it is not redownloaded. +# The function will exit with failure if the checksum does not match. +downloadfile() { + downloadfile_URL="$1" + shift + downloadfile_FILE="$1" + shift + downloadfile_SUM="$1" + shift + + # Set DKMLSYS_* + autodetect_system_binaries + + if [ -e "$downloadfile_FILE" ]; then + if sha256check "$downloadfile_FILE" "$downloadfile_SUM"; then + return 0 + else + $DKMLSYS_RM -f "$downloadfile_FILE" + fi + fi + if [ "${CI:-}" = true ]; then + if [ -n "$DKMLSYS_CURL" ]; then + log_trace "$DKMLSYS_CURL" -L -s "$downloadfile_URL" -o "$downloadfile_FILE".tmp + elif [ -n "$DKMLSYS_WGET" ]; then + log_trace "$DKMLSYS_WGET" -q -O "$downloadfile_FILE".tmp "$downloadfile_URL" + else + echo "No curl or wget available on the system paths" >&2 + exit 107 + fi + else + if [ -n "$DKMLSYS_CURL" ]; then + log_trace "$DKMLSYS_CURL" -L "$downloadfile_URL" -o "$downloadfile_FILE".tmp + elif [ -n "$DKMLSYS_WGET" ]; then + log_trace "$DKMLSYS_WGET" -O "$downloadfile_FILE".tmp "$downloadfile_URL" + else + echo "No curl or wget available on the system paths" >&2 + exit 107 + fi + fi + if ! sha256check "$downloadfile_FILE".tmp "$downloadfile_SUM"; then + printf "%s\n" "FATAL: Encountered a corrupted or compromised download from $downloadfile_URL" >&2 + exit 1 + fi + $DKMLSYS_MV "$downloadfile_FILE".tmp "$downloadfile_FILE" +} + +# --- Environment detection --- + +# Set DKMLSYS_* +autodetect_system_binaries + +# Find host ABI. Set in BUILDHOST_ARCH +autodetect_buildhost_arch + +# Use the project tree as the current directory +PROJ_DIR=$(dirname "$0") +PROJ_DIR=$(cd "$PROJ_DIR" && pwd) +cd "$PROJ_DIR" + +# --- Tool directory selection --- + +tools_dir= +tools_name=dktool +# 1. Check if CI since many CI providers can only cache content in a subdirectory +# of the project. +if [ -z "$tools_dir" ] && [ "${CI:-}" = true ]; then + install -d "$PROJ_DIR/.tools" + tools_dir="$PROJ_DIR/.tools" +fi +# 2. Check in locations rooted under /opt/diskuv +# We look under a /opt/diskuv early because +# - Especially important for WSL2 to use a pure Linux filesystem (ext4) for +# best performance. +# - Using a canonical location (especially /opt/diskuv/usr/share) makes +# it easy to use CMake presets for non-Windows hosts. +if [ -z "$tools_dir" ] && [ -n "${XDG_DATA_HOME:-}" ] && [ -w "/opt/diskuv/$XDG_DATA_HOME" ]; then + install -d "/opt/diskuv/$XDG_DATA_HOME/$tools_name" + tools_dir="/opt/diskuv/$XDG_DATA_HOME/$tools_name" +fi +if [ -z "$tools_dir" ] && [ -n "${HOME:-}" ] && [ -w "/opt/diskuv/$HOME" ]; then + install -d "/opt/diskuv/$HOME/.local/share/$tools_name" + tools_dir="/opt/diskuv/$HOME/.local/share/$tools_name" +fi +if [ -z "$tools_dir" ] && [ -w "/opt/diskuv/usr/share" ]; then + install -d "/opt/diskuv/usr/share/$tools_name" + tools_dir="/opt/diskuv/usr/share/$tools_name" +fi +# 3. Check in the conventional locations rooted under / +if [ -z "$tools_dir" ] && [ -n "${XDG_DATA_HOME:-}" ] && [ -w "$XDG_DATA_HOME" ]; then + install -d "$XDG_DATA_HOME/$tools_name" + tools_dir="$XDG_DATA_HOME/$tools_name" +fi +if [ -z "$tools_dir" ] && [ -n "${HOME:-}" ] && [ -w "$HOME" ]; then + install -d "$HOME/.local/share/$tools_name" + tools_dir="$HOME/.local/share/$tools_name" +fi +# 4. Validate +if [ -z "$tools_dir" ]; then + echo "FATAL: Could not find a location to install the tools necessary for this project." >&2 + echo " ...: Make sure you have a home directory and that it is write-able, or define" >&2 + echo " ...: the environment variable XDG_DATA_HOME in a shell profile script after" >&2 + echo " ...: creating the \$XDG_DATA_HOME directory." >&2 + exit 2 +fi + +# --- Tool downloads and installs --- + +# PREREQS +# ------- + +install_linux_prog() { + install_linux_prog_NAME=$1 + shift + install_linux_prog_PKG=$1 + shift + if [ -x "/usr/bin/$install_linux_prog_NAME" ]; then + export DK_PROG_INSTALLED_LOCATION="/usr/bin/$install_linux_prog_NAME" + else + if command -v yum > /dev/null 2> /dev/null; then + if [ "$(id -u)" -eq 0 ]; then + yum install -y "$install_linux_prog_PKG" + else + echo "Running: sudo yum install -y $install_linux_prog_PKG" + sudo yum install -y "$install_linux_prog_PKG" + fi + else + if [ "$(id -u)" -eq 0 ]; then + apt-get -q install -y "$install_linux_prog_PKG" + else + echo "Running: sudo -q apt-get -qq install -y --no-install-suggests $install_linux_prog_PKG" + sudo apt-get -qq install -y --no-install-suggests "$install_linux_prog_PKG" + fi + fi + DK_PROG_INSTALLED_LOCATION=$(command -v "$install_linux_prog_NAME") + export DK_PROG_INSTALLED_LOCATION + fi +} + +get_homebrew_binary() { + get_homebrew_binary_NAME=$1 + shift + if command -v brew > /dev/null 2> /dev/null; then + get_homebrew_binary_PREFIX=$(brew --prefix) + if [ -x "$get_homebrew_binary_PREFIX/bin/$get_homebrew_binary_NAME" ]; then + export DK_PROG_INSTALLED_LOCATION="$get_homebrew_binary_PREFIX/bin/$get_homebrew_binary_NAME" + return 0 + fi + fi + return 1 +} + +install_macos_prog() { + install_macos_prog_NAME=$1 + shift + install_macos_prog_PKG=$1 + shift + if [ -x "/usr/bin/$install_macos_prog_NAME" ]; then + export DK_PROG_INSTALLED_LOCATION="/usr/bin/$install_macos_prog_NAME" + elif [ -x "/usr/local/bin/$install_macos_prog_NAME" ]; then + export DK_PROG_INSTALLED_LOCATION="/usr/local/bin/$install_macos_prog_NAME" + elif get_homebrew_binary "$install_macos_prog_NAME"; then + # DK_PROG_INSTALLED_LOCATION already set by [get_homebrew_binary] + true + else + if command -v brew > /dev/null 2> /dev/null; then + brew install --quiet --formula "$install_macos_prog_PKG" >&2 + get_homebrew_binary "$install_macos_prog_NAME" + # DK_PROG_INSTALLED_LOCATION already set by [get_homebrew_binary] + elif command -v port > /dev/null 2> /dev/null; then + if [ "$(id -u)" -eq 0 ]; then + port install "$install_macos_prog_PKG" + else + echo "Running: sudo port install $install_macos_prog_PKG" + sudo port install "$install_macos_prog_PKG" + fi + DK_PROG_INSTALLED_LOCATION=$(command -v "$install_macos_prog_NAME") + export DK_PROG_INSTALLED_LOCATION + else + echo "FATAL: Neither Homebrew nor MacPorts are available on your macOS. You can follow https://docs.brew.sh/Installation to install Homebrew." >&2 + exit 2 + fi + fi +} + +case $BUILDHOST_ARCH in + linux_*) + install_linux_prog wget wget # For [downloadfile] + install_linux_prog tar tar # For handling tar balls later in this script + ;; +esac + +# NINJA +# ----- +# We need a valid CMAKE_GENERATOR to do FetchContent_Populate() in script mode + +NINJA_EXE= +case $BUILDHOST_ARCH in + darwin_*) + install_macos_prog ninja ninja + NINJA_EXE=$DK_PROG_INSTALLED_LOCATION;; + linux_*) + install_linux_prog ninja ninja-build + NINJA_EXE=$DK_PROG_INSTALLED_LOCATION;; +esac + +# CMAKE +# ----- + +case $BUILDHOST_ARCH in + linux_*) + # This is for CMake to do FetchContent() + install_linux_prog git git ;; +esac +case $BUILDHOST_ARCH in + linux_x86) + # This is for Python wheel extraction + install_linux_prog unzip unzip ;; +esac + +cmake_base= +cmake_majmin_ver=3.25 +cmake_majminpat_ver=3.25.2 +cmake_bindir= +cmake_destdir=$tools_dir/cmake-$cmake_majminpat_ver +install -d "$tools_dir/dl" +download_cmake() { + case $BUILDHOST_ARCH in + darwin_*) + install_macos_prog cmake cmake + cmake_bindir=$(dirname "$DK_PROG_INSTALLED_LOCATION") + ;; + linux_x86_64) + cmake_base="cmake-$cmake_majminpat_ver-linux-x86_64" + printf "%s\n\n" "-- Downloading cmake-$cmake_majminpat_ver for Linux x86_64" >&2 + downloadfile \ + "https://github.com/Kitware/CMake/releases/download/v$cmake_majminpat_ver/$cmake_base.tar.gz" \ + "$tools_dir/dl/cmake.tar.gz" \ + 783da74f132fd1fea91b8236d267efa4df5b91c5eec1dea0a87f0cf233748d99 + cmake_bindir="$cmake_destdir/bin" ;; + linux_x86) + # CMake does not provide 32-bit binaries. But pypi does at https://pypi.org/project/cmake/ + printf "%s\n\n" "-- Downloading cmake-$cmake_majminpat_ver for Linux x86" >&2 + downloadfile \ + https://files.pythonhosted.org/packages/11/6e/aeeddf2f5b16542b6a30ceab4896421e8705d8e9a9296dba79395db11b00/cmake-3.25.2-py2.py3-none-manylinux_2_17_i686.manylinux2014_i686.whl \ + "$tools_dir/dl/cmake.whl" \ + 715ef82e81b48db3e4c7744614c15ff361d53f6987fd70b1b66b0880595f2e2c + cmake_bindir="$cmake_destdir/bin" ;; + linux_arm64) + cmake_base="cmake-$cmake_majminpat_ver-linux-aarch64" + printf "%s\n\n" "-- Downloading cmake-$cmake_majminpat_ver for Linux ARM64" >&2 + downloadfile \ + "https://github.com/Kitware/CMake/releases/download/v$cmake_majminpat_ver/$cmake_base.tar.gz" \ + "$tools_dir/dl/cmake.tar.gz" \ + 9216ecf0449ade700e66e0def11eeaebf9fa7d4428c02f49cb59f11418d3f8a5 + cmake_bindir="$cmake_destdir/bin" ;; + esac +} +export_cmake_vars() { + case $BUILDHOST_ARCH in + darwin_*) + if command -v brew > /dev/null 2> /dev/null; then + cmake_bindir=$(brew --prefix cmake)/bin + else + cmake_bindir=$(command -v cmake) + cmake_bindir=$(dirname "$cmake_bindir") + fi + ;; + linux_x86_64) + cmake_bindir="$cmake_destdir/bin" ;; + linux_x86) + cmake_bindir="$cmake_destdir/bin" ;; + esac +} +have_correct_cmake=0 +if [ -x "$tools_dir/cmake-$cmake_majminpat_ver/bin/cmake" ]; then + # shellcheck disable=SC2016 + have_correct_cmake_VER=$("$tools_dir/cmake-$cmake_majminpat_ver/bin/cmake" --version | $DKMLSYS_AWK 'NR==1{print $NF}') + if [ "$have_correct_cmake_VER" = "$cmake_majminpat_ver" ]; then + have_correct_cmake=1 + fi +fi +if [ $have_correct_cmake -eq 0 ]; then + download_cmake +fi +# Handle tarball +if [ -e "$tools_dir/dl/cmake.tar.gz" ] && [ -n "$cmake_base" ]; then + rm -rf "$tools_dir/cmake-$cmake_majminpat_ver" + install -d "$cmake_destdir" + tar xCfz "$cmake_destdir" "$tools_dir/dl/cmake.tar.gz" + rm -f "$tools_dir/dl/cmake.tar.gz" + set +f + if [ -e "$cmake_destdir/$cmake_base/CMake.app" ]; then + mv "$cmake_destdir/$cmake_base/CMake.app/Contents"/* "$cmake_destdir/" + else + mv "$cmake_destdir/$cmake_base"/* "$cmake_destdir/" + fi + set -f +fi +# Handle Python wheel +if [ -e "$tools_dir/dl/cmake.whl" ]; then + rm -rf "$tools_dir/cmake-$cmake_majminpat_ver" + cd "$tools_dir/dl" + rm -rf cmake/data + # Don't want cmake/data/{aclocal,bash-completion,emacs,vim} + unzip -q cmake.whl 'cmake/data/bin/**' + unzip -q cmake.whl 'cmake/data/doc/**' + # Don't want cmake/data/share/cmake-$cmake_majmin_ver/Help + unzip -q cmake.whl "cmake/data/share/cmake-$cmake_majmin_ver/"'include/**' + unzip -q cmake.whl "cmake/data/share/cmake-$cmake_majmin_ver/"'Modules/**' + unzip -q cmake.whl "cmake/data/share/cmake-$cmake_majmin_ver/"'Templates/**' + rm -f cmake.whl + cd - + set +f + install -d "$cmake_destdir/share" "$cmake_destdir/doc" "$cmake_destdir/bin" + mv "$tools_dir/dl/cmake/data/bin"/* "$cmake_destdir/bin/" + rm -rf "$cmake_destdir/share/cmake-$cmake_majmin_ver" "$cmake_destdir/doc/cmake-$cmake_majmin_ver" "$cmake_destdir/doc/cmake" + mv "$tools_dir/dl/cmake/data/share/cmake-$cmake_majmin_ver" "$cmake_destdir/share/" + if [ -e "$tools_dir/dl/cmake/data/doc/cmake" ]; then # Windows wheel + mv "$tools_dir/dl/cmake/data/doc/cmake" "$cmake_destdir/doc/" + fi + if [ -e "$tools_dir/dl/cmake/data/doc/cmake-$cmake_majmin_ver" ]; then # Linux wheel + mv "$tools_dir/dl/cmake/data/doc/cmake-$cmake_majmin_ver" "$cmake_destdir/doc/" + fi + set -f + # other dirs: aclocal bash-completion emacs vim + rm -rf "$tools_dir/dl/cmake/data/share" + # be pedantic. if we don't know about a directory, it may be important. so error + # if some directory is non-empty + rmdir "$tools_dir/dl/cmake/data/bin" "$tools_dir/dl/cmake/data/doc" + rmdir "$tools_dir/dl/cmake/data" +fi + +# Put tools in PATH +export_cmake_vars +if [ -n "$cmake_bindir" ] && [ -d "$cmake_bindir" ]; then + tools_bin_dir=$(cd "$cmake_bindir" && pwd) + export PATH="$tools_bin_dir:$PATH" +else + echo "This platform is not supported. No cmake 3.25+ download logic has been added" >&2 + exit 1 +fi + +# Validate +"$cmake_bindir/cmake" --version > /dev/null + +# --- Run finder script --- + +cd "$PROJ_DIR" +"$cmake_bindir/cmake" \ + -D CMAKE_GENERATOR=Ninja -D CMAKE_MAKE_PROGRAM="$NINJA_EXE" \ + -D "DKTOOL_WORKDIR:FILEPATH=$tools_dir/work" -D "DKTOOL_CMDLINE:STRING=$*" \ + -P cmake/FindDkToolScripts.cmake \ No newline at end of file diff --git a/src/subprojects/c-capnproto/dk.cmd b/src/subprojects/c-capnproto/dk.cmd new file mode 100755 index 00000000..aeefd72b --- /dev/null +++ b/src/subprojects/c-capnproto/dk.cmd @@ -0,0 +1,146 @@ +@ECHO OFF +REM Recommendation: Place this file in source control. +REM Auto-generated by `./dk dksdk.project.new` of dktool. + +REM The canonical way to run this script is: ./dk +REM That works in Powershell on Windows, and in Unix. Copy-and-paste works! + +SETLOCAL + +REM Coding guidelines +REM 1. Microsoft way of getting around PowerShell permissions: +REM https://github.com/microsoft/vcpkg/blob/71422c627264daedcbcd46f01f1ed0dcd8460f1b/bootstrap-vcpkg.bat +REM 2. Write goto downward please so code flow is top to bottom. + +SET DK_CMAKE_VER=3.25.3 +SET DK_NINJA_VER=1.11.1 +SET DK_BUILD_TYPE=Release +SET DK_SHARE=%LOCALAPPDATA%\Programs\DkSDK\dktool +SET DK_PROJ_DIR=%~dp0 + +REM -------------- CMAKE -------------- + +REM Find CMAKE.EXE +where.exe /q cmake.exe >NUL 2>NUL +IF %ERRORLEVEL% neq 0 ( + goto FindDownloadedCMake +) +FOR /F "tokens=* usebackq" %%F IN (`where.exe cmake.exe`) DO ( + SET "DK_CMAKE_EXE=%%F" +) + +REM Check if present at /cmake-VER/bin/cmake.exe +:FindDownloadedCMake +IF EXIST %DK_SHARE%\cmake-%DK_CMAKE_VER%-windows-x86_64\bin\cmake.exe ( + SET "DK_CMAKE_EXE=%DK_SHARE%\cmake-%DK_CMAKE_VER%-windows-x86_64\bin\cmake.exe" + GOTO ValidateCMake +) + +REM Download CMAKE.EXE +bitsadmin /transfer dktool-cmake /download /priority FOREGROUND ^ + "https://github.com/Kitware/CMake/releases/download/v%DK_CMAKE_VER%/cmake-%DK_CMAKE_VER%-windows-x86_64.zip" ^ + "%TEMP%\cmake-%DK_CMAKE_VER%-windows-x86_64.zip" +IF %ERRORLEVEL% equ 0 ( + GOTO UnzipCMakeZip +) +REM Try PowerShell 3+ instead +powershell -NoProfile -ExecutionPolicy Bypass -Command ^ + "Invoke-WebRequest https://github.com/Kitware/CMake/releases/download/v%DK_CMAKE_VER%/cmake-%DK_CMAKE_VER%-windows-x86_64.zip -OutFile '%TEMP%\cmake-%DK_CMAKE_VER%-windows-x86_64.zip'" +IF %ERRORLEVEL% neq 0 ( + echo. + echo.Could not download CMake %DK_CMAKE_VER%. Make sure that PowerShell is installed + echo.and has not been disabled by a corporate policy. + echo. + EXIT /b 1 +) + +REM Unzip CMAKE.EXE (use PowerShell; could download unzip.exe and sha256sum.exe as well in case corporate policy) +:UnzipCMakeZip +powershell -NoProfile -ExecutionPolicy Bypass -Command ^ + "Expand-Archive '%TEMP%\cmake-%DK_CMAKE_VER%-windows-x86_64.zip' -DestinationPath '%DK_SHARE%'" +IF %ERRORLEVEL% neq 0 ( + echo. + echo.Could not unzip CMake %DK_CMAKE_VER%. Make sure that PowerShell is installed + echo.and has not been disabled by a corporate policy. + echo. + EXIT /b 1 +) +SET "DK_CMAKE_EXE=%DK_SHARE%\cmake-%DK_CMAKE_VER%-windows-x86_64\bin\cmake.exe" + +REM Validate cmake.exe +:ValidateCMake +"%DK_CMAKE_EXE%" -version >NUL 2>NUL +if %ERRORLEVEL% neq 0 ( + echo. + echo.%DK_CMAKE_EXE% + echo.is not responding to the -version option. Make sure that + echo.CMake is installed correctly. + echo. + exit /b 1 +) + +REM -------------- NINJA -------------- + +REM Find NINJA.EXE +where.exe /q ninja.exe >NUL 2>NUL +IF %ERRORLEVEL% neq 0 ( + goto FindDownloadedNinja +) +FOR /F "tokens=* usebackq" %%F IN (`where.exe ninja.exe`) DO ( + SET "DK_NINJA_EXE=%%F" +) + +REM Check if present at /ninja-VER/bin/ninja.exe +:FindDownloadedNinja +IF EXIST %DK_SHARE%\ninja-%DK_NINJA_VER%-windows-x86_64\bin\ninja.exe ( + SET "DK_NINJA_EXE=%DK_SHARE%\ninja-%DK_NINJA_VER%-windows-x86_64\bin\ninja.exe" + GOTO ValidateNinja +) + +REM Download NINJA.EXE +bitsadmin /transfer dktool-ninja /download /priority FOREGROUND ^ + "https://github.com/ninja-build/ninja/releases/download/v%DK_NINJA_VER%/ninja-win.zip" ^ + "%TEMP%\ninja-%DK_NINJA_VER%-windows-x86_64.zip" +IF %ERRORLEVEL% equ 0 ( + GOTO UnzipNinjaZip +) +REM Try PowerShell 3+ instead +powershell -NoProfile -ExecutionPolicy Bypass -Command ^ + "Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v%DK_NINJA_VER%/ninja-win.zip -OutFile '%TEMP%\ninja-%DK_NINJA_VER%-windows-x86_64.zip'" +IF %ERRORLEVEL% neq 0 ( + echo. + echo.Could not download Ninja %DK_NINJA_VER%. Make sure that PowerShell is installed + echo.and has not been disabled by a corporate policy. + echo. + EXIT /b 1 +) + +REM Unzip NINJA.EXE (use PowerShell; could download unzip.exe and sha256sum.exe as well in case corporate policy) +:UnzipNinjaZip +powershell -NoProfile -ExecutionPolicy Bypass -Command ^ + "Expand-Archive '%TEMP%\ninja-%DK_NINJA_VER%-windows-x86_64.zip' -DestinationPath '%DK_SHARE%\ninja-%DK_NINJA_VER%-windows-x86_64\bin'" +IF %ERRORLEVEL% neq 0 ( + echo. + echo.Could not unzip Ninja %DK_NINJA_VER%. Make sure that PowerShell is installed + echo.and has not been disabled by a corporate policy. + echo. + EXIT /b 1 +) +SET "DK_NINJA_EXE=%DK_SHARE%\ninja-%DK_NINJA_VER%-windows-x86_64\bin\ninja.exe" + +REM Validate ninja.exe +:ValidateNinja +"%DK_NINJA_EXE%" --version >NUL 2>NUL +if %ERRORLEVEL% neq 0 ( + echo. + echo.%DK_NINJA_EXE% + echo.is not responding to the --version option. Make sure that + echo.Ninja is installed correctly. + echo. + exit /b 1 +) + +REM -------------- Run finder -------------- + +cd %DK_PROJ_DIR% +"%DK_CMAKE_EXE%" -D CMAKE_GENERATOR=Ninja -D "CMAKE_MAKE_PROGRAM=%DK_NINJA_EXE%" -D "DKTOOL_WORKDIR:FILEPATH=%DK_SHARE%\work" -D "DKTOOL_CMDLINE:STRING=%*" -P cmake/FindDkToolScripts.cmake diff --git a/src/subprojects/c-capnproto/environment.yml b/src/subprojects/c-capnproto/environment.yml new file mode 100644 index 00000000..9736cc9f --- /dev/null +++ b/src/subprojects/c-capnproto/environment.yml @@ -0,0 +1,7 @@ +name: c-capnproto +# channels: +# - conda-forge +# - defaults +dependencies: + - 'python>=3.8' + - meson diff --git a/src/subprojects/c-capnproto/examples/book/CMakeLists.txt b/src/subprojects/c-capnproto/examples/book/CMakeLists.txt new file mode 100644 index 00000000..8dc1c1cc --- /dev/null +++ b/src/subprojects/c-capnproto/examples/book/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.10) +project(MyCapnpProject) + +# Find the Cap'n Proto compiler and C plugin +find_program(CAPNP_EXECUTABLE capnp) + +if(NOT CAPNP_EXECUTABLE) + message(FATAL_ERROR "capnp compiler not found!") +endif() + +# Schema file (adjust path as needed) +set(SCHEMA_FILE "book.capnp") + +# Generated file paths (outputs in the build directory) +set(GENERATED_C "${CMAKE_CURRENT_BINARY_DIR}/${SCHEMA_FILE}.c") +set(GENERATED_H "${CMAKE_CURRENT_BINARY_DIR}/${SCHEMA_FILE}.h") + +# Generate C++ sources from the schema +add_custom_command( + OUTPUT ${GENERATED_C} ${GENERATED_H} + COMMAND ${CAPNP_EXECUTABLE} compile + -o $:${CMAKE_CURRENT_BINARY_DIR} + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../compiler + --src-prefix ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/${SCHEMA_FILE} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${SCHEMA_FILE} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating C code for ${SCHEMA_FILE}" +) + +# Create an executable/library and include generated files +add_executable(book test.c ${GENERATED_C}) + +# Include directory for generated headers +target_include_directories(book PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link against Cap'n Proto libraries +target_link_libraries(book PRIVATE + capnp + CapnC_Runtime +) diff --git a/src/subprojects/c-capnproto/examples/book/book.capnp b/src/subprojects/c-capnproto/examples/book/book.capnp new file mode 100644 index 00000000..1e759de2 --- /dev/null +++ b/src/subprojects/c-capnproto/examples/book/book.capnp @@ -0,0 +1,42 @@ +@0xf9ffb48dde27c0e6; + +using C = import "/c.capnp"; +$C.fieldgetset; +$C.codecgen; +$C.extraheader("#include "); + +struct Chapter $C.mapname("chapter_t") { + caption @0: Text; + start @1: UInt32; + end @2: UInt32; +} + +struct Publish $C.mapname("publish_t") { + isbn @0: UInt64; + year @1: UInt32; +} + +struct Nulldata $C.mapname("nulldata_t") { + null @0: UInt32 $C.mapname("null_"); +} + +struct Buy $C.mapname("buy_t") { + from @0: Text; + u :union $C.mapname("u") $C.mapuniontag("with_recipe") { + norecipe @1: Void; + recipeAddr @2: Text $C.mapname("recipe_addr"); + } +} +struct Book $C.mapname("book_t") { + title @0: Text; + authors @1: List(Text) $C.mapname("authors") $C.maplistcount("n_authors"); + chapters @5: List(Chapter) $C.mapname("chapters_") $C.maplistcount("n_chapters"); + publish @6: Publish; + nulldata @7: Nulldata; + magic1 @2: List(UInt32) $C.mapname("magic_1") $C.maplistcount("n_magic1"); + description @8: Text; + acquire :union $C.mapuniontag("acquire_method") { + buy @3: Buy; + donation @4: Text; + } +} diff --git a/src/subprojects/c-capnproto/examples/book/book.h b/src/subprojects/c-capnproto/examples/book/book.h new file mode 100644 index 00000000..91a9b9fe --- /dev/null +++ b/src/subprojects/c-capnproto/examples/book/book.h @@ -0,0 +1,49 @@ +#if !defined(_BOOK_H_) + +#define _BOOK_H_ 1 + +#include +#include + +typedef struct { + char *caption; + int32_t start; + int32_t end; +} chapter_t; + +typedef struct { + uint64_t isbn; + uint32_t year; +} publish_t; + +typedef struct { + int null_; +} nulldata_t; + +typedef struct { + char *from; + int with_recipe; + union { + char *recipe_addr; + } u; +} buy_t; + +typedef struct { + char *title; + int n_authors; + char **authors; + int n_chapters; + chapter_t **chapters_; + publish_t *publish; + nulldata_t *nulldata; + int n_magic1; + uint32_t *magic_1; + char *description; + int acquire_method; + union { + buy_t *buy; + char *donation; + } acquire; +} book_t; + +#endif diff --git a/src/subprojects/c-capnproto/examples/book/test.c b/src/subprojects/c-capnproto/examples/book/test.c new file mode 100644 index 00000000..7e6272fe --- /dev/null +++ b/src/subprojects/c-capnproto/examples/book/test.c @@ -0,0 +1,147 @@ +#include +#include + +#include "book.capnp.h" +#include "book.h" + +static void usage(char *app) { + fprintf(stderr, "usage: %s encode | %s decode\n", + app, app); +} + +int encode() { + struct capn c; + book_t book; + char *title = "Book title"; + char *authors[2] = { + "author1", + "author2" + }; + uint32_t magic1[2] = { + 1101,1012 + }; + chapter_t chapters_[3] = { + {.caption ="Chapter1", + .start =1, + .end=99}, + {.caption = "Chapter2", + .start = 100, + .end = 150}, + {.caption = "Chapter3", + .start = 151, + .end=199} + }; + chapter_t* chapters[3] = { + &chapters_[0], &chapters_[1], &chapters_[2] + }; + publish_t publish = { + .isbn = 335677, + .year =2001 + }; + buy_t buy = { + .from = "Xinghua Book store", + .with_recipe = Buy_u_recipeAddr, + .u = { + .recipe_addr = "Xinghua Street" + } + }; + struct capn_segment *cs; + struct Book b; + Book_ptr p; + + book.title = title; + book.n_authors = 2; + book.authors = authors; + book.n_chapters = 3; + book.chapters_ = &chapters[0]; + book.publish = &publish ; + book.nulldata = NULL; + book.n_magic1 = 2; + book.magic_1 = &magic1[0]; + book.description = NULL; + book.acquire_method = Book_acquire_buy; + book.acquire.buy = &buy; + + capn_init_malloc(&c); + cs = capn_root(&c).seg; + + encode_Book_ptr(cs, &p, &book); + + capn_setp(capn_root(&c), 0, p.p); + + capn_write_fd(&c, write, 1, 0); + + capn_free(&c); + + return 0; +} + +int decode() { + struct capn c; + Book_ptr p; + book_t *book; + int i; + + capn_init_fp(&c, stdin, 0); + p.p = capn_getp(capn_root(&c), 0, 1); + + decode_Book_ptr(&book, p); + + printf("title: %s\n", book->title); + + printf("authors(%d):\n", book->n_authors); + + for(i = 0; i < book->n_authors; i ++) { + printf("\t%s\n", book->authors[i]); + } + + printf("chapters(%d):\n", book->n_chapters); + for(i = 0; i < book->n_chapters; i ++) { + printf("\tcaption: %s\n", book->chapters_[i]->caption); + printf("\tfrom %d to %d\n", + book->chapters_[i]->start, + book->chapters_[i]->end); + } + + printf("ISBN: %lu year: %u\n", + book->publish->isbn, + book->publish->year); + + printf("magic1:\n"); + for(i = 0; i < book->n_magic1; i ++) { + printf("\t%d\n", book->magic_1[i]); + } + + if (book->acquire_method == Book_acquire_buy) { + printf("buy from %s\n", book->acquire.buy->from); + if (book->acquire.buy->with_recipe == Buy_u_recipeAddr) { + printf("recipe address %s\n", + book->acquire.buy->u.recipe_addr); + } + } + else { + printf("%s\n", book->acquire.donation); + } + + free_Book_ptr(&book); + capn_free(&c); + + return 0; +} + +int main(int argc,char *argv[]) { + + if (argc != 2) { + usage(argv[0]); + return -1; + } + + if ( strcmp(argv[1],"encode") == 0) { + encode(); + } + else { + decode(); + } + + return 0; +} diff --git a/src/subprojects/c-capnproto/lib/capn-list.inc b/src/subprojects/c-capnproto/lib/capn-list.inc new file mode 100644 index 00000000..ad94ec8f --- /dev/null +++ b/src/subprojects/c-capnproto/lib/capn-list.inc @@ -0,0 +1,162 @@ +/* capn-list.inc + * + * Copyright (C) 2013 James McKaskill + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#define CAT2(A,B) A ## B +#define CAT(A,B) CAT2(A, B) +#define UINT_T CAT(CAT(uint, SZ), _t) +#define LIST_T CAT(capn_list, SZ) +#define FLIP CAT(capn_flip, SZ) + +UINT_T CAT(capn_get,SZ) (LIST_T l, int off) { + char *d; + capn_ptr p = l.p; + if (off >= p.len) { + return 0; + } + + switch (p.type) { + case CAPN_LIST: + if (p.datasz < SZ/8) + return 0; + d = p.data + off * (p.datasz + 8*p.ptrs); + return FLIP(*(UINT_T*)d); + + case CAPN_PTR_LIST: + d = struct_ptr(p.seg, p.data + 8*off, SZ/8); + if (d) { + return FLIP(*(UINT_T*)d); + } else { + return 0; + } + + default: + return 0; + } +} + +int CAT(capn_getv,SZ) (LIST_T l, int off, UINT_T *to, int sz) { + int i; + capn_ptr p; + capn_resolve(&l.p); + p = l.p; + if (off + sz > p.len) { + sz = p.len - off; + } + + switch (p.type) { + case CAPN_LIST: + if (p.datasz == SZ/8 && !p.ptrs && (SZ == 8 || CAPN_LITTLE)) { + memcpy(to, p.data + off, sz * (SZ/8)); + return sz; + } else if (p.datasz < SZ/8) { + return -1; + } + + for (i = 0; i < sz; i++) { + char *d = p.data + (i + off) * (p.datasz + 8*p.ptrs); + to[i] = FLIP(*(UINT_T*)d); + } + return sz; + + case CAPN_PTR_LIST: + for (i = 0; i < sz; i++) { + char *d = struct_ptr(p.seg, p.data + 8*(i+off), SZ/8); + if (d) { + to[i] = FLIP(*(UINT_T*)d); + } else { + return -1; + } + } + return sz; + + default: + return -1; + } +} + +int CAT(capn_set,SZ) (LIST_T l, int off, UINT_T v) { + char *d; + capn_ptr p = l.p; + if (off >= p.len) { + return -1; + } + + switch (p.type) { + case CAPN_LIST: + if (p.datasz < SZ/8) + return -1; + d = p.data + off * (p.datasz + 8*p.ptrs); + *(UINT_T*) d = FLIP(v); + return 0; + + case CAPN_PTR_LIST: + d = struct_ptr(p.seg, p.data + 8*off, SZ/8); + if (!d) { + return -1; + } + *(UINT_T*) d = FLIP(v); + return 0; + + default: + return -1; + } +} + +int CAT(capn_setv,SZ) (LIST_T l, int off, const UINT_T *from, int sz) { + int i; + capn_ptr p = l.p; + if (off + sz > p.len) { + sz = p.len - off; + } + + switch (p.type) { + case CAPN_LIST: + if (p.datasz == SZ/8 && !p.ptrs && (SZ == 8 || CAPN_LITTLE)) { + memcpy(p.data + off, from, sz * (SZ/8)); + return sz; + } else if (p.datasz < SZ/8) { + return -1; + } + + for (i = 0; i < sz; i++) { + char *d = p.data + (i + off) * (p.datasz + 8*p.ptrs); + *(UINT_T*) d = FLIP(from[i]); + } + return sz; + + case CAPN_PTR_LIST: + for (i = 0; i < sz; i++) { + char *d = struct_ptr(p.seg, p.data + 8*(i+off), SZ/8); + if (d) { + *(UINT_T*) d = FLIP(from[i]); + } else { + return -1; + } + } + return sz; + + default: + return -1; + } +} + +LIST_T CAT(capn_new_list,SZ) (struct capn_segment *seg, int sz) { + LIST_T l = {{CAPN_LIST}}; + l.p.seg = seg; + l.p.len = sz; + l.p.datasz = SZ/8; + new_object(&l.p, sz*(SZ/8)); + return l; +} + +#undef CAT2 +#undef CAT +#undef UINT_T +#undef LIST_T +#undef FLIP + diff --git a/src/subprojects/c-capnproto/lib/capn-malloc.c b/src/subprojects/c-capnproto/lib/capn-malloc.c new file mode 100644 index 00000000..569bef9b --- /dev/null +++ b/src/subprojects/c-capnproto/lib/capn-malloc.c @@ -0,0 +1,435 @@ +/* vim: set sw=8 ts=8 sts=8 noet: */ +/* capn-malloc.c + * + * Copyright (C) 2013 James McKaskill + * Copyright (C) 2014 Steve Dee + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#include "capnp_c.h" +#include "capnp_priv.h" +#include +#include +#include +#include + +/* + * 8 byte alignment is required for struct capn_segment. + * This struct check_segment_alignment verifies this at compile time. + * + * Unless capn_segment is defined with 8 byte alignment, check_segment_alignment + * fails to compile in x86 mode (or on another CPU with 32-bit pointers), + * as (sizeof(struct capn_segment)&7) -> (44 & 7) evaluates to 4. + * It compiles in x64 mode (or on another CPU with 64-bit pointers), + * as (sizeof(struct capn_segment)&7) -> (80 & 7) evaluates to 0. + */ +struct check_segment_alignment { + unsigned int foo : (sizeof(struct capn_segment)&7) ? -1 : 1; +}; + +static struct capn_segment *create(void *u, uint32_t id, int sz) { + struct capn_segment *s; + sz += sizeof(*s); + if (sz < 4096) { + sz = 4096; + } else { + sz = (sz + 4095) & ~4095; + } + s = (struct capn_segment*) calloc(1, sz); + s->data = (char*) (s+1); + s->cap = sz - sizeof(*s); + s->user = s; + return s; +} + +static struct capn_segment *create_local(void *u, int sz) { + return create(u, 0, sz); +} + +void capn_init_malloc(struct capn *c) { + memset(c, 0, sizeof(*c)); + c->create = &create; + c->create_local = &create_local; +} + +void capn_free(struct capn *c) { + struct capn_segment *s = c->seglist; + while (s != NULL) { + struct capn_segment *n = s->next; + free(s->user); + s = n; + } + capn_reset_copy(c); +} + +void capn_reset_copy(struct capn *c) { + struct capn_segment *s = c->copylist; + while (s != NULL) { + struct capn_segment *n = s->next; + free(s->user); + s = n; + } + c->copy = NULL; + c->copylist = NULL; +} + +#define ZBUF_SZ 4096 + +static int read_fp(void *p, size_t sz, FILE *f, struct capn_stream *z, uint8_t* zbuf, int packed) { + if (f && packed) { + z->next_out = (uint8_t*) p; + z->avail_out = sz; + + while (z->avail_out && capn_inflate(z) == CAPN_NEED_MORE) { + int r; + memmove(zbuf, z->next_in, z->avail_in); + r = fread(zbuf+z->avail_in, 1, ZBUF_SZ - z->avail_in, f); + if (r <= 0) + return -1; + z->avail_in += r; + } + return 0; + + } else if (f && !packed) { + return fread(p, sz, 1, f) != 1; + + } else if (packed) { + z->next_out = (uint8_t*) p; + z->avail_out = sz; + return capn_inflate(z) != 0; + + } else { + if (z->avail_in < sz) + return -1; + memcpy(p, z->next_in, sz); + z->next_in += sz; + z->avail_in -= sz; + return 0; + } +} + +static int init_fp(struct capn *c, FILE *f, struct capn_stream *z, int packed) { + /* + * Initialize 'c' from the contents of 'f', assuming the message has been + * serialized with the standard framing format. From https://capnproto.org/encoding.html: + * + * When transmitting over a stream, the following should be sent. All integers are unsigned and little-endian. + * (4 bytes) The number of segments, minus one (since there is always at least one segment). + * (N * 4 bytes) The size of each segment, in words. + * (0 or 4 bytes) Padding up to the next word boundary. + * The content of each segment, in order. + */ + + struct capn_segment *s = NULL; + uint32_t i, segnum, total = 0; + uint32_t hdr[1024]; + uint8_t zbuf[ZBUF_SZ]; + char *data = NULL; + + capn_init_malloc(c); + + /* Read the first four bytes to know how many headers we have */ + if (read_fp(&segnum, 4, f, z, zbuf, packed)) + goto err; + + segnum = capn_flip32(segnum); + if (segnum > 1023) + goto err; + segnum++; /* The wire encoding was zero-based */ + + /* Read the header list */ + if (read_fp(hdr, 8 * (segnum/2) + 4, f, z, zbuf, packed)) + goto err; + + for (i = 0; i < segnum; i++) { + uint32_t n = capn_flip32(hdr[i]); + if (n > INT_MAX/8 || n > UINT32_MAX/8 || UINT32_MAX - total < n*8) + goto err; + hdr[i] = n*8; + total += hdr[i]; + } + + /* Allocate space for the data and the capn_segment structs */ + s = (struct capn_segment*) calloc(1, total + (sizeof(*s) * segnum)); + if (!s) + goto err; + + /* Now read the data and setup the capn_segment structs */ + data = (char*) (s+segnum); + if (read_fp(data, total, f, z, zbuf, packed)) + goto err; + + for (i = 0; i < segnum; i++) { + s[i].len = s[i].cap = hdr[i]; + s[i].data = data; + data += s[i].len; + capn_append_segment(c, &s[i]); + } + + /* Set the entire region to be freed on the last segment */ + s[segnum-1].user = s; + + return 0; + +err: + memset(c, 0, sizeof(*c)); + free(s); + return -1; +} + +int capn_init_fp(struct capn *c, FILE *f, int packed) { + struct capn_stream z; + memset(&z, 0, sizeof(z)); + return init_fp(c, f, &z, packed); +} + +int capn_init_mem(struct capn *c, const uint8_t *p, size_t sz, int packed) { + struct capn_stream z; + memset(&z, 0, sizeof(z)); + z.next_in = p; + z.avail_in = sz; + return init_fp(c, NULL, &z, packed); +} + +static void header_calc(struct capn *c, uint32_t *headerlen, size_t *headersz) +{ + /* segnum == 1: + * [segnum][segsiz] + * segnum == 2: + * [segnum][segsiz][segsiz][zeroes] + * segnum == 3: + * [segnum][segsiz][segsiz][segsiz] + * segnum == 4: + * [segnum][segsiz][segsiz][segsiz][segsiz][zeroes] + */ + *headerlen = ((2 + c->segnum) / 2) * 2; + *headersz = 4 * *headerlen; +} + +static int header_render(struct capn *c, struct capn_segment *seg, uint32_t *header, uint32_t headerlen, size_t *datasz) +{ + size_t i; + + header[0] = capn_flip32(c->segnum - 1); + header[headerlen-1] = 0; /* Zero out the spare position in the header sizes */ + for (i = 0; i < c->segnum; i++, seg = seg->next) { + if (0 == seg) + return -1; + *datasz += seg->len; + header[1 + i] = capn_flip32(seg->len / 8); + } + if (0 != seg) + return -1; + + return 0; +} + +static int64_t capn_write_mem_packed(struct capn *c, uint8_t *p, size_t sz) +{ + struct capn_segment *seg; + struct capn_ptr root; + uint32_t headerlen; + size_t headersz, datasz = 0; + uint32_t *header; + struct capn_stream z; + int ret; + + root = capn_root(c); + header_calc(c, &headerlen, &headersz); + header = (uint32_t*) (p + headersz + 2); /* must reserve two bytes for worst case expansion */ + + if (sz < headersz*2 + 2) /* We must have space for temporary writing of header to deflate */ + return -1; + + ret = header_render(c, root.seg, header, headerlen, &datasz); + if (ret != 0) + return -1; + + memset(&z, 0, sizeof(z)); + z.next_in = (uint8_t *)header; + z.avail_in = headersz; + z.next_out = p; + z.avail_out = sz; + + // pack the headers + ret = capn_deflate(&z); + if (ret != 0 || z.avail_in != 0) + return -1; + + for (seg = root.seg; seg; seg = seg->next) { + z.next_in = (uint8_t *)seg->data; + z.avail_in = seg->len; + ret = capn_deflate(&z); + if (ret != 0 || z.avail_in != 0) + return -1; + } + + return (int64_t)(sz - z.avail_out); +} + +int64_t +capn_write_mem(struct capn *c, uint8_t *p, size_t sz, int packed) +{ + struct capn_segment *seg; + struct capn_ptr root; + uint32_t headerlen; + size_t headersz, datasz = 0; + uint32_t *header; + int ret; + + if (c->segnum == 0) + return -1; + + if (packed) + return capn_write_mem_packed(c, p, sz); + + root = capn_root(c); + header_calc(c, &headerlen, &headersz); + header = (uint32_t*) p; + + if (sz < headersz) + return -1; + + ret = header_render(c, root.seg, header, headerlen, &datasz); + if (ret != 0) + return -1; + + if (sz < headersz + datasz) + return -1; + + p += headersz; + + for (seg = root.seg; seg; seg = seg->next) { + memcpy(p, seg->data, seg->len); + p += seg->len; + } + + return (int64_t)(headersz + datasz); +} + +static int _write_fd(ssize_t (*write_fd)(int fd, const void *p, size_t count), int fd, void *p, size_t count) +{ + ssize_t ret; + size_t sent = 0; + + while (sent < count) { + ret = write_fd(fd, ((uint8_t*)p)+sent, count-sent); + if (ret < 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + else + return -1; + } + sent += ret; + } + + return 0; +} + +int capn_write_fd(struct capn *c, ssize_t (*write_fd)(int fd, const void *p, size_t count), int fd, int packed) +{ + unsigned char buf[4096]; + struct capn_segment *seg; + struct capn_ptr root; + uint32_t headerlen; + size_t headersz, datasz = 0; + int ret; + struct capn_stream z; + unsigned char *p; + + if (c->segnum == 0) + return -1; + + root = capn_root(c); + header_calc(c, &headerlen, &headersz); + + if (sizeof(buf) < headersz) + return -1; + + ret = header_render(c, root.seg, (uint32_t*)buf, headerlen, &datasz); + if (ret != 0) + return -1; + + if (packed) { + const int headerrem = sizeof(buf) - headersz; + const int maxpack = headersz + 2; + if (headerrem < maxpack) + return -1; + + memset(&z, 0, sizeof(z)); + z.next_in = buf; + z.avail_in = headersz; + z.next_out = buf + headersz; + z.avail_out = headerrem; + ret = capn_deflate(&z); + if (ret != 0) + return -1; + + p = buf + headersz; + headersz = headerrem - z.avail_out; + } else { + p = buf; + } + + ret = _write_fd(write_fd, fd, p, headersz); + if (ret < 0) + return -1; + + datasz = headersz; + for (seg = root.seg; seg; seg = seg->next) { + size_t bufsz; + if (packed) { + memset(&z, 0, sizeof(z)); + z.next_in = (uint8_t*)seg->data; + z.avail_in = seg->len; + z.next_out = buf; + z.avail_out = sizeof(buf); + ret = capn_deflate(&z); + if (ret != 0) + return -1; + p = buf; + bufsz = sizeof(buf) - z.avail_out; + } else { + p = (uint8_t*)seg->data; + bufsz = seg->len; + } + ret = _write_fd(write_fd, fd, p, bufsz); + if (ret < 0) + return -1; + datasz += bufsz; + } + + return datasz; +} + +int64_t capn_size(struct capn *c) +{ + size_t headersz, datasz = 0; + struct capn_ptr root; + struct capn_segment *seg; + uint32_t i; + + if (c->segnum == 0) + return -1; + + root = capn_root(c); + seg = root.seg; + + headersz = 8 * ((2 + c->segnum) / 2); + + for (i = 0; i < c->segnum; i++, seg = seg->next) { + if (0 == seg) + return -1; + datasz += seg->len; + } + if (0 != seg) + return -1; + + return (int64_t)(headersz + datasz); +} diff --git a/src/subprojects/c-capnproto/lib/capn-stream.c b/src/subprojects/c-capnproto/lib/capn-stream.c new file mode 100644 index 00000000..135d1b2b --- /dev/null +++ b/src/subprojects/c-capnproto/lib/capn-stream.c @@ -0,0 +1,217 @@ +/* vim: set sw=8 ts=8 sts=8 noet: */ +/* capn-stream.c + * + * Copyright (C) 2013 James McKaskill + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include "capnp_c.h" +#include "capnp_priv.h" +#include + +#ifndef min +static unsigned min(unsigned a, unsigned b) { return (a < b) ? a : b; } +#endif + +int capn_deflate(struct capn_stream* s) { + if (s->avail_in % 8) { + return CAPN_MISALIGNED; + } + + while (s->avail_in) { + int i; + size_t sz; + uint8_t hdr = 0; + uint8_t *p; + + if (!s->avail_out) + return CAPN_NEED_MORE; + + if (s->raw > 0) { + sz = min(s->raw, min(s->avail_in, s->avail_out)); + memcpy(s->next_out, s->next_in, sz); + s->next_out += sz; + s->next_in += sz; + s->avail_out -= sz; + s->avail_in -= sz; + s->raw -= sz; + continue; + } + + if (s->avail_in < 8) + return CAPN_NEED_MORE; + + sz = 0; + for (i = 0; i < 8; i++) { + if (s->next_in[i]) { + sz ++; + hdr |= 1 << i; + } + } + + switch (sz) { + case 0: + if (s->avail_out < 2) + return CAPN_NEED_MORE; + + s->next_out[0] = 0; + for (sz = 1; sz < min(s->avail_in/8, 256); sz++) { + if (((uint64_t*) s->next_in)[sz] != 0) { + break; + } + } + + s->next_out[1] = (uint8_t) (sz-1); + s->next_in += sz*8; + s->avail_in -= sz*8; + s->next_out += 2; + s->avail_out -= 2; + continue; + + case 8: + if (s->avail_out < 10) + return CAPN_NEED_MORE; + + s->next_out[0] = 0xFF; + memcpy(s->next_out+1, s->next_in, 8); + s->next_in += 8; + s->avail_in -= 8; + + s->raw = min(s->avail_in, 256*8); + if ((p = (uint8_t*) memchr(s->next_in, 0, s->raw)) != NULL) { + s->raw = (p - s->next_in) & ~7; + } + + s->next_out[9] = (uint8_t) (s->raw/8); + s->next_out += 10; + s->avail_out -= 10; + continue; + + default: + if (s->avail_out < 1U + sz) + return CAPN_NEED_MORE; + + *(s->next_out++) = hdr; + for (i = 0; i < 8; i++) { + if (s->next_in[i]) { + *(s->next_out++) = s->next_in[i]; + } + } + s->avail_out -= sz + 1; + s->next_in += 8; + s->avail_in -= 8; + continue; + } + } + + return 0; +} + +int capn_inflate(struct capn_stream* s) { + while (s->avail_out) { + int i; + size_t sz; + uint8_t hdr; + uint8_t *wr; + + if (s->avail_buf && s->avail_out >= s->avail_buf) { + memcpy(s->next_out, s->inflate_buf, s->avail_buf); + s->next_out += s->avail_buf; + s->avail_out -= s->avail_buf; + s->avail_buf = 0; + if (!s->avail_out) + return 0; + } + if (s->avail_buf && s->avail_out < s->avail_buf) { + memcpy(s->next_out, s->inflate_buf, s->avail_out); + memmove(s->inflate_buf, s->inflate_buf + s->avail_out, + s->avail_buf - s->avail_out); + s->avail_buf -= s->avail_out; + s->avail_out = 0; + return 0; + } + + if (s->zeros > 0) { + sz = min(s->avail_out, s->zeros); + memset(s->next_out, 0, sz); + s->next_out += sz; + s->avail_out -= sz; + s->zeros -= sz; + continue; + } + + if (s->raw > 0) { + if (s->avail_in == 0) + return CAPN_NEED_MORE; + + sz = min(min(s->avail_out, s->raw), s->avail_in); + memcpy(s->next_out, s->next_in, sz); + s->next_in += sz; + s->next_out += sz; + s->avail_in -= sz; + s->avail_out -= sz; + s->raw -= sz; + continue; + } + + if (s->avail_in == 0) + return 0; + else if (s->avail_in < 2) + return CAPN_NEED_MORE; + + switch (s->next_in[0]) { + case 0xFF: + /* 0xFF is followed by 8 bytes raw, followed by + * a byte with length in words to read raw */ + if (s->avail_in < 10) + return CAPN_NEED_MORE; + + memcpy(s->inflate_buf, s->next_in+1, 8); + s->avail_buf = 8; + + s->raw = s->next_in[9] * 8; + s->next_in += 10; + s->avail_in -= 10; + continue; + + case 0x00: + /* 0x00 is followed by a single byte indicating + * the count of consecutive zero value words + * minus 1 */ + s->zeros = (s->next_in[1] + 1) * 8; + s->next_in += 2; + s->avail_in -= 2; + continue; + + default: + hdr = s->next_in[0]; + sz = 0; + for (i = 0; i < 8; i++) { + if (hdr & (1 << i)) + sz++; + } + if (s->avail_in < 1U + sz) + return CAPN_NEED_MORE; + + s->next_in += 1; + + wr = s->inflate_buf; + for (i = 0; i < 8; i++) { + if (hdr & (1 << i)) { + *wr++ = *s->next_in++; + } else { + *wr++ = 0; + } + } + + s->avail_buf = 8; + s->avail_in -= 1 + sz; + continue; + } + } + + return 0; +} + diff --git a/src/subprojects/c-capnproto/lib/capn.c b/src/subprojects/c-capnproto/lib/capn.c new file mode 100644 index 00000000..04cf8b53 --- /dev/null +++ b/src/subprojects/c-capnproto/lib/capn.c @@ -0,0 +1,1147 @@ +/* vim: set sw=8 ts=8 sts=8 noet: */ +/* capn.c + * + * Copyright (C) 2013 James McKaskill + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +#include "capnp_c.h" + +#include +#include +#ifndef _MSC_VER +#include +#endif + +#define STRUCT_PTR 0 +#define LIST_PTR 1 +#define FAR_PTR 2 +#define DOUBLE_PTR 6 + +#define VOID_LIST 0 +#define BIT_1_LIST 1 +#define BYTE_1_LIST 2 +#define BYTE_2_LIST 3 +#define BYTE_4_LIST 4 +#define BYTE_8_LIST 5 +#define PTR_LIST 6 +#define COMPOSITE_LIST 7 + +#define U64(val) ((uint64_t) (val)) +#define I64(val) ((int64_t) (val)) +#define U32(val) ((uint32_t) (val)) +#define I32(val) ((int32_t) (val)) +#define U16(val) ((uint16_t) (val)) +#define I16(val) ((int16_t) (val)) + +#ifndef min +static int min(int a, int b) { return (a < b) ? a : b; } +#endif + +#ifdef BYTE_ORDER +#define CAPN_LITTLE (BYTE_ORDER == LITTLE_ENDIAN) +#elif defined(__BYTE_ORDER) +#define CAPN_LITTLE (__BYTE_ORDER == __LITTLE_ENDIAN) +#else +#define CAPN_LITTLE 0 +#endif + +struct capn_tree *capn_tree_insert(struct capn_tree *root, struct capn_tree *n) { + n->red = 1; + n->link[0] = n->link[1] = NULL; + + for (;;) { + /* parent, uncle, grandparent, great grandparent link */ + struct capn_tree *p, *u, *g, **gglink; + int dir; + + /* Case 1: N is root */ + p = n->parent; + if (!p) { + n->red = 0; + root = n; + break; + } + + /* Case 2: p is black */ + if (!p->red) { + break; + } + + g = p->parent; + dir = (p == g->link[1]); + + /* Case 3: P and U are red, switch g to red, but must + * loop as G could be root or have a red parent + * g to G + * / \ / \ + * P U p u + * / / + * N N + */ + u = g->link[!dir]; + if (u != NULL && u->red) { + p->red = 0; + u->red = 0; + g->red = 1; + n = g; + continue; + } + + if (!g->parent) { + gglink = &root; + } else if (g->parent->link[1] == g) { + gglink = &g->parent->link[1]; + } else { + gglink = &g->parent->link[0]; + } + + if (dir != (n == p->link[1])) { + /* Case 4: rotate on P, then on g + * here dir is / + * g to g to n + * / \ / \ / \ + * P u N u P G + * / \ / \ /| / \ + * 1 N P 3 1 2 3 u + * / \ / \ + * 2 3 1 2 + */ + struct capn_tree *two = n->link[dir]; + struct capn_tree *three = n->link[!dir]; + p->link[!dir] = two; + g->link[dir] = three; + n->link[dir] = p; + n->link[!dir] = g; + *gglink = n; + n->parent = g->parent; + p->parent = n; + g->parent = n; + if (two) + two->parent = p; + if (three) + three->parent = g; + n->red = 0; + g->red = 1; + } else { + /* Case 5: rotate on g + * here dir is / + * g to p + * / \ / \ + * P u N G + * / \ /| / \ + * N 3 1 2 3 u + * / \ + * 1 2 + */ + struct capn_tree *three = p->link[!dir]; + g->link[dir] = three; + p->link[!dir] = g; + *gglink = p; + p->parent = g->parent; + g->parent = p; + if (three) + three->parent = g; + g->red = 1; + p->red = 0; + } + + break; + } + + return root; +} + +void capn_append_segment(struct capn *c, struct capn_segment *s) { + s->id = c->segnum++; + s->capn = c; + s->next = NULL; + + if (c->lastseg) { + c->lastseg->next = s; + c->lastseg->hdr.link[1] = &s->hdr; + s->hdr.parent = &c->lastseg->hdr; + } else { + c->seglist = s; + s->hdr.parent = NULL; + } + + c->lastseg = s; + c->segtree = capn_tree_insert(c->segtree, &s->hdr); +} + +static char *new_data(struct capn *c, int sz, struct capn_segment **ps) { + struct capn_segment *s; + + /* find a segment with sufficient data */ + for (s = c->seglist; s != NULL; s = s->next) { + if (s->len + sz <= s->cap) { + goto end; + } + } + + s = c->create ? c->create(c->user, c->segnum, sz) : NULL; + if (!s) { + *ps = NULL; + return NULL; + } + + capn_append_segment(c, s); +end: + *ps = s; + s->len += sz; + return s->data + s->len - sz; +} + +static struct capn_segment *lookup_segment(struct capn* c, struct capn_segment *s, uint32_t id) { + struct capn_tree **x; + struct capn_segment *y = NULL; + + if (s && s->id == id) + return s; + if (!c) + return NULL; + + if (id < c->segnum) { + x = &c->segtree; + while (*x) { + y = (struct capn_segment*) *x; + if (id == y->id) { + return y; + } else if (id < y->id) { + x = &y->hdr.link[0]; + } else { + x = &y->hdr.link[1]; + } + } + } else { + /* Otherwise `x` may be uninitialized */ + return NULL; + } + + s = c->lookup ? c->lookup(c->user, id) : NULL; + if (!s) + return NULL; + + if (id < c->segnum) { + s->id = id; + s->capn = c; + s->next = c->seglist; + c->seglist = s; + s->hdr.parent = &y->hdr; + *x = &s->hdr; + c->segtree = capn_tree_insert(c->segtree, &s->hdr); + } else { + c->segnum = id; + capn_append_segment(c, s); + } + + return s; +} + +static uint64_t lookup_double(struct capn_segment **s, char **d, uint64_t val) { + uint64_t far, tag; + size_t off = (U32(val) >> 3) * 8; + char *p; + + if ((*s = lookup_segment((*s)->capn, *s, U32(val >> 32))) == NULL) { + return 0; + } + + p = (*s)->data + off; + if (off + 16 > (*s)->len) { + return 0; + } + + far = capn_flip64(*(uint64_t*) p); + tag = capn_flip64(*(uint64_t*) (p+8)); + + /* the far tag should not be another double, and the tag + * should be struct/list and have no offset */ + if ((far&7) != FAR_PTR || U32(tag) > LIST_PTR) { + return 0; + } + + if ((*s = lookup_segment((*s)->capn, *s, U32(far >> 32))) == NULL) { + return 0; + } + + /* -8 because far pointers reference from the start of + * the segment, but offsets reference the end of the + * pointer data. Here *d points to where an equivalent + * ptr would be. + */ + *d = (*s)->data - 8; + return U64(U32(far) >> 3 << 2) | tag; +} + +static uint64_t lookup_far(struct capn_segment **s, char **d, uint64_t val) { + size_t off = (U32(val) >> 3) * 8; + + if ((*s = lookup_segment((*s)->capn, *s, U32(val >> 32))) == NULL) { + return 0; + } + + if (off + 8 > (*s)->len) { + return 0; + } + + *d = (*s)->data + off; + return capn_flip64(*(uint64_t*)*d); +} + +static char *struct_ptr(struct capn_segment *s, char *d, int minsz) { + uint64_t val = capn_flip64(*(uint64_t*)d); + uint16_t datasz; + + switch (val&7) { + case FAR_PTR: + val = lookup_far(&s, &d, val); + break; + case DOUBLE_PTR: + val = lookup_double(&s, &d, val); + break; + } + + datasz = U16(val >> 32); + d += (I32(U32(val)) << 1) + 8; + + if (val != 0 && (val&3) != STRUCT_PTR && datasz >= minsz && s->data <= d && d < s->data + s->len) { + return d; + } + + return NULL; +} + +static capn_ptr read_ptr(struct capn_segment *s, char *d) { + capn_ptr ret = {CAPN_NULL}; + uint64_t val; + char *e = 0; + + val = capn_flip64(*(uint64_t*) d); + + switch (val&7) { + case FAR_PTR: + val = lookup_far(&s, &d, val); + ret.has_ptr_tag = (U32(val) >> 2) == 0; + break; + case DOUBLE_PTR: + val = lookup_double(&s, &d, val); + break; + } + + d += (I32(U32(val)) >> 2) * 8 + 8; + + if (d < s->data) { + goto err; + } + + switch (val & 3) { + case STRUCT_PTR: + ret.type = val ? CAPN_STRUCT : CAPN_NULL; + goto struct_common; + + struct_common: + ret.datasz = U32(U16(val >> 32)) * 8; + ret.ptrs = U32(U16(val >> 48)); + e = d + ret.datasz + 8 * ret.ptrs; + break; + + case LIST_PTR: + ret.type = CAPN_LIST; + ret.len = val >> 35; + + switch ((val >> 32) & 7) { + case VOID_LIST: + e = d; + break; + case BIT_1_LIST: + ret.type = CAPN_BIT_LIST; + ret.datasz = (ret.len+7)/8; + e = d + ret.datasz; + break; + case BYTE_1_LIST: + ret.datasz = 1; + e = d + ret.len; + break; + case BYTE_2_LIST: + ret.datasz = 2; + e = d + ret.len * 2; + break; + case BYTE_4_LIST: + ret.datasz = 4; + e = d + ret.len * 4; + break; + case BYTE_8_LIST: + ret.datasz = 8; + e = d + ret.len * 8; + break; + case PTR_LIST: + ret.type = CAPN_PTR_LIST; + e = d + ret.len * 8; + break; + case COMPOSITE_LIST: + if ((size_t)((d+8) - s->data) > s->len) { + goto err; + } + + val = capn_flip64(*(uint64_t*) d); + + d += 8; + e = d + ret.len * 8; + + ret.datasz = U32(U16(val >> 32)) * 8; + ret.ptrs = U32(U16(val >> 48)); + ret.len = U32(val) >> 2; + ret.is_composite_list = 1; + + if ((ret.datasz + 8*ret.ptrs) * ret.len != e - d) { + goto err; + } + break; + } + break; + + default: + goto err; + } + + if ((size_t)(e - s->data) > s->len) + goto err; + + ret.data = d; + ret.seg = s; + return ret; +err: + memset(&ret, 0, sizeof(ret)); + return ret; +} + +void capn_resolve(capn_ptr *p) { + if (p->type == CAPN_FAR_POINTER) { + *p = read_ptr(p->seg, p->data); + } +} + +/* TODO: should this handle CAPN_BIT_LIST? */ +capn_ptr capn_getp(capn_ptr p, int off, int resolve) { + capn_ptr ret = {CAPN_FAR_POINTER}; + ret.seg = p.seg; + + capn_resolve(&p); + + switch (p.type) { + case CAPN_LIST: + /* Return an inner pointer */ + if (off < p.len) { + capn_ptr ret = {CAPN_STRUCT}; + ret.is_list_member = 1; + ret.data = p.data + off * (p.datasz + 8*p.ptrs); + ret.seg = p.seg; + ret.datasz = p.datasz; + ret.ptrs = p.ptrs; + return ret; + } else { + goto err; + } + + case CAPN_STRUCT: + if (off >= p.ptrs) { + goto err; + } + ret.data = p.data + p.datasz + 8*off; + break; + + case CAPN_PTR_LIST: + if (off >= p.len) { + goto err; + } + ret.data = p.data + 8*off; + break; + + default: + goto err; + } + + if (resolve) { + ret = read_ptr(ret.seg, ret.data); + } + + return ret; + +err: + memset(&p, 0, sizeof(p)); + return p; +} + +static void write_ptr_tag(char *d, capn_ptr p, int off) { + /* + lsb struct pointer msb + +-+-----------------------------+---------------+---------------+ + |A| B | C | D | + +-+-----------------------------+---------------+---------------+ + + A (2 bits) = 0, to indicate that this is a struct pointer. + B (30 bits) = Offset, in words, from the end of the pointer to the + start of the struct's data section. Signed. + C (16 bits) = Size of the struct's data section, in words. + D (16 bits) = Size of the struct's pointer section, in words. + + For B we can't simply left-shift by 2 bits since C11 6.5.7.4 + https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf + says we can get undefined behavior when the left-shift exceeds + the signed integer (ie. values run into the sign bit). The + ASAN detector will rightly complain. So we do two's complement + manually, and check bounds, to stay within unsigned arithmetic. + */ + const int off_words = off / 8; + uint64_t val; + if (off_words < 0) { + if (off_words < -(2147483647 >> 2) - 1) { + goto err; + } + uint32_t twos = 1 + ~(U32(-off_words) << 2); + val = U64(twos); + } else { + val = U64(U32(off_words) << 2); + } + + switch (p.type) { + case CAPN_STRUCT: + val |= STRUCT_PTR | (U64(p.datasz/8) << 32) | (U64(p.ptrs) << 48); + break; + + case CAPN_LIST: + if (p.is_composite_list) { + val |= LIST_PTR | (U64(COMPOSITE_LIST) << 32) | (U64(p.len * (p.datasz/8 + p.ptrs)) << 35); + } else { + val |= LIST_PTR | (U64(p.len) << 35); + + switch (p.datasz) { + case 8: + val |= (U64(BYTE_8_LIST) << 32); + break; + case 4: + val |= (U64(BYTE_4_LIST) << 32); + break; + case 2: + val |= (U64(BYTE_2_LIST) << 32); + break; + case 1: + val |= (U64(BYTE_1_LIST) << 32); + break; + case 0: + val |= (U64(VOID_LIST) << 32); + break; + } + } + break; + + case CAPN_BIT_LIST: + val |= LIST_PTR | (U64(BIT_1_LIST) << 32) | (U64(p.len) << 35); + break; + + case CAPN_PTR_LIST: + val |= LIST_PTR | (U64(PTR_LIST) << 32) | (U64(p.len) << 35); + break; + + default: + val = 0; + break; + } + + *(uint64_t*) d = capn_flip64(val); + +err: + memset(&p, 0, sizeof(p)); +} + +static void write_far_ptr(char *d, struct capn_segment *s, char *tgt) { + *(uint64_t*) d = capn_flip64(FAR_PTR | U64(tgt - s->data) | (U64(s->id) << 32)); +} + +static void write_double_far(char *d, struct capn_segment *s, char *tgt) { + *(uint64_t*) d = capn_flip64(DOUBLE_PTR | U64(tgt - s->data) | (U64(s->id) << 32)); +} + +#define NEED_TO_COPY 1 + +static int write_ptr(struct capn_segment *s, char *d, capn_ptr p) { + /* note p.seg can be NULL if its a ptr to static data */ + char *pdata = p.data - 8*p.is_composite_list; + + if (p.type == CAPN_NULL || (p.type == CAPN_STRUCT && p.datasz == 0 && p.ptrs == 0)) { + write_ptr_tag(d, p, 0); + return 0; + + } else if (!p.seg || p.seg->capn != s->capn || p.is_list_member) { + return NEED_TO_COPY; + + } else if (p.seg == s) { + write_ptr_tag(d, p, pdata - d - 8); + return 0; + + } else if (p.has_ptr_tag) { + /* By lucky chance, the data has a tag in front + * of it. This happens when new_object had to move + * the data to a new segment. */ + write_far_ptr(d, p.seg, pdata-8); + return 0; + + } else if (p.seg->len + 8 <= p.seg->cap) { + /* The target segment has enough room for tag */ + char *t = p.seg->data + p.seg->len; + write_ptr_tag(t, p, pdata - t - 8); + write_far_ptr(d, p.seg, t); + p.seg->len += 8; + return 0; + + } else { + /* have to allocate room for a double far + * pointer */ + char *t; + + if (s->len + 16 <= s->cap) { + /* Try and allocate in the src segment + * first. This should improve lookup on + * read. */ + t = s->data + s->len; + s->len += 16; + } else { + t = new_data(s->capn, 16, &s); + if (!t) return -1; + } + + write_far_ptr(t, p.seg, pdata); + write_ptr_tag(t+8, p, 0); + write_double_far(d, s, t); + return 0; + } +} + +struct copy { + struct capn_tree hdr; + struct capn_ptr to, from; + char *fbegin, *fend; +}; + +static capn_ptr new_clone(struct capn_segment *s, capn_ptr p) { + switch (p.type) { + case CAPN_STRUCT: + return capn_new_struct(s, p.datasz, p.ptrs); + case CAPN_PTR_LIST: + return capn_new_ptr_list(s, p.len); + case CAPN_BIT_LIST: + return capn_new_list1(s, p.len).p; + case CAPN_LIST: + return capn_new_list(s, p.len, p.datasz, p.ptrs); + default: + return p; + } +} + +static int is_ptr_equal(const struct capn_ptr *a, const struct capn_ptr *b) { + return a->data == b->data + && a->type == b->type + && a->len == b->len + && a->datasz == b->datasz + && a->ptrs == b->ptrs; +} + +static int data_size(struct capn_ptr p) { + switch (p.type) { + case CAPN_BIT_LIST: + return p.datasz; + case CAPN_PTR_LIST: + return p.len*8; + case CAPN_STRUCT: + return p.datasz + 8*p.ptrs; + case CAPN_LIST: + return p.len * (p.datasz + 8*p.ptrs) + 8*p.is_composite_list; + default: + return 0; + } +} + +static int copy_ptr(struct capn_segment *seg, char *data, struct capn_ptr *t, struct capn_ptr *f, int *dep) { + struct capn *c = seg->capn; + struct copy *cp = NULL; + struct capn_tree **xcp; + char *fbegin = f->data - 8*f->is_composite_list; + char *fend = fbegin + data_size(*f); + int zero_sized = (fend == fbegin); + + /* We always copy list members as it would otherwise be an + * overlapped pointer (the data is owned by the enclosing list). + * We do not bother with the overlapped lookup for zero sized + * structures/lists as they never overlap. Nor do we add them to + * the copy list as there is no data to be shared by multiple + * pointers. + */ + + xcp = &c->copy; + while (*xcp && !zero_sized) { + cp = (struct copy*) *xcp; + if (fend <= cp->fbegin) { + xcp = &cp->hdr.link[0]; + } else if (cp->fend <= fbegin) { + xcp = &cp->hdr.link[1]; + } else if (is_ptr_equal(f, &cp->from)) { + /* we already have a copy so just point to that */ + return write_ptr(seg, data, cp->to); + } else { + /* pointer to overlapped data */ + return -1; + } + } + + /* no copy found - have to create a new copy */ + *t = new_clone(seg, *f); + + if (write_ptr(seg, data, *t)) + return -1; + + /* add the copy to the copy tree so we can look for overlapping + * source pointers and handle recursive structures */ + if (!zero_sized) { + struct copy *n; + struct capn_segment *cs = c->copylist; + + /* need to allocate a struct copy */ + if (!cs || cs->len + (int)sizeof(*n) > cs->cap) { + cs = c->create_local ? c->create_local(c->user, sizeof(*n)) : NULL; + if (!cs) { + /* can't allocate a copy structure */ + return -1; + } + cs->next = c->copylist; + c->copylist = cs; + } + + n = (struct copy*) (cs->data + cs->len); + cs->len += sizeof(*n); + + n->from = *f; + n->to = *t; + n->fbegin = fbegin; + n->fend = fend; + + *xcp = &n->hdr; + n->hdr.parent = &cp->hdr; + + c->copy = capn_tree_insert(c->copy, &n->hdr); + } + + /* minimize the number of types the main copy routine has to + * deal with to just CAPN_LIST and CAPN_PTR_LIST. ptr list only + * needs t->type, t->len, t->data, t->seg, f->data, f->seg to + * be valid */ + switch (t->type) { + case CAPN_STRUCT: + if (t->datasz) { + memcpy(t->data, f->data, t->datasz); + t->data += t->datasz; + f->data += t->datasz; + } + if (t->ptrs) { + t->type = CAPN_PTR_LIST; + t->len = t->ptrs; + (*dep)++; + } + return 0; + + case CAPN_BIT_LIST: + memcpy(t->data, f->data, t->datasz); + return 0; + + case CAPN_LIST: + if (!t->len) { + /* empty list - nothing to copy */ + } else if (t->ptrs && t->datasz) { + (*dep)++; + } else if (t->datasz) { + memcpy(t->data, f->data, t->len * t->datasz); + } else if (t->ptrs) { + t->type = CAPN_PTR_LIST; + t->len *= t->ptrs; + (*dep)++; + } + return 0; + + case CAPN_PTR_LIST: + if (t->len) { + (*dep)++; + } + return 0; + + default: + return -1; + } +} + +static void copy_list_member(capn_ptr* t, capn_ptr *f, int *dep) { + /* copy struct data */ + int sz = min(t->datasz, f->datasz); + memcpy(t->data, f->data, sz); + memset(t->data + sz, 0, t->datasz - sz); + t->data += t->datasz; + f->data += f->datasz; + + /* reset excess pointers */ + sz = min(t->ptrs, f->ptrs); + memset(t->data + sz, 0, 8*(t->ptrs - sz)); + + /* create a pointer list for the main loop to copy */ + if (t->ptrs) { + t->type = CAPN_PTR_LIST; + t->len = t->ptrs; + (*dep)++; + } +} + +#define MAX_COPY_DEPTH 32 + +/* TODO: handle CAPN_BIT_LIST and setting from an inner bit list member */ +int capn_setp(capn_ptr p, int off, capn_ptr tgt) { + struct capn_ptr to[MAX_COPY_DEPTH], from[MAX_COPY_DEPTH]; + char *data; + int err, dep = 0; + + capn_resolve(&p); + + if (tgt.type == CAPN_FAR_POINTER && tgt.seg->capn == p.seg->capn) { + uint64_t val = capn_flip64(*(uint64_t*) tgt.data); + if ((val & 3) == FAR_PTR) { + *(uint64_t*) p.data = *(uint64_t*) tgt.data; + return 0; + } + } + + capn_resolve(&tgt); + + switch (p.type) { + case CAPN_LIST: + if (off >= p.len || tgt.type != CAPN_STRUCT) + return -1; + + to[0] = p; + to[0].data += off * (p.datasz + 8*p.ptrs); + from[0] = tgt; + copy_list_member(to, from, &dep); + break; + + case CAPN_PTR_LIST: + if (off >= p.len) + return -1; + data = p.data + 8*off; + goto copy_ptr; + + case CAPN_STRUCT: + if (off >= p.ptrs) + return -1; + data = p.data + p.datasz + 8*off; + goto copy_ptr; + + copy_ptr: + err = write_ptr(p.seg, data, tgt); + if (err != NEED_TO_COPY) + return err; + + /* Depth first copy the source whilst using a pointer stack to + * maintain the ptr to set and size left to copy at each level. + * We also maintain a rbtree (capn->copy) of the copies indexed + * by the source data. This way we can detect overlapped + * pointers in the source (and bail) and recursive structures + * (and point to the previous copy). + */ + + from[0] = tgt; + if (copy_ptr(p.seg, data, to, from, &dep)) + return -1; + break; + + default: + return -1; + } + + while (dep) { + struct capn_ptr *tc = &to[dep-1], *tn = &to[dep]; + struct capn_ptr *fc = &from[dep-1], *fn = &from[dep]; + + if (dep+1 == MAX_COPY_DEPTH) { + return -1; + } + + if (!tc->len) { + dep--; + continue; + } + + if (tc->type == CAPN_LIST) { + *fn = capn_getp(*fc, 0, 1); + *tn = capn_getp(*tc, 0, 1); + + copy_list_member(tn, fn, &dep); + + fc->data += fc->datasz + 8*fc->ptrs; + tc->data += tc->datasz + 8*tc->ptrs; + tc->len--; + + } else { /* CAPN_PTR_LIST */ + *fn = read_ptr(fc->seg, fc->data); + + if (fn->type && copy_ptr(tc->seg, tc->data, tn, fn, &dep)) + return -1; + + fc->data += 8; + tc->data += 8; + tc->len--; + } + } + + return 0; +} + +/* TODO: handle CAPN_LIST, CAPN_PTR_LIST for bit lists */ + +int capn_get1(capn_list1 l, int off) { + return l.p.type == CAPN_BIT_LIST + && off < l.p.len + && (l.p.data[off/8] & (1 << (off%8))) != 0; +} + +int capn_set1(capn_list1 l, int off, int val) { + if (l.p.type != CAPN_BIT_LIST || off >= l.p.len) + return -1; + if (val) { + l.p.data[off/8] |= 1 << (off%8); + } else { + l.p.data[off/8] &= ~(1 << (off%8)); + } + return 0; +} + +int capn_getv1(capn_list1 l, int off, uint8_t *data, int sz) { + /* Note we only support aligned reads */ + int bsz; + capn_ptr p; + capn_resolve(&l.p); + p = l.p; + if (p.type != CAPN_BIT_LIST || (off & 7) != 0) + return -1; + + bsz = (sz + 7) / 8; + off /= 8; + + if (off + sz > p.datasz) { + memcpy(data, p.data + off, p.datasz - off); + return p.len - off*8; + } else { + memcpy(data, p.data + off, bsz); + return sz; + } +} + +int capn_setv1(capn_list1 l, int off, const uint8_t *data, int sz) { + /* Note we only support aligned writes */ + int bsz; + capn_ptr p = l.p; + if (p.type != CAPN_BIT_LIST || (off & 7) != 0) + return -1; + + bsz = (sz + 7) / 8; + off /= 8; + + if (off + sz > p.datasz) { + memcpy(p.data + off, data, p.datasz - off); + return p.len - off*8; + } else { + memcpy(p.data + off, data, bsz); + return sz; + } +} + +/* pull out whether we add a tag or not as a define so the unit test can + * test double far pointers by not creating tags */ +#ifndef ADD_TAG +#define ADD_TAG 1 +#endif + +static void new_object(capn_ptr *p, int bytes) { + struct capn_segment *s = p->seg; + + if (!s) { + memset(p, 0, sizeof(*p)); + return; + } + + /* pointer needs to be initialised to get a valid offset on write */ + if (!bytes) { + p->data = s->data + s->len; + return; + } + + /* all allocations are 8 byte aligned */ + bytes = (bytes + 7) & ~7; + + if (s->len + bytes <= s->cap) { + p->data = s->data + s->len; + s->len += bytes; + return; + } + + /* add a tag whenever we switch segments so that write_ptr can + * use it */ + p->data = new_data(s->capn, bytes + ADD_TAG*8, &p->seg); + if (!p->data) { + memset(p, 0, sizeof(*p)); + return; + } + + if (ADD_TAG) { + write_ptr_tag(p->data, *p, 0); + p->data += 8; + p->has_ptr_tag = 1; + } +} + +capn_ptr capn_root(struct capn *c) { + capn_ptr r = {CAPN_PTR_LIST}; + r.seg = lookup_segment(c, NULL, 0); + r.data = r.seg ? r.seg->data : new_data(c, 8, &r.seg); + r.len = 1; + + if (!r.seg || r.seg->cap < 8) { + memset(&r, 0, sizeof(r)); + } else if (r.seg->len < 8) { + r.seg->len = 8; + } + + return r; +} + +capn_ptr capn_new_struct(struct capn_segment *seg, int datasz, int ptrs) { + capn_ptr p = {CAPN_STRUCT}; + p.seg = seg; + p.datasz = (datasz + 7) & ~7; + p.ptrs = ptrs; + new_object(&p, p.datasz + 8*p.ptrs); + return p; +} + +capn_ptr capn_new_list(struct capn_segment *seg, int sz, int datasz, int ptrs) { + capn_ptr p = {CAPN_LIST}; + p.seg = seg; + p.len = sz; + + if (ptrs || datasz > 8) { + p.is_composite_list = 1; + p.datasz = (datasz + 7) & ~7; + p.ptrs = ptrs; + new_object(&p, p.len * (p.datasz + 8*p.ptrs) + 8); + if (p.data) { + uint64_t hdr = STRUCT_PTR | (U64(p.len) << 2) | (U64(p.datasz/8) << 32) | (U64(ptrs) << 48); + *(uint64_t*) p.data = capn_flip64(hdr); + p.data += 8; + } + } else if (datasz > 4) { + p.datasz = 8; + new_object(&p, p.len * 8); + } else if (datasz > 2) { + p.datasz = 4; + new_object(&p, p.len * 4); + } else { + p.datasz = datasz; + new_object(&p, p.len * datasz); + } + + return p; +} + +capn_list1 capn_new_list1(struct capn_segment *seg, int sz) { + capn_list1 l = {{CAPN_BIT_LIST}}; + l.p.seg = seg; + l.p.datasz = (sz+7)/8; + l.p.len = sz; + new_object(&l.p, l.p.datasz); + return l; +} + +capn_ptr capn_new_ptr_list(struct capn_segment *seg, int sz) { + capn_ptr p = {CAPN_PTR_LIST}; + p.seg = seg; + p.len = sz; + p.ptrs = 0; + p.datasz = 0; + new_object(&p, sz*8); + return p; +} + +capn_ptr capn_new_string(struct capn_segment *seg, const char *str, ssize_t sz) { + capn_ptr p = {CAPN_LIST}; + p.seg = seg; + p.len = ((sz >= 0) ? (size_t)sz : strlen(str)) + 1; + p.datasz = 1; + new_object(&p, p.len); + if (p.data) { + memcpy(p.data, str, p.len - 1); + p.data[p.len - 1] = '\0'; + } + return p; +} + +capn_text capn_get_text(capn_ptr p, int off, capn_text def) { + capn_ptr m = capn_getp(p, off, 1); + capn_text ret = def; + if (m.type == CAPN_LIST && m.datasz == 1 && m.len && m.data[m.len - 1] == 0) { + ret.seg = m.seg; + ret.str = m.data; + ret.len = m.len - 1; + } + return ret; +} + +int capn_set_text(capn_ptr p, int off, capn_text tgt) { + capn_ptr m = {CAPN_NULL}; + if (tgt.seg) { + m.type = CAPN_LIST; + m.seg = tgt.seg; + m.data = (char*)tgt.str; + m.len = tgt.len + 1; + m.datasz = 1; + } else if (tgt.str) { + m = capn_new_string(p.seg, tgt.str, tgt.len); + } + return capn_setp(p, off, m); +} + +capn_data capn_get_data(capn_ptr p, int off) { + capn_data ret; + ret.p = capn_getp(p, off, 1); + if (ret.p.type != CAPN_LIST || ret.p.datasz != 1) { + memset(&ret, 0, sizeof(ret)); + } + return ret; +} + +#define SZ 8 +#include "capn-list.inc" +#undef SZ + +#define SZ 16 +#include "capn-list.inc" +#undef SZ + +#define SZ 32 +#include "capn-list.inc" +#undef SZ + +#define SZ 64 +#include "capn-list.inc" +#undef SZ diff --git a/src/subprojects/c-capnproto/lib/capnp_c.h b/src/subprojects/c-capnproto/lib/capnp_c.h new file mode 100644 index 00000000..2b4b22a9 --- /dev/null +++ b/src/subprojects/c-capnproto/lib/capnp_c.h @@ -0,0 +1,461 @@ +/* vim: set sw=8 ts=8 sts=8 noet: */ +/* capnp_c.h + * + * Copyright (C) 2013 James McKaskill + * Copyright (C) 2014 Steve Dee + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#ifndef CAPNP_C_H +#define CAPNP_C_H + +#include +#include +#ifndef _MSC_VER +#include +#endif + +#if defined(unix) && !defined(__APPLE__) && !defined(__FreeBSD__) +#include +#elif defined(__FreeBSD__) +#include +#endif + +/* ssize_t is a POSIX type, not an ISO C one... + * Windows seems to only have SSIZE_T in BaseTsd.h + */ +#ifdef _MSC_VER +#include +typedef SSIZE_T ssize_t; +#else +#include +#endif + +/* Cross-platform macro ALIGNED_(x) aligns a struct or a field + * by `x` bytes. When applied to a struct, it applies to the + * aggregate but not the individual members of the struct. So + * apply ALIGNED_(x) to individual members that need to be + * aligned. + * Confer: https://www.ibm.com/docs/en/i/7.1?topic=attributes-aligned-type-attribute + */ +#ifdef _MSC_VER +#define ALIGNED_(x) __declspec(align(x)) +#endif +#ifdef __GNUC__ +#define ALIGNED_(x) __attribute__ ((aligned(x))) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__cplusplus) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#define CAPN_INLINE static inline +#else +#define CAPN_INLINE static +#endif + +#define CAPN_VERSION 1 + +/* struct capn is a common structure shared between segments in the same + * session/context so that far pointers between segments will be created. + * + * lookup is used to lookup segments by id when derefencing a far pointer + * + * create is used to create or lookup an alternate segment that has at least + * sz available (ie returned seg->len + sz <= seg->cap) + * + * create_local is used to create a segment for the copy tree and should be + * allocated in the local memory space. + * + * Allocated segments must be zero initialized. + * + * create and lookup can be NULL if you don't need multiple segments and don't + * want to support copying + * + * seglist and copylist are linked lists which can be used to free up segments + * on cleanup, but should not be modified by the user. + * + * lookup, create, create_local, and user can be set by the user. Other values + * should be zero initialized. + */ +struct capn { + /* user settable */ + struct capn_segment *(*lookup)(void* /*user*/, uint32_t /*id */); + struct capn_segment *(*create)(void* /*user*/, uint32_t /*id */, int /*sz*/); + struct capn_segment *(*create_local)(void* /*user*/, int /*sz*/); + void *user; + /* zero initialized, user should not modify */ + uint32_t segnum; + struct capn_tree *copy; + struct capn_tree *segtree; + struct capn_segment *seglist, *lastseg; + struct capn_segment *copylist; +}; + +/* struct capn_tree is a rb tree header used internally for the segment id + * lookup and copy tree */ +struct capn_tree { + struct capn_tree *parent, *link[2]; + unsigned int red : 1; +}; + +struct capn_tree *capn_tree_insert(struct capn_tree *root, struct capn_tree *n); + +/* struct capn_segment contains the information about a single segment. + * + * capn points to a struct capn that is shared between segments in the + * same session + * + * id specifies the segment id, used for far pointers + * + * data specifies the segment data. This should not move after creation. + * + * len specifies the current segment length. This is 0 for a blank + * segment. + * + * cap specifies the segment capacity. + * + * When creating new structures len will be incremented until it reaches cap, + * at which point a new segment will be requested via capn->create. The + * create callback can either create a new segment or expand an existing + * one by incrementing cap and returning the expanded segment. + * + * data, len, and cap must all be 8 byte aligned, hence the ALIGNED_(8) macro + * on the struct fields. + * + * data, len, cap, and user should all be set by the user. Other values + * should be zero initialized. + */ + +struct ALIGNED_(8) capn_segment { + struct capn_tree hdr; + struct capn_segment *next; + struct capn *capn; + uint32_t id; + /* user settable */ + ALIGNED_(8) char *data; + ALIGNED_(8) size_t len; + ALIGNED_(8) size_t cap; + ALIGNED_(8) void *user; +}; + +enum CAPN_TYPE { + CAPN_NULL = 0, + CAPN_STRUCT = 1, + CAPN_LIST = 2, + CAPN_PTR_LIST = 3, + CAPN_BIT_LIST = 4, + CAPN_FAR_POINTER = 5, +}; + +struct capn_ptr { + unsigned int type : 4; + unsigned int has_ptr_tag : 1; + unsigned int is_list_member : 1; + unsigned int is_composite_list : 1; + unsigned int datasz : 19; + unsigned int ptrs : 16; + int len; + char *data; + struct capn_segment *seg; +}; + +struct capn_text { + int len; + const char *str; + struct capn_segment *seg; +}; + +typedef struct capn_ptr capn_ptr; +typedef struct capn_text capn_text; +typedef struct {capn_ptr p;} capn_data; +typedef struct {capn_ptr p;} capn_list1; +typedef struct {capn_ptr p;} capn_list8; +typedef struct {capn_ptr p;} capn_list16; +typedef struct {capn_ptr p;} capn_list32; +typedef struct {capn_ptr p;} capn_list64; + +struct capn_msg { + struct capn_segment *seg; + uint64_t iface; + uint16_t method; + capn_ptr args; +}; + +/* capn_append_segment appends a segment to a session */ +void capn_append_segment(struct capn*, struct capn_segment*); + +capn_ptr capn_root(struct capn *c); +void capn_resolve(capn_ptr *p); + +#define capn_len(list) ((list).p.type == CAPN_FAR_POINTER ? (capn_resolve(&(list).p), (list).p.len) : (list).p.len) + +/* capn_getp|setp functions get/set ptrs in list/structs + * off is the list index or pointer index in a struct + * capn_setp will copy the data, create far pointers, etc if the target + * is in a different segment/context. + * Both of these will use/return inner pointers for composite lists. + */ +capn_ptr capn_getp(capn_ptr p, int off, int resolve); +int capn_setp(capn_ptr p, int off, capn_ptr tgt); + +capn_text capn_get_text(capn_ptr p, int off, capn_text def); +capn_data capn_get_data(capn_ptr p, int off); +int capn_set_text(capn_ptr p, int off, capn_text tgt); +/* there is no set_data -- use capn_new_list8 + capn_setv8 instead + * and set data.p = list.p */ + +/* capn_get* functions get data from a list + * The length of the list is given by p->size + * off specifies how far into the list to start + * sz indicates the number of elements to get + * The function returns the number of elements read or -1 on an error. + * off must be byte aligned for capn_getv1 + */ +int capn_get1(capn_list1 p, int off); +uint8_t capn_get8(capn_list8 p, int off); +uint16_t capn_get16(capn_list16 p, int off); +uint32_t capn_get32(capn_list32 p, int off); +uint64_t capn_get64(capn_list64 p, int off); +int capn_getv1(capn_list1 p, int off, uint8_t *data, int sz); +int capn_getv8(capn_list8 p, int off, uint8_t *data, int sz); +int capn_getv16(capn_list16 p, int off, uint16_t *data, int sz); +int capn_getv32(capn_list32 p, int off, uint32_t *data, int sz); +int capn_getv64(capn_list64 p, int off, uint64_t *data, int sz); + +/* capn_set* functions set data in a list + * off specifies how far into the list to start + * sz indicates the number of elements to write + * The function returns the number of elemnts written or -1 on an error. + * off must be byte aligned for capn_setv1 + */ +int capn_set1(capn_list1 p, int off, int v); +int capn_set8(capn_list8 p, int off, uint8_t v); +int capn_set16(capn_list16 p, int off, uint16_t v); +int capn_set32(capn_list32 p, int off, uint32_t v); +int capn_set64(capn_list64 p, int off, uint64_t v); +int capn_setv1(capn_list1 p, int off, const uint8_t *data, int sz); +int capn_setv8(capn_list8 p, int off, const uint8_t *data, int sz); +int capn_setv16(capn_list16 p, int off, const uint16_t *data, int sz); +int capn_setv32(capn_list32 p, int off, const uint32_t *data, int sz); +int capn_setv64(capn_list64 p, int off, const uint64_t *data, int sz); + +/* capn_new_* functions create a new object + * datasz is in bytes, ptrs is # of pointers, sz is # of elements in the list + * On an error a CAPN_NULL pointer is returned + */ +capn_ptr capn_new_string(struct capn_segment *seg, const char *str, ssize_t sz); +capn_ptr capn_new_struct(struct capn_segment *seg, int datasz, int ptrs); +capn_ptr capn_new_interface(struct capn_segment *seg, int datasz, int ptrs); +capn_ptr capn_new_ptr_list(struct capn_segment *seg, int sz); +capn_ptr capn_new_list(struct capn_segment *seg, int sz, int datasz, int ptrs); +capn_list1 capn_new_list1(struct capn_segment *seg, int sz); +capn_list8 capn_new_list8(struct capn_segment *seg, int sz); +capn_list16 capn_new_list16(struct capn_segment *seg, int sz); +capn_list32 capn_new_list32(struct capn_segment *seg, int sz); +capn_list64 capn_new_list64(struct capn_segment *seg, int sz); + +/* capn_read|write* functions read/write struct values + * off is the offset into the structure in bytes + * Rarely should these be called directly, instead use the generated code. + * Data must be xored with the default value + * These are inlined + */ +CAPN_INLINE uint8_t capn_read8(capn_ptr p, int off); +CAPN_INLINE uint16_t capn_read16(capn_ptr p, int off); +CAPN_INLINE uint32_t capn_read32(capn_ptr p, int off); +CAPN_INLINE uint64_t capn_read64(capn_ptr p, int off); +CAPN_INLINE int capn_write1(capn_ptr p, int off, int val); +CAPN_INLINE int capn_write8(capn_ptr p, int off, uint8_t val); +CAPN_INLINE int capn_write16(capn_ptr p, int off, uint16_t val); +CAPN_INLINE int capn_write32(capn_ptr p, int off, uint32_t val); +CAPN_INLINE int capn_write64(capn_ptr p, int off, uint64_t val); + +/* capn_init_malloc inits the capn struct with a create function which + * allocates segments on the heap using malloc + * + * capn_init_(fp|mem) inits by reading segments in from the file/memory buffer + * in serialized form (optionally packed). It will then setup the create + * function ala capn_init_malloc so that further segments can be created. + * + * capn_free frees all the segment headers and data created by the create + * function setup by capn_init_* + */ +void capn_init_malloc(struct capn *c); +int capn_init_fp(struct capn *c, FILE *f, int packed); +int capn_init_mem(struct capn *c, const uint8_t *p, size_t sz, int packed); + +/* capn_size() calculates the amount of memory required to serialise the given + * Cap'n Proto structure in the unpacked format. It does NOT apply to packed + * serialisation, as that may (in rare cases) actually become bigger than the + * input. A buffer of this size can then be passed to capn_write_mem() without + * fear of truncation (again, only in the unpacked case). + */ +int64_t capn_size(struct capn *c); + +/* capn_write_(fp|mem) writes segments to the file/memory buffer in + * serialized form and returns the number of bytes written. + */ +/* TODO */ +/*int capn_write_fp(struct capn *c, FILE *f, int packed);*/ +int capn_write_fd(struct capn *c, ssize_t (*write_fd)(int fd, const void *p, size_t count), int fd, int packed); +int64_t capn_write_mem(struct capn *c, uint8_t *p, size_t sz, int packed); + +void capn_free(struct capn *c); +void capn_reset_copy(struct capn *c); + +/* Inline functions */ + + +CAPN_INLINE uint8_t capn_flip8(uint8_t v) { + return v; +} +CAPN_INLINE uint16_t capn_flip16(uint16_t v) { +#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + return v; +#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ + defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 + return __builtin_bswap16(v); +#else + union { uint16_t u; uint8_t v[2]; } s; + s.v[0] = (uint8_t)v; + s.v[1] = (uint8_t)(v>>8); + return s.u; +#endif +} +CAPN_INLINE uint32_t capn_flip32(uint32_t v) { +#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + return v; +#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ + defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 + return __builtin_bswap32(v); +#else + union { uint32_t u; uint8_t v[4]; } s; + s.v[0] = (uint8_t)v; + s.v[1] = (uint8_t)(v>>8); + s.v[2] = (uint8_t)(v>>16); + s.v[3] = (uint8_t)(v>>24); + return s.u; +#endif +} +CAPN_INLINE uint64_t capn_flip64(uint64_t v) { +#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) + return v; +#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \ + defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 + return __builtin_bswap64(v); +#else + union { uint64_t u; uint8_t v[8]; } s; + s.v[0] = (uint8_t)v; + s.v[1] = (uint8_t)(v>>8); + s.v[2] = (uint8_t)(v>>16); + s.v[3] = (uint8_t)(v>>24); + s.v[4] = (uint8_t)(v>>32); + s.v[5] = (uint8_t)(v>>40); + s.v[6] = (uint8_t)(v>>48); + s.v[7] = (uint8_t)(v>>56); + return s.u; +#endif +} + +CAPN_INLINE int capn_write1(capn_ptr p, int off, int val) { + if (off >= p.datasz*8) { + return -1; + } else if (val) { + uint8_t tmp = (uint8_t)(1 << (off & 7)); + ((uint8_t*) p.data)[off >> 3] |= tmp; + return 0; + } else { + uint8_t tmp = (uint8_t)(~(1 << (off & 7))); + ((uint8_t*) p.data)[off >> 3] &= tmp; + return 0; + } +} + +CAPN_INLINE uint8_t capn_read8(capn_ptr p, int off) { + return off+1 <= p.datasz ? capn_flip8(*(uint8_t*) (p.data+off)) : 0; +} +CAPN_INLINE int capn_write8(capn_ptr p, int off, uint8_t val) { + if (off+1 <= p.datasz) { + *(uint8_t*) (p.data+off) = capn_flip8(val); + return 0; + } else { + return -1; + } +} + +CAPN_INLINE uint16_t capn_read16(capn_ptr p, int off) { + return off+2 <= p.datasz ? capn_flip16(*(uint16_t*) (p.data+off)) : 0; +} +CAPN_INLINE int capn_write16(capn_ptr p, int off, uint16_t val) { + if (off+2 <= p.datasz) { + *(uint16_t*) (p.data+off) = capn_flip16(val); + return 0; + } else { + return -1; + } +} + +CAPN_INLINE uint32_t capn_read32(capn_ptr p, int off) { + return off+4 <= p.datasz ? capn_flip32(*(uint32_t*) (p.data+off)) : 0; +} +CAPN_INLINE int capn_write32(capn_ptr p, int off, uint32_t val) { + if (off+4 <= p.datasz) { + *(uint32_t*) (p.data+off) = capn_flip32(val); + return 0; + } else { + return -1; + } +} + +CAPN_INLINE uint64_t capn_read64(capn_ptr p, int off) { + return off+8 <= p.datasz ? capn_flip64(*(uint64_t*) (p.data+off)) : 0; +} +CAPN_INLINE int capn_write64(capn_ptr p, int off, uint64_t val) { + if (off+8 <= p.datasz) { + *(uint64_t*) (p.data+off) = capn_flip64(val); + return 0; + } else { + return -1; + } +} + +union capn_conv_f32 { + uint32_t u; + float f; +}; + +union capn_conv_f64 { + uint64_t u; + double f; +}; + +CAPN_INLINE float capn_to_f32(uint32_t v) { + union capn_conv_f32 u; + u.u = v; + return u.f; +} +CAPN_INLINE double capn_to_f64(uint64_t v) { + union capn_conv_f64 u; + u.u = v; + return u.f; +} +CAPN_INLINE uint32_t capn_from_f32(float v) { + union capn_conv_f32 u; + u.f = v; + return u.u; +} +CAPN_INLINE uint64_t capn_from_f64(double v) { + union capn_conv_f64 u; + u.f = v; + return u.u; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/subprojects/c-capnproto/lib/capnp_priv.h b/src/subprojects/c-capnproto/lib/capnp_priv.h new file mode 100644 index 00000000..6c03763e --- /dev/null +++ b/src/subprojects/c-capnproto/lib/capnp_priv.h @@ -0,0 +1,62 @@ +/* vim: set sw=8 ts=8 sts=8 noet: */ +/* capnp_c.h + * + * Copyright (C) 2013 James McKaskill + * Copyright (C) 2014 Steve Dee + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +/* + * functions / structures in this header are private to the capnproto-c + * library; applications should not call or use them. + */ + +#ifndef CAPNP_PRIV_H +#define CAPNP_PRIV_H + +#include "capnp_c.h" + +#if defined(__GNUC__) && __GNUC__ >= 4 +# define intern __attribute__((visibility ("internal"))) +#else +# define intern /**/ +#endif + +/* capn_stream encapsulates the needed fields for capn_(deflate|inflate) in a + * similar manner to z_stream from zlib + * + * The user should set next_in, avail_in, next_out, avail_out to the + * available in/out buffers before calling capn_(deflate|inflate). + * + * Other fields should be zero initialized. + */ +struct capn_stream { + const uint8_t *next_in; + size_t avail_in; + uint8_t *next_out; + size_t avail_out; + unsigned zeros, raw; + + uint8_t inflate_buf[8]; + size_t avail_buf; +}; + +#define CAPN_MISALIGNED -1 +#define CAPN_NEED_MORE -2 + +/* capn_deflate deflates a stream to the packed format + * capn_inflate inflates a stream from the packed format + * + * Returns: + * CAPN_MISALIGNED - if the unpacked data is not 8 byte aligned + * CAPN_NEED_MORE - more packed data/room is required (out for inflate, in for + * deflate) + * 0 - success, all output for inflate, all input for deflate processed + */ +intern int capn_deflate(struct capn_stream*); +intern int capn_inflate(struct capn_stream*); + + +#endif /* CAPNP_PRIV_H */ diff --git a/src/subprojects/c-capnproto/m4/.gitignore b/src/subprojects/c-capnproto/m4/.gitignore new file mode 100644 index 00000000..0f4126cd --- /dev/null +++ b/src/subprojects/c-capnproto/m4/.gitignore @@ -0,0 +1 @@ +*.m4 diff --git a/src/subprojects/c-capnproto/meson.build b/src/subprojects/c-capnproto/meson.build new file mode 100644 index 00000000..e6d7ed5f --- /dev/null +++ b/src/subprojects/c-capnproto/meson.build @@ -0,0 +1,130 @@ +project('capnp-c', ['c','cpp'], meson_version: '>=1.0.0', default_options : ['c_std=c99', 'cpp_std=c++14']) + +pkg = import('pkgconfig') +cc = meson.get_compiler('c') + +common_c_args = [] +common_cpp_args = ['-std=c++14'] +libcapnp_c_args = [] +libcapnp_src = [ + 'lib' / 'capn-malloc.c', + 'lib' / 'capn-stream.c', + 'lib' / 'capn.c', +] + +libcapnp = library('capnp', libcapnp_src, + c_args : common_c_args + libcapnp_c_args, + dependencies: [], + implicit_include_directories: false, + include_directories: include_directories(['compiler', 'lib']) +) + +libcapnp_dep = declare_dependency( + link_with: libcapnp, + dependencies: [], + include_directories: include_directories(['compiler', 'lib']) +) + +capnpc_src = [ + 'compiler' / 'capnpc-c.c', + 'compiler' / 'schema.capnp.c', + 'compiler' / 'str.c' +] + +capnpc_c = executable('capnpc-c', capnpc_src, + include_directories: include_directories(['lib']), + dependencies: [libcapnp_dep], + c_args : common_c_args, +) + +capnp_install_lib = static_library('CapnC_Runtime', + ['lib' / 'capn-malloc.c', + 'lib' / 'capn-stream.c', + 'lib' / 'capn.c'], + include_directories: include_directories(['compiler', 'lib']), + dependencies: [], + implicit_include_directories: false, + install: true, +) + +install_headers(['lib' / 'capnp_c.h']) + +capnpc_c_install = executable('capnpc-c-install', + ['compiler' / 'capnpc-c.c', + 'compiler' / 'schema.capnp.c', + 'compiler' / 'str.c'], + include_directories: include_directories(['lib']), + link_with: capnp_install_lib, + c_args : common_c_args, + install: true) + +meson.add_install_script('sh', '-c', + 'mv "$MESON_INSTALL_DESTDIR_PREFIX/bin/capnpc-c-install" "$MESON_INSTALL_DESTDIR_PREFIX/bin/capnpc-c"') + +pkg.generate(capnp_install_lib, + name: 'c-capnproto', + description: 'Cap\'n Proto C bindings', + version: '1.0.1') + +# Register the fallbacks the parent resolves through this wrap's [provide] +# section: dependency('c-capnproto') and find_program('capnpc-c'). Without +# these the subproject builds but the parent lookup fails ("did not override +# ... dependency"). +capnp_c_dep = declare_dependency( + link_with: capnp_install_lib, + include_directories: include_directories('lib'), + version: '1.0.1') +meson.override_dependency('c-capnproto', capnp_c_dep) +meson.override_find_program('capnpc-c', capnpc_c) + +# Raw flags for non-meson consumers (frontend/apiserver reads them via +# dep.get_variable() to fill CGO_CFLAGS/CGO_LDFLAGS -- Go's cgo cannot +# consume meson dependency objects). Mirrors the nix c-capnproto.pc +# (Libs: -L${libdir} -lCapnC_Runtime, Cflags: -I${includedir}); the archive +# lands in this subproject's build-dir root. +capnp_c_raw = declare_dependency( + variables: { + 'cflags': '-I' + meson.current_source_dir() / 'lib', + 'ldflags': '-L' + meson.current_build_dir() + ' -lCapnC_Runtime', + }) +meson.override_dependency('c-capnproto-raw', capnp_c_raw) + +capn_test_src = [ + 'tests' / 'capn-test.cpp', + 'tests' / 'capn-stream-test.cpp', + 'tests' / 'example-test.cpp', + 'tests' / 'addressbook.capnp.c', + 'compiler' / 'test.capnp.c', + 'compiler' / 'schema-test.cpp', + 'compiler' / 'schema.capnp.c' +] + +if get_option('enable_tests') and not meson.is_subproject() + + thread_dep = dependency('threads') + + gtest_proj = subproject('gtest') + gtest_dep = gtest_proj.get_variable('gtest_dep') + gmock_dep = gtest_proj.get_variable('gmock_dep') + + test_dependencies = [libcapnp_dep, gtest_dep, gmock_dep, thread_dep] + + if get_option('b_sanitize').contains('address') + test_dependencies += cc.find_library('asan') + endif + if get_option('b_sanitize').contains('undefined') + test_dependencies += cc.find_library('ubsan') + endif + + exe = executable('capn-test', capn_test_src, + include_directories: include_directories(['lib', 'tests', 'compiler']), + dependencies: test_dependencies, + c_args : common_c_args, + cpp_args : common_cpp_args, + install: false, + install_rpath: '', + implicit_include_directories: false + ) + test('capn-test', exe) + +endif diff --git a/src/subprojects/c-capnproto/meson_options.txt b/src/subprojects/c-capnproto/meson_options.txt new file mode 100644 index 00000000..ae5c8a48 --- /dev/null +++ b/src/subprojects/c-capnproto/meson_options.txt @@ -0,0 +1 @@ +option('enable_tests', type: 'boolean', value: true, description: 'Build unit tests in test/ and compiler/') diff --git a/src/subprojects/c-capnproto/subprojects/gtest.wrap b/src/subprojects/c-capnproto/subprojects/gtest.wrap new file mode 100644 index 00000000..195aaca8 --- /dev/null +++ b/src/subprojects/c-capnproto/subprojects/gtest.wrap @@ -0,0 +1,15 @@ +[wrap-file] +directory = googletest-1.13.0 +source_url = https://github.com/google/googletest/archive/refs/tags/v1.13.0.tar.gz +source_filename = gtest-1.13.0.tar.gz +source_hash = ad7fdba11ea011c1d925b3289cf4af2c66a352e18d4c7264392fead75e919363 +patch_filename = gtest_1.13.0-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/gtest_1.13.0-1/get_patch +patch_hash = 6d82a02c3a45071cea989983bf6becde801cbbfd29196ba30dada0215393b082 +wrapdb_version = 1.13.0-1 + +[provide] +gtest = gtest_dep +gtest_main = gtest_main_dep +gmock = gmock_dep +gmock_main = gmock_main_dep diff --git a/src/subprojects/c-capnproto/tests/CMakeLists.txt b/src/subprojects/c-capnproto/tests/CMakeLists.txt new file mode 100644 index 00000000..e12ba2b5 --- /dev/null +++ b/src/subprojects/c-capnproto/tests/CMakeLists.txt @@ -0,0 +1,48 @@ +# googletest +# ---------- +# +# The 1.14.x branch requires at least C++14. +# +# In particular, 19.34+ (MSVC 2022) is required for Visual Studio: +# Avoid GoogleTest 1.14.0 error: +# [build] C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\yvals_core.h(811): +# error STL1001: Unexpected compiler version, expected MSVC 19.34 or newer. +# [build] C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\yvals_core.h(811): +# error C2338: Error in C++ Standard Library usage. +# [build] C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\type_traits(1767): +# error C2275: '_Ty1': illegal use of this type as an expression +set(GIT_TAG) +if(MSVC) + if(MSVC_VERSION LESS 1934) + message(STATUS "Using GoogleTest 1.13 because MSVC 19.34+ (MSVC 2022) is needed for GoogleTest 1.14+") + set(GIT_TAG b796f7d44681514f58a683a3a71ff17c94edb0c1) # v1.13.0 + endif() +elseif(NOT "cxx_std_14" IN_LIST CMAKE_CXX_COMPILE_FEATURES) + message(STATUS "Using GoogleTest 1.13 because C++14 is needed for GoogleTest 1.14+") + set(GIT_TAG b796f7d44681514f58a683a3a71ff17c94edb0c1) # v1.13.0 +endif() +if(NOT GIT_TAG) + set(GIT_TAG f8d7d77c06936315286eb55f8de22cd23c188571) # v1.14.0 +endif() + +include(FetchContent) +FetchContent_Declare(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG ${GIT_TAG} +) +FetchContent_MakeAvailable(googletest) + +add_executable(c-capnproto-testcases addressbook.capnp.c capn-stream-test.cpp capn-test.cpp example-test.cpp) +target_link_libraries(c-capnproto-testcases PRIVATE CapnC_Runtime GTest::gtest) + +include(GoogleTest) +gtest_add_tests(TARGET c-capnproto-testcases TEST_LIST testCases) + +if(WIN32) + # On Windows gtest.dll must be in PATH or in current directory. + foreach(testCase IN LISTS testCases) + set_property(TEST ${testCase} APPEND PROPERTY + ENVIRONMENT_MODIFICATION + PATH=path_list_prepend:${PROJECT_BINARY_DIR}/bin) + endforeach() +endif() diff --git a/src/subprojects/c-capnproto/tests/addressbook.capnp b/src/subprojects/c-capnproto/tests/addressbook.capnp new file mode 100644 index 00000000..c2b85f46 --- /dev/null +++ b/src/subprojects/c-capnproto/tests/addressbook.capnp @@ -0,0 +1,59 @@ +# Based on the addressbook.capnp example in the capnproto C++ project: +# https://github.com/sandstorm-io/capnproto/blob/6816634a08b08bc8f52b4ee809afb58389f19655/c%2B%2B/samples/addressbook.capnp +# +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0x9eb32e19f86ee174; + +using C = import "/c.capnp"; +$C.fieldgetset; + +struct Person { + id @0 :UInt32; + name @1 :Text; + email @2 :Text; + phones @3 :List(PhoneNumber); + + struct PhoneNumber { + number @0 :Text; + type @1 :Type; + + enum Type { + mobile @0; + home @1; + work @2; + } + } + + employment :union { + unemployed @4 :Void; + employer @5 :Text; + school @6 :Text; + selfEmployed @7 :Void; + # We assume that a person is only one of these. + } +} + +struct AddressBook { + people @0 :List(Person); +} + diff --git a/src/subprojects/c-capnproto/tests/addressbook.capnp.c b/src/subprojects/c-capnproto/tests/addressbook.capnp.c new file mode 100644 index 00000000..db2ad3cb --- /dev/null +++ b/src/subprojects/c-capnproto/tests/addressbook.capnp.c @@ -0,0 +1,200 @@ +#include "addressbook.capnp.h" +/* AUTO GENERATED - DO NOT EDIT */ +static const capn_text capn_val0 = {0,"",0}; + +Person_ptr new_Person(struct capn_segment *s) { + Person_ptr p; + p.p = capn_new_struct(s, 8, 4); + return p; +} +Person_list new_Person_list(struct capn_segment *s, int len) { + Person_list p; + p.p = capn_new_list(s, len, 8, 4); + return p; +} +void read_Person(struct Person *s, Person_ptr p) { + capn_resolve(&p.p); + s->id = capn_read32(p.p, 0); + s->name = capn_get_text(p.p, 0, capn_val0); + s->email = capn_get_text(p.p, 1, capn_val0); + s->phones.p = capn_getp(p.p, 2, 0); + s->employment_which = (enum Person_employment_which)(int) capn_read16(p.p, 4); + switch (s->employment_which) { + case Person_employment_employer: + case Person_employment_school: + s->employment.school = capn_get_text(p.p, 3, capn_val0); + break; + default: + break; + } +} +void write_Person(const struct Person *s, Person_ptr p) { + capn_resolve(&p.p); + capn_write32(p.p, 0, s->id); + capn_set_text(p.p, 0, s->name); + capn_set_text(p.p, 1, s->email); + capn_setp(p.p, 2, s->phones.p); + capn_write16(p.p, 4, s->employment_which); + switch (s->employment_which) { + case Person_employment_employer: + case Person_employment_school: + capn_set_text(p.p, 3, s->employment.school); + break; + default: + break; + } +} +void get_Person(struct Person *s, Person_list l, int i) { + Person_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Person(s, p); +} +void set_Person(const struct Person *s, Person_list l, int i) { + Person_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Person(s, p); +} + +uint32_t Person_get_id(Person_ptr p) +{ + uint32_t id; + id = capn_read32(p.p, 0); + return id; +} + +capn_text Person_get_name(Person_ptr p) +{ + capn_text name; + name = capn_get_text(p.p, 0, capn_val0); + return name; +} + +capn_text Person_get_email(Person_ptr p) +{ + capn_text email; + email = capn_get_text(p.p, 1, capn_val0); + return email; +} + +Person_PhoneNumber_list Person_get_phones(Person_ptr p) +{ + Person_PhoneNumber_list phones; + phones.p = capn_getp(p.p, 2, 0); + return phones; +} + +void Person_set_id(Person_ptr p, uint32_t id) +{ + capn_write32(p.p, 0, id); +} + +void Person_set_name(Person_ptr p, capn_text name) +{ + capn_set_text(p.p, 0, name); +} + +void Person_set_email(Person_ptr p, capn_text email) +{ + capn_set_text(p.p, 1, email); +} + +void Person_set_phones(Person_ptr p, Person_PhoneNumber_list phones) +{ + capn_setp(p.p, 2, phones.p); +} + +Person_PhoneNumber_ptr new_Person_PhoneNumber(struct capn_segment *s) { + Person_PhoneNumber_ptr p; + p.p = capn_new_struct(s, 8, 1); + return p; +} +Person_PhoneNumber_list new_Person_PhoneNumber_list(struct capn_segment *s, int len) { + Person_PhoneNumber_list p; + p.p = capn_new_list(s, len, 8, 1); + return p; +} +void read_Person_PhoneNumber(struct Person_PhoneNumber *s, Person_PhoneNumber_ptr p) { + capn_resolve(&p.p); + s->number = capn_get_text(p.p, 0, capn_val0); + s->type = (enum Person_PhoneNumber_Type)(int) capn_read16(p.p, 0); +} +void write_Person_PhoneNumber(const struct Person_PhoneNumber *s, Person_PhoneNumber_ptr p) { + capn_resolve(&p.p); + capn_set_text(p.p, 0, s->number); + capn_write16(p.p, 0, (uint16_t) (s->type)); +} +void get_Person_PhoneNumber(struct Person_PhoneNumber *s, Person_PhoneNumber_list l, int i) { + Person_PhoneNumber_ptr p; + p.p = capn_getp(l.p, i, 0); + read_Person_PhoneNumber(s, p); +} +void set_Person_PhoneNumber(const struct Person_PhoneNumber *s, Person_PhoneNumber_list l, int i) { + Person_PhoneNumber_ptr p; + p.p = capn_getp(l.p, i, 0); + write_Person_PhoneNumber(s, p); +} + +capn_text Person_PhoneNumber_get_number(Person_PhoneNumber_ptr p) +{ + capn_text number; + number = capn_get_text(p.p, 0, capn_val0); + return number; +} + +enum Person_PhoneNumber_Type Person_PhoneNumber_get_type(Person_PhoneNumber_ptr p) +{ + enum Person_PhoneNumber_Type type; + type = (enum Person_PhoneNumber_Type)(int) capn_read16(p.p, 0); + return type; +} + +void Person_PhoneNumber_set_number(Person_PhoneNumber_ptr p, capn_text number) +{ + capn_set_text(p.p, 0, number); +} + +void Person_PhoneNumber_set_type(Person_PhoneNumber_ptr p, enum Person_PhoneNumber_Type type) +{ + capn_write16(p.p, 0, (uint16_t) (type)); +} + +AddressBook_ptr new_AddressBook(struct capn_segment *s) { + AddressBook_ptr p; + p.p = capn_new_struct(s, 0, 1); + return p; +} +AddressBook_list new_AddressBook_list(struct capn_segment *s, int len) { + AddressBook_list p; + p.p = capn_new_list(s, len, 0, 1); + return p; +} +void read_AddressBook(struct AddressBook *s, AddressBook_ptr p) { + capn_resolve(&p.p); + s->people.p = capn_getp(p.p, 0, 0); +} +void write_AddressBook(const struct AddressBook *s, AddressBook_ptr p) { + capn_resolve(&p.p); + capn_setp(p.p, 0, s->people.p); +} +void get_AddressBook(struct AddressBook *s, AddressBook_list l, int i) { + AddressBook_ptr p; + p.p = capn_getp(l.p, i, 0); + read_AddressBook(s, p); +} +void set_AddressBook(const struct AddressBook *s, AddressBook_list l, int i) { + AddressBook_ptr p; + p.p = capn_getp(l.p, i, 0); + write_AddressBook(s, p); +} + +Person_list AddressBook_get_people(AddressBook_ptr p) +{ + Person_list people; + people.p = capn_getp(p.p, 0, 0); + return people; +} + +void AddressBook_set_people(AddressBook_ptr p, Person_list people) +{ + capn_setp(p.p, 0, people.p); +} diff --git a/src/subprojects/c-capnproto/tests/addressbook.capnp.h b/src/subprojects/c-capnproto/tests/addressbook.capnp.h new file mode 100644 index 00000000..80be6c8d --- /dev/null +++ b/src/subprojects/c-capnproto/tests/addressbook.capnp.h @@ -0,0 +1,134 @@ +#ifndef CAPN_9EB32E19F86EE174 +#define CAPN_9EB32E19F86EE174 +/* AUTO GENERATED - DO NOT EDIT */ +#include + +#if CAPN_VERSION != 1 +#error "version mismatch between capnp_c.h and generated code" +#endif + +#include "c.capnp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Person; +struct Person_PhoneNumber; +struct AddressBook; + +typedef struct {capn_ptr p;} Person_ptr; +typedef struct {capn_ptr p;} Person_PhoneNumber_ptr; +typedef struct {capn_ptr p;} AddressBook_ptr; + +typedef struct {capn_ptr p;} Person_list; +typedef struct {capn_ptr p;} Person_PhoneNumber_list; +typedef struct {capn_ptr p;} AddressBook_list; + +enum Person_PhoneNumber_Type { + Person_PhoneNumber_Type_mobile = 0, + Person_PhoneNumber_Type_home = 1, + Person_PhoneNumber_Type_work = 2 +}; +enum Person_employment_which { + Person_employment_unemployed = 0, + Person_employment_employer = 1, + Person_employment_school = 2, + Person_employment_selfEmployed = 3 +}; + +struct Person { + uint32_t id; + capn_text name; + capn_text email; + Person_PhoneNumber_list phones; + enum Person_employment_which employment_which; + union { + capn_text employer; + capn_text school; + } employment; +}; + +static const size_t Person_word_count = 1; + +static const size_t Person_pointer_count = 4; + +static const size_t Person_struct_bytes_count = 40; + +uint32_t Person_get_id(Person_ptr p); + +capn_text Person_get_name(Person_ptr p); + +capn_text Person_get_email(Person_ptr p); + +Person_PhoneNumber_list Person_get_phones(Person_ptr p); + +void Person_set_id(Person_ptr p, uint32_t id); + +void Person_set_name(Person_ptr p, capn_text name); + +void Person_set_email(Person_ptr p, capn_text email); + +void Person_set_phones(Person_ptr p, Person_PhoneNumber_list phones); + +struct Person_PhoneNumber { + capn_text number; + enum Person_PhoneNumber_Type type; +}; + +static const size_t Person_PhoneNumber_word_count = 1; + +static const size_t Person_PhoneNumber_pointer_count = 1; + +static const size_t Person_PhoneNumber_struct_bytes_count = 16; + +capn_text Person_PhoneNumber_get_number(Person_PhoneNumber_ptr p); + +enum Person_PhoneNumber_Type Person_PhoneNumber_get_type(Person_PhoneNumber_ptr p); + +void Person_PhoneNumber_set_number(Person_PhoneNumber_ptr p, capn_text number); + +void Person_PhoneNumber_set_type(Person_PhoneNumber_ptr p, enum Person_PhoneNumber_Type type); + +struct AddressBook { + Person_list people; +}; + +static const size_t AddressBook_word_count = 0; + +static const size_t AddressBook_pointer_count = 1; + +static const size_t AddressBook_struct_bytes_count = 8; + +Person_list AddressBook_get_people(AddressBook_ptr p); + +void AddressBook_set_people(AddressBook_ptr p, Person_list people); + +Person_ptr new_Person(struct capn_segment*); +Person_PhoneNumber_ptr new_Person_PhoneNumber(struct capn_segment*); +AddressBook_ptr new_AddressBook(struct capn_segment*); + +Person_list new_Person_list(struct capn_segment*, int len); +Person_PhoneNumber_list new_Person_PhoneNumber_list(struct capn_segment*, int len); +AddressBook_list new_AddressBook_list(struct capn_segment*, int len); + +void read_Person(struct Person*, Person_ptr); +void read_Person_PhoneNumber(struct Person_PhoneNumber*, Person_PhoneNumber_ptr); +void read_AddressBook(struct AddressBook*, AddressBook_ptr); + +void write_Person(const struct Person*, Person_ptr); +void write_Person_PhoneNumber(const struct Person_PhoneNumber*, Person_PhoneNumber_ptr); +void write_AddressBook(const struct AddressBook*, AddressBook_ptr); + +void get_Person(struct Person*, Person_list, int i); +void get_Person_PhoneNumber(struct Person_PhoneNumber*, Person_PhoneNumber_list, int i); +void get_AddressBook(struct AddressBook*, AddressBook_list, int i); + +void set_Person(const struct Person*, Person_list, int i); +void set_Person_PhoneNumber(const struct Person_PhoneNumber*, Person_PhoneNumber_list, int i); +void set_AddressBook(const struct AddressBook*, AddressBook_list, int i); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/subprojects/c-capnproto/tests/capn-stream-test.cpp b/src/subprojects/c-capnproto/tests/capn-stream-test.cpp new file mode 100644 index 00000000..a05fd7bb --- /dev/null +++ b/src/subprojects/c-capnproto/tests/capn-stream-test.cpp @@ -0,0 +1,338 @@ +/* capn-stream-test.cpp + * + * Copyright (C) 2013 James McKaskill + * Copyright (C) 2014 Steve Dee + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include "capn-stream.c" +#include + +template +union AlignedData { + uint8_t bytes[wordCount * 8]; + uint64_t words[wordCount]; +}; + +TEST(Stream, ReadEmptyStream_Even) { + AlignedData<2> data = {{ + 1, 0, 0, 0, // num of segs - 1 + 0, 0, 0, 0, + 0, 0, 0, 0, + 2, 3, 4, 0, // garbage that should be ignored + }}; + + struct capn ctx; + ASSERT_NE(0, capn_init_mem(&ctx, data.bytes, 12, 0)); + ASSERT_EQ(0, capn_init_mem(&ctx, data.bytes, 16, 0)); + EXPECT_EQ(2, ctx.segnum); + EXPECT_EQ(0, ctx.seglist->len); + EXPECT_EQ(0, ctx.seglist->next->len); + capn_free(&ctx); +} + +TEST(Stream, ReadEmptyStream_Odd) { + AlignedData<3> data = {{ + 2, 0, 0, 0, // num of segs - 1 + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 2, 3, 4, 0, // garbage that should be ignored + }}; + + struct capn ctx; + ASSERT_NE(0, capn_init_mem(&ctx, data.bytes, 12, 0)); + + ASSERT_EQ(0, capn_init_mem(&ctx, data.bytes, 16, 0)); + EXPECT_EQ(3, ctx.segnum); + EXPECT_EQ(0, ctx.seglist->len); + EXPECT_EQ(0, ctx.seglist->next->len); + capn_free(&ctx); + + ASSERT_EQ(0, capn_init_mem(&ctx, data.bytes, 20, 0)); + EXPECT_EQ(3, ctx.segnum); + EXPECT_EQ(0, ctx.seglist->len); + EXPECT_EQ(0, ctx.seglist->next->len); + capn_free(&ctx); +} + +TEST(Stream, ReadStream_Even) { + AlignedData<5> data = {{ + 1, 0, 0, 0, // num of segs - 1 + 1, 0, 0, 0, + 2, 0, 0, 0, + 2, 3, 4, 0, // garbage that should be ignored + 1, 2, 3, 4, 5, 6, 7, 8, + 9,10,11,12,13,14,15,16, + 17,18,19,20,21,22,23,24, + }}; + + struct capn ctx; + ASSERT_NE(0, capn_init_mem(&ctx, data.bytes, 36, 0)); + ASSERT_EQ(0, capn_init_mem(&ctx, data.bytes, 40, 0)); + EXPECT_EQ(2, ctx.segnum); + EXPECT_EQ(8, ctx.seglist->len); + EXPECT_EQ(1, ctx.seglist->data[0]); + EXPECT_EQ(16, ctx.seglist->next->len); + EXPECT_EQ(9, ctx.seglist->next->data[0]); + capn_free(&ctx); +} + +static struct capn_segment *CreateSmallSegment(void *u, uint32_t id, int sz) { + struct capn_segment *s = (struct capn_segment*) calloc(1, sizeof(*s)); + s->data = (char*) calloc(1, sz); + s->cap = sz; + return s; +} + +TEST(Stream, SizeEmptyStream) { + struct capn ctx; + capn_init_malloc(&ctx); + struct capn_ptr root = capn_root(&ctx); + ASSERT_EQ(CAPN_PTR_LIST, root.type); + EXPECT_EQ(2*8, capn_size(&ctx)); + + capn_free(&ctx); +} + +TEST(Stream, SizeOneSegment) { + struct capn ctx; + capn_init_malloc(&ctx); + struct capn_ptr root = capn_root(&ctx); + struct capn_ptr ptr = capn_new_struct(root.seg, 8, 0); + EXPECT_EQ(0, capn_setp(root, 0, ptr)); + EXPECT_EQ(0, capn_write64(ptr, 0, UINT64_C(0x1011121314151617))); + EXPECT_EQ(3*8, capn_size(&ctx)); + + capn_free(&ctx); +} + +TEST(Stream, SizeTwoSegments) { + struct capn ctx; + capn_init_malloc(&ctx); + ctx.create = &CreateSmallSegment; + struct capn_ptr root = capn_root(&ctx); + struct capn_ptr ptr1 = capn_new_struct(root.seg, 8, 0); + EXPECT_EQ(0, capn_setp(root, 0, ptr1)); + EXPECT_EQ(0, capn_write64(ptr1, 0, UINT64_C(0xfffefdfcfbfaf9f8))); + EXPECT_EQ(2, ctx.segnum); + + /* 2 words: header + * 1 word: segment 1 + * 2 words: segment 2 + */ + EXPECT_EQ(5*8, capn_size(&ctx)); + + capn_free(&ctx); +} + +TEST(Stream, SizeThreeSegments) { + struct capn ctx; + capn_init_malloc(&ctx); + ctx.create = &CreateSmallSegment; + struct capn_ptr root = capn_root(&ctx); + struct capn_ptr ptr1 = capn_new_struct(root.seg, 0, 1); + EXPECT_EQ(0, capn_setp(root, 0, ptr1)); + struct capn_ptr ptr2 = capn_new_struct(ptr1.seg, 4, 0); + EXPECT_EQ(0, capn_setp(ptr1, 0, ptr2)); + EXPECT_EQ(0, capn_write32(ptr2, 0, 0x12345678)); + EXPECT_EQ(3, ctx.segnum); + + EXPECT_EQ(7*8, capn_size(&ctx)); + + capn_free(&ctx); +} + +TEST(Stream, WriteEmptyStream) { + uint8_t buf[2048]; + + struct capn ctx1, ctx2; + capn_init_malloc(&ctx1); + struct capn_ptr root = capn_root(&ctx1); + ASSERT_EQ(CAPN_PTR_LIST, root.type); + EXPECT_EQ(-1, capn_write_mem(&ctx1, buf, 2*8-1, 0)); + EXPECT_EQ(2*8, capn_write_mem(&ctx1, buf, 2048, 0)); + ASSERT_EQ(0, capn_init_mem(&ctx2, buf, 2048, 0)); + EXPECT_EQ(1, ctx2.segnum); + EXPECT_EQ(8, ctx2.seglist->len); + EXPECT_EQ(0, ctx2.seglist->next); + + capn_free(&ctx1); + capn_free(&ctx2); +} + +TEST(Stream, WriteEmptyStreamPacked) { + uint8_t buf[2048]; + + struct capn ctx1, ctx2; + capn_init_malloc(&ctx1); + struct capn_ptr root = capn_root(&ctx1); + ASSERT_EQ(CAPN_PTR_LIST, root.type); + EXPECT_EQ(-1, capn_write_mem(&ctx1, buf, 3, 1)); + EXPECT_EQ(4, capn_write_mem(&ctx1, buf, 2048, 1)); + ASSERT_EQ(0, capn_init_mem(&ctx2, buf, 2048, 1)); + EXPECT_EQ(1, ctx2.segnum); + EXPECT_EQ(8, ctx2.seglist->len); + EXPECT_EQ(0, ctx2.seglist->next); + + capn_free(&ctx1); + capn_free(&ctx2); +} + +TEST(Stream, WriteOneSegment) { + uint8_t buf[2048]; + + struct capn ctx1, ctx2; + capn_init_malloc(&ctx1); + + struct capn_ptr root = capn_root(&ctx1); + struct capn_ptr ptr = capn_new_struct(root.seg, 8, 0); + EXPECT_EQ(0, capn_setp(root, 0, ptr)); + EXPECT_EQ(0, capn_write64(ptr, 0, UINT64_C(0x1011121314151617))); + + EXPECT_EQ(-1, capn_write_mem(&ctx1, buf, 3*8-1, 0)); + EXPECT_EQ(3*8, capn_write_mem(&ctx1, buf, 2048, 0)); + ASSERT_EQ(0, capn_init_mem(&ctx2, buf, 2048, 0)); + EXPECT_EQ(1, ctx2.segnum); + + root = capn_root(&ctx2); + ptr = capn_getp(root, 0, 1); + EXPECT_EQ(UINT64_C(0x1011121314151617), capn_read64(ptr, 0)); + + capn_free(&ctx1); + capn_free(&ctx2); +} + +TEST(Stream, WriteOneSegmentPacked) { + uint8_t buf[2048]; + + struct capn ctx1, ctx2; + capn_init_malloc(&ctx1); + + struct capn_ptr root = capn_root(&ctx1); + struct capn_ptr ptr = capn_new_struct(root.seg, 8, 0); + EXPECT_EQ(0, capn_setp(root, 0, ptr)); + EXPECT_EQ(0, capn_write64(ptr, 0, UINT64_C(0x1011121314151617))); + + EXPECT_EQ(-1, capn_write_mem(&ctx1, buf, 13, 1)); + EXPECT_EQ(14, capn_write_mem(&ctx1, buf, 2048, 1)); + ASSERT_EQ(0, capn_init_mem(&ctx2, buf, 2048, 1)); + EXPECT_EQ(1, ctx2.segnum); + + root = capn_root(&ctx2); + ptr = capn_getp(root, 0, 1); + EXPECT_EQ(UINT64_C(0x1011121314151617), capn_read64(ptr, 0)); + + capn_free(&ctx1); + capn_free(&ctx2); +} + +TEST(Stream, WriteTwoSegments) { + struct capn ctx1, ctx2; + uint8_t buf[5*8]; + + capn_init_malloc(&ctx1); + ctx1.create = &CreateSmallSegment; + struct capn_ptr root = capn_root(&ctx1); + struct capn_ptr ptr1 = capn_new_struct(root.seg, 8, 0); + EXPECT_EQ(0, capn_setp(root, 0, ptr1)); + EXPECT_EQ(0, capn_write64(ptr1, 0, UINT64_C(0xfffefdfcfbfaf9f8))); + EXPECT_EQ(2, ctx1.segnum); + + /* 2 words: header + * 1 word: segment 1 + * 2 words: segment 2 + */ + EXPECT_EQ(5*8, capn_write_mem(&ctx1, buf, 5*8, 0)); + + ASSERT_EQ(0, capn_init_mem(&ctx2, buf, 2048, 0)); + root = capn_root(&ctx2); + ptr1 = capn_getp(root, 0, 1); + EXPECT_EQ(UINT64_C(0xfffefdfcfbfaf9f8), capn_read64(ptr1, 0)); + + capn_free(&ctx1); + capn_free(&ctx2); +} + +TEST(Stream, WriteTwoSegmentsPacked) { + struct capn ctx1, ctx2; + uint8_t buf[5*8]; + + capn_init_malloc(&ctx1); + ctx1.create = &CreateSmallSegment; + struct capn_ptr root = capn_root(&ctx1); + struct capn_ptr ptr1 = capn_new_struct(root.seg, 8, 0); + EXPECT_EQ(0, capn_setp(root, 0, ptr1)); + EXPECT_EQ(0, capn_write64(ptr1, 0, UINT64_C(0xfffefdfcfbfaf9f8))); + EXPECT_EQ(2, ctx1.segnum); + + /* 2 words: header + * 1 word: segment 1 + * 2 words: segment 2 + */ + EXPECT_EQ(20, capn_write_mem(&ctx1, buf, 5*8, 1)); + + ASSERT_EQ(0, capn_init_mem(&ctx2, buf, 2048, 1)); + root = capn_root(&ctx2); + ptr1 = capn_getp(root, 0, 1); + EXPECT_EQ(UINT64_C(0xfffefdfcfbfaf9f8), capn_read64(ptr1, 0)); + + capn_free(&ctx1); + capn_free(&ctx2); +} + +TEST(Stream, WriteThreeSegments) { + struct capn ctx1, ctx2; + uint8_t buf[2048]; + + capn_init_malloc(&ctx1); + ctx1.create = &CreateSmallSegment; + struct capn_ptr root = capn_root(&ctx1); + struct capn_ptr ptr1 = capn_new_struct(root.seg, 0, 1); + EXPECT_EQ(0, capn_setp(root, 0, ptr1)); + struct capn_ptr ptr2 = capn_new_struct(ptr1.seg, 4, 0); + EXPECT_EQ(0, capn_setp(ptr1, 0, ptr2)); + EXPECT_EQ(0, capn_write32(ptr2, 0, 0x12345678)); + EXPECT_EQ(3, ctx1.segnum); + + EXPECT_EQ(-1, capn_write_mem(&ctx1, buf, 7*8-1, 0)); + EXPECT_EQ(7*8, capn_write_mem(&ctx1, buf, 2048, 0)); + + EXPECT_EQ(0, capn_init_mem(&ctx2, buf, 2048, 0)); + root = capn_root(&ctx2); + ptr1 = capn_getp(root, 0, 1); + ptr2 = capn_getp(ptr1, 0, 1); + EXPECT_EQ(0x12345678, capn_read32(ptr2, 0)); + + capn_free(&ctx1); + capn_free(&ctx2); +} + +TEST(Stream, WriteThreeSegmentsPacked) { + struct capn ctx1, ctx2; + uint8_t buf[2048]; + + capn_init_malloc(&ctx1); + ctx1.create = &CreateSmallSegment; + struct capn_ptr root = capn_root(&ctx1); + struct capn_ptr ptr1 = capn_new_struct(root.seg, 0, 1); + EXPECT_EQ(0, capn_setp(root, 0, ptr1)); + struct capn_ptr ptr2 = capn_new_struct(ptr1.seg, 4, 0); + EXPECT_EQ(0, capn_setp(ptr1, 0, ptr2)); + EXPECT_EQ(0, capn_write32(ptr2, 0, 0x12345678)); + EXPECT_EQ(3, ctx1.segnum); + + EXPECT_EQ(-1, capn_write_mem(&ctx1, buf, 20, 1)); + EXPECT_EQ(21, capn_write_mem(&ctx1, buf, 2048, 1)); + + EXPECT_EQ(0, capn_init_mem(&ctx2, buf, 2048, 1)); + root = capn_root(&ctx2); + ptr1 = capn_getp(root, 0, 1); + ptr2 = capn_getp(ptr1, 0, 1); + EXPECT_EQ(0x12345678, capn_read32(ptr2, 0)); + + capn_free(&ctx1); + capn_free(&ctx2); +} diff --git a/src/subprojects/c-capnproto/tests/capn-test.cpp b/src/subprojects/c-capnproto/tests/capn-test.cpp new file mode 100644 index 00000000..a08f35a1 --- /dev/null +++ b/src/subprojects/c-capnproto/tests/capn-test.cpp @@ -0,0 +1,454 @@ +/* capn-test.cpp + * + * Copyright (C) 2013 James McKaskill + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include +#include + +static int g_AddTag = 1; +#define ADD_TAG g_AddTag + +#include "capn.c" +#include "capn-malloc.c" + +template +union AlignedData { + uint8_t bytes[wordCount * 8]; + uint64_t words[wordCount]; +}; + +class Session { +public: + Session() {capn_init_malloc(&capn);} + ~Session() {capn_free(&capn);} + struct capn capn; +}; + + + + + +TEST(WireFormat, SimpleRawDataStruct) { + AlignedData<2> data = {{ + // Struct ref, offset = 1, dataSize = 1, referenceCount = 0 + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + // Content for the data segment. + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef + }}; + + struct capn_segment seg; + memset(&seg, 0, sizeof(seg)); + seg.data = (char*) data.bytes; + seg.len = seg.cap = sizeof(data.bytes); + + struct capn ctx; + memset(&ctx, 0, sizeof(ctx)); + capn_append_segment(&ctx, &seg); + + EXPECT_EQ(&seg, ctx.seglist); + EXPECT_EQ(&seg, ctx.lastseg); + EXPECT_EQ(&seg.hdr, ctx.segtree); + EXPECT_EQ(1, ctx.segnum); + EXPECT_EQ(0, seg.id); + + struct capn_ptr ptr = capn_getp(capn_root(&ctx), 0, 1); + EXPECT_EQ(CAPN_STRUCT, ptr.type); + EXPECT_EQ(8, ptr.datasz); + EXPECT_EQ(0, ptr.ptrs); + + EXPECT_EQ(UINT64_C(0xefcdab8967452301), capn_read64(ptr, 0)); + EXPECT_EQ(UINT64_C(0), capn_read64(ptr, 8)); + EXPECT_EQ(UINT32_C(0x67452301), capn_read32(ptr, 0)); + EXPECT_EQ(UINT32_C(0xefcdab89), capn_read32(ptr, 4)); + EXPECT_EQ(UINT32_C(0), capn_read32(ptr, 8)); + EXPECT_EQ(UINT16_C(0x2301), capn_read16(ptr, 0)); + EXPECT_EQ(UINT16_C(0x6745), capn_read16(ptr, 2)); + EXPECT_EQ(UINT16_C(0xab89), capn_read16(ptr, 4)); + EXPECT_EQ(UINT16_C(0xefcd), capn_read16(ptr, 6)); + EXPECT_EQ(UINT16_C(0), capn_read16(ptr, 8)); +} + +static void setupStruct(struct capn *ctx) { + struct capn_ptr root = capn_root(ctx); + ASSERT_EQ(CAPN_PTR_LIST, root.type); + ASSERT_EQ(1, root.len); + + struct capn_ptr ptr = capn_new_struct(root.seg, 16, 6); + ASSERT_EQ(CAPN_STRUCT, ptr.type); + EXPECT_EQ(16, ptr.datasz); + EXPECT_EQ(6, ptr.ptrs); + EXPECT_EQ(0, capn_setp(root, 0, ptr)); + + EXPECT_EQ(0, capn_write64(ptr, 0, UINT64_C(0x1011121314151617))); + EXPECT_EQ(0, capn_write32(ptr, 8, UINT32_C(0x20212223))); + EXPECT_EQ(0, capn_write16(ptr, 12, UINT16_C(0x3031))); + EXPECT_EQ(0, capn_write8(ptr, 14, 0x40)); + EXPECT_EQ(0, capn_write8(ptr, 15, (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2))); + + capn_ptr subStruct = capn_new_struct(ptr.seg, 8, 0); + ASSERT_EQ(CAPN_STRUCT, subStruct.type); + EXPECT_EQ(8, subStruct.datasz); + EXPECT_EQ(0, subStruct.ptrs); + EXPECT_EQ(0, capn_write32(subStruct, 0, 123)); + EXPECT_NE(0, capn_write32(subStruct, 8, 124)); + EXPECT_EQ(0, capn_setp(ptr, 0, subStruct)); + + capn_list32 list32 = capn_new_list32(ptr.seg, 3); + capn_list64 list64 = {list32.p}; + ASSERT_EQ(CAPN_LIST, list32.p.type); + EXPECT_EQ(3, list32.p.len); + EXPECT_EQ(4, list32.p.datasz); + EXPECT_EQ(0, capn_set32(list32, 0, 200)); + EXPECT_EQ(0, capn_set32(list32, 1, 201)); + EXPECT_EQ(0, capn_set32(list32, 2, 202)); + EXPECT_NE(0, capn_set32(list32, 3, 203)); + EXPECT_NE(0, capn_set64(list64, 0, 405)); + EXPECT_EQ(0, capn_setp(ptr, 1, list32.p)); + + capn_ptr list = capn_new_list(ptr.seg, 4, 4, 1); + ASSERT_EQ(CAPN_LIST, list.type); + ASSERT_EQ(1, list.is_composite_list); + EXPECT_EQ(4, list.len); + EXPECT_EQ(8, list.datasz); + EXPECT_EQ(1, list.ptrs); + EXPECT_EQ(0, capn_setp(ptr, 2, list)); + for (int i = 0; i < 4; i++) { + capn_ptr element = capn_getp(list, i, 1); + ASSERT_EQ(CAPN_STRUCT, element.type); + EXPECT_EQ(1, element.is_list_member); + EXPECT_EQ(8, element.datasz); + EXPECT_EQ(1, element.ptrs); + EXPECT_EQ(0, capn_write32(element, 0, 300+i)); + + capn_ptr subelement = capn_new_struct(element.seg, 8, 0); + ASSERT_EQ(CAPN_STRUCT, subelement.type); + EXPECT_EQ(8, subelement.datasz); + EXPECT_EQ(0, subelement.ptrs); + EXPECT_EQ(0, capn_write32(subelement, 0, 400+i)); + EXPECT_EQ(0, capn_setp(element, 0, subelement)); + } + + list = capn_new_ptr_list(ptr.seg, 5); + ASSERT_EQ(CAPN_PTR_LIST, list.type); + EXPECT_EQ(5, list.len); + EXPECT_EQ(0, capn_setp(ptr, 3, list)); + for (int i = 0; i < 5; i++) { + capn_list16 element = capn_new_list16(list.seg, i+1); + ASSERT_EQ(CAPN_LIST, element.p.type); + EXPECT_EQ(i+1, element.p.len); + EXPECT_EQ(2, element.p.datasz); + EXPECT_EQ(0, element.p.ptrs); + EXPECT_EQ(0, capn_setp(list, i, element.p)); + for (int j = 0; j <= i; j++) { + EXPECT_EQ(0, capn_set16(element, j, 500+j)); + } + } + + capn_ptr recurse = capn_new_struct(ptr.seg, 0, 2); + EXPECT_EQ(CAPN_STRUCT, recurse.type); + EXPECT_EQ(0, recurse.datasz); + EXPECT_EQ(2, recurse.ptrs); + EXPECT_EQ(0, capn_setp(recurse, 0, recurse)); + EXPECT_EQ(0, capn_setp(ptr, 4, recurse)); + +} + +static void checkStruct(struct capn *ctx) { + capn_ptr ptr = capn_getp(capn_root(ctx), 0, 1); + EXPECT_EQ(CAPN_STRUCT, ptr.type); + EXPECT_EQ(16, ptr.datasz); + EXPECT_EQ(6, ptr.ptrs); + EXPECT_EQ(UINT64_C(0x1011121314151617), capn_read64(ptr, 0)); + EXPECT_EQ(UINT32_C(0x20212223), capn_read32(ptr, 8)); + EXPECT_EQ(0x3031, capn_read16(ptr, 12)); + EXPECT_EQ(0x40, capn_read8(ptr, 14)); + EXPECT_EQ((1 << 6) | (1 << 5) | (1 << 4) | (1 << 2), capn_read8(ptr, 15)); + + capn_ptr subStruct = capn_getp(ptr, 0, 1); + EXPECT_EQ(CAPN_STRUCT, subStruct.type); + EXPECT_EQ(8, subStruct.datasz); + EXPECT_EQ(0, subStruct.ptrs); + EXPECT_EQ(123, capn_read32(subStruct, 0)); + + capn_list32 list32 = {capn_getp(ptr, 1, 1)}; + capn_list8 list8 = {list32.p}; + capn_list16 list16 = {list32.p}; + capn_list64 list64 = {list32.p}; + EXPECT_EQ(CAPN_LIST, list32.p.type); + EXPECT_EQ(3, list32.p.len); + EXPECT_EQ(4, list32.p.datasz); + EXPECT_EQ(0, list32.p.ptrs); + EXPECT_EQ(200, capn_get32(list32, 0)); + EXPECT_EQ(201, capn_get32(list32, 1)); + EXPECT_EQ(202, capn_get32(list32, 2)); + EXPECT_EQ(0, capn_get32(list32, 3)); + EXPECT_EQ(0, capn_get64(list64, 0)); + EXPECT_EQ(201, capn_get8(list8, 1)); + EXPECT_EQ(202, capn_get16(list16, 2)); + + capn_ptr list = capn_getp(ptr, 2, 1); + EXPECT_EQ(CAPN_LIST, list.type); + EXPECT_EQ(1, list.is_composite_list); + EXPECT_EQ(4, list.len); + EXPECT_EQ(8, list.datasz); + EXPECT_EQ(1, list.ptrs); + + for (int i = 0; i < 4; i++) { + capn_ptr element = capn_getp(list, i, 1); + EXPECT_EQ(CAPN_STRUCT, element.type); + EXPECT_EQ(1, element.is_list_member); + EXPECT_EQ(8, element.datasz); + EXPECT_EQ(1, element.ptrs); + EXPECT_EQ(300+i, capn_read32(element,0)); + + capn_ptr subelement = capn_getp(element, 0, 1); + EXPECT_EQ(CAPN_STRUCT, subelement.type); + EXPECT_EQ(8, subelement.datasz); + EXPECT_EQ(0, subelement.ptrs); + EXPECT_EQ(400+i, capn_read32(subelement, 0)); + } + + list = capn_getp(ptr, 3, 1); + EXPECT_EQ(CAPN_PTR_LIST, list.type); + EXPECT_EQ(5, list.len); + for (int i = 0; i < 5; i++) { + capn_list16 element = {capn_getp(list, i, 1)}; + EXPECT_EQ(CAPN_LIST, element.p.type); + EXPECT_EQ(i+1, element.p.len); + EXPECT_EQ(2, element.p.datasz); + EXPECT_EQ(0, element.p.ptrs); + for (int j = 0; j <= i; j++) { + EXPECT_EQ(500+j, capn_get16(element, j)); + } + } + + capn_ptr recurse = capn_getp(ptr, 4, 1); + EXPECT_EQ(CAPN_STRUCT, recurse.type); + EXPECT_EQ(0, recurse.datasz); + EXPECT_EQ(2, recurse.ptrs); + capn_ptr recurse_mbr = capn_getp(recurse, 0, 1); + EXPECT_EQ(CAPN_STRUCT, recurse_mbr.type); + EXPECT_EQ(0, recurse_mbr.datasz); + EXPECT_EQ(2, recurse_mbr.ptrs); + EXPECT_EQ(recurse.seg, recurse_mbr.seg); + EXPECT_EQ(recurse.data, recurse_mbr.data); + EXPECT_EQ(CAPN_NULL, capn_getp(recurse, 1, 1).type); +} + +TEST(WireFormat, StructRoundTrip_OneSegment) { + Session ctx; + setupStruct(&ctx.capn); + + // word count: + // 1 root reference + // 8 root struct + // 1 sub message + // 2 3-element int32 list + // 13 struct list + // 1 tag + // 12 4x struct + // 1 data segment + // 1 reference segment + // 1 sub-struct + // 11 list list + // 5 references to sub-lists + // 6 sub-lists (4x 1 word, 1x 2 words) + // 2 recurse + // ----- + // 38 + ASSERT_EQ(1, ctx.capn.segnum); + EXPECT_EQ(38*8, ctx.capn.seglist->len); + + checkStruct(&ctx.capn); + + struct capn ctx2; + memset(&ctx2, 0, sizeof(ctx2)); + capn_append_segment(&ctx2, ctx.capn.seglist); + checkStruct(&ctx2); +} + +static struct capn_segment *CreateSmallSegment(void *u, uint32_t id, int sz) { + struct capn_segment *s = (struct capn_segment*) calloc(1, sizeof(*s)); + s->data = (char*) calloc(1, sz); + s->cap = sz; + return s; +} + +static void getSegments(struct capn *c, struct capn_segment **s, size_t num) { + ASSERT_EQ(num, c->segnum); + + s[0] = c->seglist; + for (size_t i = 1; i < num; i++) { + s[i] = s[i-1]->next; + } + + for (size_t i = 0; i < num; i++) { + EXPECT_EQ(s[i]->id, i); + } +} + +TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) { + Session ctx; + ctx.capn.create = &CreateSmallSegment; + + setupStruct(&ctx.capn); + + struct capn_segment *segments[16]; + getSegments(&ctx.capn, segments, 16); + + // Check that each segment has the expected size. Recall that the first word of each segment will + // actually be a reference to the first thing allocated within that segment. + EXPECT_EQ( 8, segments[ 0]->len); // root ref + EXPECT_EQ(72, segments[ 1]->len); // root struct + EXPECT_EQ(16, segments[ 2]->len); // sub-struct + EXPECT_EQ(24, segments[ 3]->len); // 3-element int32 list + EXPECT_EQ(80, segments[ 4]->len); // struct list + EXPECT_EQ(16, segments[ 5]->len); // struct list substruct 1 + EXPECT_EQ(16, segments[ 6]->len); // struct list substruct 2 + EXPECT_EQ(16, segments[ 7]->len); // struct list substruct 3 + EXPECT_EQ(16, segments[ 8]->len); // struct list substruct 4 + EXPECT_EQ(48, segments[ 9]->len); // list list + EXPECT_EQ(16, segments[10]->len); // list list sublist 1 + EXPECT_EQ(16, segments[11]->len); // list list sublist 2 + EXPECT_EQ(16, segments[12]->len); // list list sublist 3 + EXPECT_EQ(16, segments[13]->len); // list list sublist 4 + EXPECT_EQ(24, segments[14]->len); // list list sublist 5 + EXPECT_EQ(24, segments[15]->len); // recurse struct + + checkStruct(&ctx.capn); + + struct capn ctx2; + memset(&ctx2, 0, sizeof(ctx2)); + for (size_t i = 0; i < sizeof(segments)/sizeof(segments[0]); i++) { + capn_append_segment(&ctx2, segments[i]); + } + + checkStruct(&ctx2); +} + +TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation_NoTag) { + Session ctx; + ctx.capn.create = &CreateSmallSegment; + + g_AddTag = 0; + setupStruct(&ctx.capn); + g_AddTag = 1; + + struct capn_segment *segments[31]; + getSegments(&ctx.capn, segments, 31); + + // Check that each segment has the expected size. Note that we have plenty + // of 16 byte double far ptrs. + EXPECT_EQ( 8, segments[ 0]->len); // root ref + EXPECT_EQ(64, segments[ 1]->len); // root struct + EXPECT_EQ(16, segments[ 2]->len); // root struct ptr + EXPECT_EQ( 8, segments[ 3]->len); // sub-struct + EXPECT_EQ(16, segments[ 4]->len); // sub-struct ptr + EXPECT_EQ(16, segments[ 5]->len); // 3-element int32 list + EXPECT_EQ(16, segments[ 6]->len); // 3-element int32 list ptr + EXPECT_EQ(72, segments[ 7]->len); // struct list + EXPECT_EQ(16, segments[ 8]->len); // struct list ptr + EXPECT_EQ( 8, segments[ 9]->len); // struct list substruct 1 + EXPECT_EQ(16, segments[10]->len); // struct list substruct 1 ptr + EXPECT_EQ( 8, segments[11]->len); // struct list substruct 2 + EXPECT_EQ(16, segments[12]->len); // struct list substruct 2 ptr + EXPECT_EQ( 8, segments[13]->len); // struct list substruct 3 + EXPECT_EQ(16, segments[14]->len); // struct list substruct 3 ptr + EXPECT_EQ( 8, segments[15]->len); // struct list substruct 4 + EXPECT_EQ(16, segments[16]->len); // struct list substruct 4 ptr + EXPECT_EQ(40, segments[17]->len); // list list + EXPECT_EQ(16, segments[18]->len); // list list ptr + EXPECT_EQ( 8, segments[19]->len); // list list sublist 1 + EXPECT_EQ(16, segments[20]->len); // list list sublist 1 ptr + EXPECT_EQ( 8, segments[21]->len); // list list sublist 2 + EXPECT_EQ(16, segments[22]->len); // list list sublist 2 ptr + EXPECT_EQ( 8, segments[23]->len); // list list sublist 3 + EXPECT_EQ(16, segments[24]->len); // list list sublist 3 ptr + EXPECT_EQ( 8, segments[25]->len); // list list sublist 4 + EXPECT_EQ(16, segments[26]->len); // list list sublist 4 ptr + EXPECT_EQ(16, segments[27]->len); // list list sublist 5 + EXPECT_EQ(16, segments[28]->len); // list list sublist 5 ptr + EXPECT_EQ(16, segments[29]->len); // recurse struct + EXPECT_EQ(16, segments[30]->len); // recurse struct ptr + + checkStruct(&ctx.capn); + + struct capn ctx2; + memset(&ctx2, 0, sizeof(ctx2)); + for (size_t i = 0; i < sizeof(segments)/sizeof(segments[0]); i++) { + capn_append_segment(&ctx2, segments[i]); + } + + checkStruct(&ctx2); +} + + +static struct capn_segment *CreateSegment64(void *u, uint32_t id, int sz) { + if (sz < 64) { + sz = 64; + } + struct capn_segment *s = (struct capn_segment*) calloc(1, sizeof(*s)); + s->data = (char*) calloc(1, sz); + s->cap = sz; + return s; +} + +TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) { + Session ctx; + ctx.capn.create = &CreateSegment64; + + setupStruct(&ctx.capn); + + // Verify that we made 6 segments. + ASSERT_EQ(6, ctx.capn.segnum); + + struct capn_segment *segments[6]; + segments[0] = ctx.capn.seglist; + for (int i = 1; i < 6; i++) { + segments[i] = segments[i-1]->next; + } + + for (int i = 0; i < 6; i++) { + EXPECT_EQ(segments[i]->id, i); + } + + // Check that each segment has the expected size. Recall that each object will be prefixed by an + // extra word if its parent is in a different segment. + EXPECT_EQ(64, segments[0]->len); // root ref (8), sub-struct (8+tag), 3-element list (16+tag), list substruct 1 (8+tag) + EXPECT_EQ(72, segments[1]->len); // root struct (64+tag) + EXPECT_EQ(80, segments[2]->len); // struct list (72+tag) + EXPECT_EQ(64, segments[3]->len); // list substruct 2,3,4 3*(8+tag), sublist 3 (8+tag) + EXPECT_EQ(64, segments[4]->len); // list list (40+tag), sublist 1,2 2*8 + EXPECT_EQ(64, segments[5]->len); // sublist 4 (8+tag), 5 (16+tag), recurse struct (16+tag) + + checkStruct(&ctx.capn); + + struct capn ctx2; + memset(&ctx2, 0, sizeof(ctx2)); + for (size_t i = 0; i < sizeof(segments)/sizeof(segments[0]); i++) { + capn_append_segment(&ctx2, segments[i]); + } + + checkStruct(&ctx2); +} + +TEST(WireFormat, CopyStruct) { + Session ctx1, ctx2; + setupStruct(&ctx1.capn); + checkStruct(&ctx1.capn); + + capn_ptr root = capn_root(&ctx2.capn); + EXPECT_EQ(0, capn_setp(root, 0, capn_getp(capn_root(&ctx1.capn), 0, 1))); + + checkStruct(&ctx2.capn); +} + +int main(int argc, char *argv[]) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/src/subprojects/c-capnproto/tests/example-test.cpp b/src/subprojects/c-capnproto/tests/example-test.cpp new file mode 100644 index 00000000..9510685b --- /dev/null +++ b/src/subprojects/c-capnproto/tests/example-test.cpp @@ -0,0 +1,165 @@ +/* example-test.cpp + * + * Some simple examples using c-capnproto. + * + * Based on the addressbook.capnp example in the capnproto C++ project: + * https://github.com/sandstorm-io/capnproto/blob/6816634a08b08bc8f52b4ee809afb58389f19655/c%2B%2B/samples/addressbook.capnp + * + * Copyright (C) 2017 Alex Helfet + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include +#include + +#include "capnp_c.h" +#include "addressbook.capnp.h" + +static capn_text chars_to_text(const char *chars) { + return { + .len = (int) strlen(chars), + .str = chars, + .seg = NULL, + }; +} + +// EXPECT_CAPN_TEXT_EQ arguments: +// const char * expected +// capn_text t +#define EXPECT_CAPN_TEXT_EQ(expected, t) \ + do { \ + EXPECT_EQ(strlen((expected)), (uint32_t) (t).len); \ + EXPECT_STREQ((expected), (t).str); \ + } while(0); + + +// Demonstrates serializing an object tree to a byte array, then deserializing it +// back into an object tree and asserting on the expected values therein. +// +// This example uses generated read_*, write_*, get_*, set_* functions +// to deserialize into structs. +TEST(Examples, RoundTripPerson) { + uint8_t buf[4096]; + ssize_t sz = 0; + + const char *name = "Firstname Lastname"; + const char *email = "username@domain.com"; + const char *school = "of life"; + + { + struct capn c; + capn_init_malloc(&c); + capn_ptr cr = capn_root(&c); + struct capn_segment *cs = cr.seg; + + // Set initial object in `p`. + struct Person p = { + .id = 17, + .name = chars_to_text(name), + .email = chars_to_text(email), + }; + p.employment_which = Person_employment_school; + p.employment.school = chars_to_text(school); + + p.phones = new_Person_PhoneNumber_list(cs, 2); + struct Person_PhoneNumber pn0 = { + .number = chars_to_text("123"), + .type = Person_PhoneNumber_Type_work, + }; + set_Person_PhoneNumber(&pn0, p.phones, 0); + struct Person_PhoneNumber pn1 = { + .number = chars_to_text("234"), + .type = Person_PhoneNumber_Type_home, + }; + set_Person_PhoneNumber(&pn1, p.phones, 1); + + Person_ptr pp = new_Person(cs); + write_Person(&p, pp); + int setp_ret = capn_setp(capn_root(&c), 0, pp.p); + ASSERT_EQ(0, setp_ret); + sz = capn_write_mem(&c, buf, sizeof(buf), 0 /* packed */); + capn_free(&c); + } + + { + // Write serialized object to file system. + FILE *f = fopen("example-test.cpp.Person.out", "wb"); + ASSERT_NE(f, (void*)0); + fwrite(buf, 1 /* size */, sz /* count */, f); + int close_ret = fclose(f); + ASSERT_EQ(0, close_ret); + } + + { + // Deserialize `buf[0..sz-1]` to `rp`. + struct capn rc; + int init_mem_ret = capn_init_mem(&rc, buf, sz, 0 /* packed */); + ASSERT_EQ(0, init_mem_ret); + Person_ptr rroot; + struct Person rp; + rroot.p = capn_getp(capn_root(&rc), 0 /* off */, 1 /* resolve */); + read_Person(&rp, rroot); + + // Assert deserialized values in `rp` + EXPECT_EQ(rp.id, (uint32_t) 17); + EXPECT_CAPN_TEXT_EQ(name, rp.name); + EXPECT_CAPN_TEXT_EQ(email, rp.email); + + EXPECT_EQ(rp.employment_which, Person_employment_school); + EXPECT_CAPN_TEXT_EQ(school, rp.employment.school); + + EXPECT_EQ(2, capn_len(rp.phones)); + + struct Person_PhoneNumber rpn0; + get_Person_PhoneNumber(&rpn0, rp.phones, 0); + EXPECT_CAPN_TEXT_EQ("123", rpn0.number); + EXPECT_EQ(rpn0.type, Person_PhoneNumber_Type_work); + + struct Person_PhoneNumber rpn1; + get_Person_PhoneNumber(&rpn1, rp.phones, 1); + EXPECT_CAPN_TEXT_EQ("234", rpn1.number); + EXPECT_EQ(rpn1.type, Person_PhoneNumber_Type_home); + + capn_free(&rc); + } +} + +// Demonstrate accessing serialized objects using accessor functions without +// first copying values into structs. +TEST(Examples, PersonWithAccessors) { + struct capn c; + capn_init_malloc(&c); + capn_ptr cr = capn_root(&c); + struct capn_segment *cs = cr.seg; + + // Set fields with set_ accessors. + Person_ptr pp = new_Person(cs); + { + Person_set_id(pp, 17); + + capn_text name = chars_to_text("Name"); + EXPECT_CAPN_TEXT_EQ("Name", name); + Person_set_name(pp, name); + + Person_PhoneNumber_list pnl = new_Person_PhoneNumber_list(cs, 1); + Person_set_phones(pp, pnl); + Person_PhoneNumber_ptr pn0; + pn0.p = capn_getp(pnl.p, 0 /* offset */, 0 /* resolve */); + Person_PhoneNumber_set_type(pn0, Person_PhoneNumber_Type_home); + } + + // Assert field values returned by get_ accessors. + { + EXPECT_EQ(Person_get_id(pp), 17); + EXPECT_CAPN_TEXT_EQ("Name", Person_get_name(pp)); + + Person_PhoneNumber_list pnl = Person_get_phones(pp); + Person_PhoneNumber_ptr pn0; + pn0.p = capn_getp(pnl.p, 0 /* offset */, 0 /* resolve */); + EXPECT_EQ(Person_PhoneNumber_Type_home, Person_PhoneNumber_get_type(pn0)); + } + + capn_free(&c); +} diff --git a/src/subprojects/c-capnproto/xmake.lua b/src/subprojects/c-capnproto/xmake.lua new file mode 100644 index 00000000..e0cda0f8 --- /dev/null +++ b/src/subprojects/c-capnproto/xmake.lua @@ -0,0 +1,60 @@ +add_rules("mode.debug", "mode.release") + +includes("@builtin/xpack") + +add_requires("gtest") + +option("trace") + set_default(false) + set_showmenu(true) + add_defines("DEBUG") + +target("CapnC_Runtime") + set_kind("static") + add_rules("utils.install.pkgconfig_importfiles") + add_files("lib/*.c") + add_headerfiles("lib/capnp_c.h") + add_options("trace") + +target("capnpc-c") + set_kind("binary") + add_files("compiler/*.c") + add_includedirs("lib", "compiler") + add_installfiles("compiler/c.capnp", "compiler/c++.capnp","compiler/schema.capnp",{ prefixdir = "share/schema"}) + add_deps("CapnC_Runtime") + add_options("trace") + +rule("capnproto.c") + set_extensions(".capnp") + on_build_file(function (target, sourcefile,opt) + os.setenv("PATH", string.format("%s:%s", target:targetdir(), os.getenv("PATH"))) + os.runv("capnp", {"compile", "-oc", "-Icompiler", sourcefile}) + end) + + +target("test") + set_kind("binary") + add_packages("gtest") + add_files("tests/*.c", "tests/*.cpp") + add_deps("CapnC_Runtime", "capnpc-c") + add_includedirs("compiler", "lib") + add_options("trace") + +target("book") + set_kind("binary") + set_policy("build.across_targets_in_parallel", false) + add_packages("capnpc-c") + add_rules("capnproto.c") + add_files("examples/book/book.capnp") + add_files("examples/book/*.c") + add_includedirs("compiler","lib","examples/book") + add_deps("CapnC_Runtime", "capnpc-c") + add_cflags("-fsanitize=address") + add_ldflags("-fsanitize=address") + +xpack("capnpc-c") + set_formats("targz") + set_title("c-capnproto") + set_licensefile("COPYING") + add_targets("capnpc-c", "CapnC_Runtime") + diff --git a/src/subprojects/librtti.wrap b/src/subprojects/librtti.wrap new file mode 100644 index 00000000..fd48aec7 --- /dev/null +++ b/src/subprojects/librtti.wrap @@ -0,0 +1,10 @@ +[wrap-git] +directory = librtti +url = ssh://forgejo@gitea.shenrs.eu/rshen/librtti +revision = 2149f778fc5eaf6071ccc934f074c64e3e93ab32 +# All local deltas live in packagefiles/librtti.patch (the src/meson.build +# override registration); there is no patch_directory overlay tree. +diff_files = librtti.patch + +[provide] +dependency_names = librtti, librtti-raw diff --git a/src/subprojects/librtti/.clang-format b/src/subprojects/librtti/.clang-format new file mode 100644 index 00000000..864a38da --- /dev/null +++ b/src/subprojects/librtti/.clang-format @@ -0,0 +1,36 @@ +--- +BasedOnStyle: webkit +ColumnLimit: 80 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: Left +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveShortCaseStatements: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true + AlignCaseColons: true +AlignEscapedNewlines: Right +AlignOperands: AlignAfterOperator +AlignTrailingComments: + Kind: Always + OverEmptyLines: 2 +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: false + +--- diff --git a/src/subprojects/librtti/.gitignore b/src/subprojects/librtti/.gitignore new file mode 100644 index 00000000..2d115069 --- /dev/null +++ b/src/subprojects/librtti/.gitignore @@ -0,0 +1,2 @@ +*~ +result diff --git a/src/subprojects/librtti/LICENSE b/src/subprojects/librtti/LICENSE new file mode 100644 index 00000000..a8a13d0e --- /dev/null +++ b/src/subprojects/librtti/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2025 rshen + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/subprojects/librtti/README.md b/src/subprojects/librtti/README.md new file mode 100644 index 00000000..14ce52dd --- /dev/null +++ b/src/subprojects/librtti/README.md @@ -0,0 +1,3 @@ +# rtti + +runtime type information library for c \ No newline at end of file diff --git a/src/subprojects/librtti/examples/meson.build b/src/subprojects/librtti/examples/meson.build new file mode 100644 index 00000000..87b466de --- /dev/null +++ b/src/subprojects/librtti/examples/meson.build @@ -0,0 +1,18 @@ +# +#app_c_srcs=[ +# 'app.c', +#] +# +#app_srcs= app_c_srcs +# +#incdir = include_directories('../include', '.') +# +#app_deps = [ +# dep_librtti, +#] +# +#app = executable('app', +# app_srcs, +# include_directories: incdir, +# dependencies: app_deps, +# install: true) diff --git a/src/subprojects/librtti/flake.lock b/src/subprojects/librtti/flake.lock new file mode 100644 index 00000000..b73ec8f3 --- /dev/null +++ b/src/subprojects/librtti/flake.lock @@ -0,0 +1,131 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1764950072, + "narHash": "sha256-BmPWzogsG2GsXZtlT+MTcAWeDK5hkbGRZTeZNW42fwA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "f61125a668a320878494449750330ca58b78c557", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1764667669, + "narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "418468ac9527e799809c900eda37cbff999199b6", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "xbuild": "xbuild" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "xbuild": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1769064169, + "narHash": "sha256-Tqb8E8vw6WtP5KPCzwWAVBzMwv+UH0gduR2ZWkkYM9g=", + "owner": "shen390s", + "repo": "my-nix-channel", + "rev": "d6e6711f401446ebfec291ad1a3fbb58fd33720d", + "type": "github" + }, + "original": { + "owner": "shen390s", + "ref": "master", + "repo": "my-nix-channel", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/src/subprojects/librtti/flake.nix b/src/subprojects/librtti/flake.nix new file mode 100644 index 00000000..8d5eb6e6 --- /dev/null +++ b/src/subprojects/librtti/flake.nix @@ -0,0 +1,43 @@ +{ + description = "Flake for librtti"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + xbuild.url = "github:shen390s/my-nix-channel?ref=master"; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + xbuild, + }: + let + supportedSystems = [ "x86_64-linux" ]; + in + flake-utils.lib.eachSystem supportedSystems ( + system: + let + mypkgs = xbuild.packages.${system}; + overlays = [ + (final: prev: mypkgs // prev) + ]; + pkgs = import nixpkgs { inherit overlays system; }; + xpkgs = import ./nixSupport/default.nix { + inherit pkgs; + }; + in + { + packages = { + librtti = xpkgs.librtti; + librtti_debug = xpkgs.librtti_debug; + default = xpkgs.librtti; + }; + devShells.default = pkgs.mkShell { + nativeBuildInputs = xpkgs.librtti.nativeBuildInputs; + }; + } + ); +} diff --git a/src/subprojects/librtti/include/rtti.h b/src/subprojects/librtti/include/rtti.h new file mode 100644 index 00000000..aa937f98 --- /dev/null +++ b/src/subprojects/librtti/include/rtti.h @@ -0,0 +1,7 @@ +#if !defined(_LIBRTTI_RTTI_H_) + +#define _LIBRTTI_RTTI_H_ 1 + +#include "rtti/typeinfo.h" + +#endif diff --git a/src/subprojects/librtti/include/rtti/typeinfo.h b/src/subprojects/librtti/include/rtti/typeinfo.h new file mode 100644 index 00000000..7277b53e --- /dev/null +++ b/src/subprojects/librtti/include/rtti/typeinfo.h @@ -0,0 +1,272 @@ +#if !defined(_RTTI_TYPEINFO_H_) + +#define _RTTI_TYPEINFO_H_ 1 + +#include +#include +#include +#include +#include +#include +#include + +#define RTTI_MAGIC (0x5254544949545452) + +#define var void* + +#define RTTI_SIZE_ROUNDUP(sz) \ + ((((sz + sizeof(void*) - 1)) / (sizeof(void*))) * sizeof(void*)) + +#define RTTI_OBJ_HEADER_SIZE RTTI_SIZE_ROUNDUP(sizeof(meta_obj_t)) + +/** Object format + ** + ** +=====================+===================+===================+ + ** | | | <- public data > | + ** +=====================+===================+===================+ + ** + **/ +#define RTTI_OBJ_TO_DATA(T, obj) ((T*)((obj)->data)) +#define RTTI_DATA_TO_OBJ(v) \ + (((v) == NULL) ? NULL : ((meta_obj_t*)(((char*)v) - RTTI_OBJ_HEADER_SIZE))) +#define RTTI_OBJ_TO_PRIV(obj) ((obj)->privdata) + +#define RTTI_GET_METHOD(result, obj, intf, method) \ + do { \ + typeinfo_t* type_ = NULL; \ + \ + (result) = NULL; \ + \ + if ((obj) == NULL) { \ + break; \ + } \ + \ + type_ = obj->type; \ + if (type_ == NULL) { \ + break; \ + } \ + \ + if (type_->interfaces.intf == NULL) { \ + break; \ + } \ + \ + (result) = type_->interfaces.intf->method; \ + } while (0) + +#define RTTI_OBJ_INVALID(obj) (((obj) == NULL) || ((obj)->magic != RTTI_MAGIC)) + +struct meta_obj_; +struct typeinfo_; + +typedef struct meta_obj_ meta_obj_t; +typedef struct typeinfo_ typeinfo_t; + +/* calculate the size of data */ +typedef size_t (*datasize_fn_t)(va_list); + +typedef void (*destroy_fn_t)(void*); +typedef int (*comp_fn_t)(void*, void*, size_t); + +/* object life cycle */ +typedef int (*obj_init_fn_t)(meta_obj_t*, va_list); +typedef void (*obj_destroy_fn_t)(meta_obj_t*); + +/* lock/unlock */ +enum { + RTTI_LOCK_READ = 0, + RTTI_LOCK_WRITE +}; + +typedef int (*lock_fn_t)(meta_obj_t*, uint64_t); +typedef void (*unlock_fn_t)(meta_obj_t*); + +typedef struct { + lock_fn_t lock; + unlock_fn_t unlock; +} intf_lock_t; + +/* convert to string */ +typedef char* (*to_string_fn_t)(meta_obj_t*, va_list); + +typedef struct { + to_string_fn_t toString; +} intf_tostring_t; + +/* iterator function */ + +#define RTTI_ITER_NO_DATA (0) +#define RTTI_ITER_OK (1) + +typedef struct { + meta_obj_t* obj; + var data; +} iterator_t; + +typedef int (*iter_make_fn_t)(iterator_t*, va_list); +typedef int (*iter_next_fn_t)(iterator_t*, void**); +typedef int (*iter_reset_fn_t)(iterator_t*); +typedef void (*iter_destroy_fn_t)(iterator_t*); + +typedef struct { + iter_make_fn_t make; + iter_next_fn_t next; + iter_reset_fn_t reset; + iter_destroy_fn_t destroy; +} intf_iterator_t; + +/* reference and deref */ +typedef int32_t (*reference_fn_t)(meta_obj_t*); +typedef void (*dereference_fn_t)(meta_obj_t*); + +typedef struct { + reference_fn_t reference; + dereference_fn_t dereference; +} intf_reference_t; + +/* hash */ + +typedef int32_t (*hash_fn_t)(meta_obj_t*); + +typedef struct { + hash_fn_t hash; +} intf_hash_t; + +/* length */ +typedef int64_t (*length_fn_t)(meta_obj_t*); + +typedef struct { + length_fn_t length; +} intf_length_t; + +/* set */ +typedef int (*bit_test_fn_t)(meta_obj_t*, unsigned long); +typedef int (*bit_set_fn_t)(meta_obj_t*, unsigned long); +typedef int (*bit_clr_fn_t)(meta_obj_t*, unsigned long); +typedef int (*bit_clrall_fn_t)(meta_obj_t*); + +typedef struct { + bit_test_fn_t test; + bit_set_fn_t set; + bit_clr_fn_t clr; + bit_clrall_fn_t clrall; +} intf_bitmap_t; + +/* key to val table */ + +typedef int (*key_add_fn_t)(meta_obj_t*, void*, void*); +typedef int (*key_del_fn_t)(meta_obj_t*, void*); +typedef uint64_t (*key_find_fn_t)(meta_obj_t*, void*, void**); + +typedef struct { + key_add_fn_t add_key; + key_del_fn_t del_key; + key_find_fn_t find_key; +} intf_kv_t; + +/* array API */ + +typedef int (*vstore_fn_t)(meta_obj_t*, void*); +typedef int (*vget_fn_t)(meta_obj_t*, int, void**); +typedef int (*vget_vec_fn_t)(meta_obj_t*, int, int*, void**); +typedef int (*vput_fn_t)(meta_obj_t*, int, void*); +typedef int (*vput_vec_fn_t)(meta_obj_t*, int, int*, void**); +typedef int (*vclear_fn_t)(meta_obj_t*, int); +/* COW snapshot support — freeze/thaw for application-level copy-on-write */ +typedef bool (*retain_fn_t)(void*, void*); +typedef int (*vfreeze_fn_t)(meta_obj_t*); +typedef int (*vthaw_fn_t)(meta_obj_t*, retain_fn_t, void*); + +typedef struct { + vstore_fn_t vstore; + vget_fn_t vget; + vget_vec_fn_t vget_vec; + vput_fn_t vput; + vput_vec_fn_t vput_vec; + vclear_fn_t vclear; + vfreeze_fn_t vfreeze; /* NEW — freeze (O(1) ptr swap) */ + vthaw_fn_t vthaw; /* NEW — thaw + merge + GC */ +} intf_varray_t; + +/* attrs API */ +typedef int (*attr_get_fn_t)(meta_obj_t*, void*, void**); +typedef int (*attr_set_fn_t)(meta_obj_t*, void*, void*); + +typedef struct { + attr_get_fn_t get; + attr_set_fn_t set; +} intf_attr_t; + +typedef struct { + intf_lock_t* lock; + intf_tostring_t* toString; + intf_iterator_t* iter; + intf_reference_t* reference; + intf_hash_t* hash; + intf_length_t* length; + intf_bitmap_t* bitmap; + intf_kv_t* kv; + intf_varray_t* varray; + intf_attr_t* attrs; +} interface_table_t; + +struct typeinfo_ { + char* name; + size_t privateSize; + datasize_fn_t dataSize; + obj_init_fn_t init; + obj_destroy_fn_t destroy; + interface_table_t interfaces; +}; + +struct meta_obj_ { + uint64_t magic; + typeinfo_t* type; + void* privdata; + void* data; +}; + +extern var makeInstance(typeinfo_t*, ...); +extern void destroy(var); +extern void destroy_(var, obj_destroy_fn_t); +extern int is_rtti_obj(var); +extern typeinfo_t* typeOf(var); +extern int instanceOf(var, typeinfo_t*); + +extern int lock(var, uint64_t); +extern void unlock(var); + +extern char* toString(var, ...); + +extern int iter_make(iterator_t*, var, ...); +extern int iter_next(iterator_t*, void**); +extern int iter_reset(iterator_t*); +extern void iter_destroy(iterator_t*); + +extern int32_t hash(var); + +extern int64_t length(var); + +extern int32_t reference(var); +extern void dereference(var); + +extern int bit_test(var, unsigned long); +extern int bit_set(var, unsigned long); +extern int bit_clr(var, unsigned long); +extern int bit_clrall(var); + +extern int key_add(var, void*, void*); +extern int key_del(var, void*); +extern int key_find(var, void*, void**); + +extern int vstore(var, void*); +extern int vget(var, int, void**); +extern int vget_vec(var, int, int*, void**); +extern int vput(var, int, void*); +extern int vput_vec(var, int, int*, void**); +extern int vclear(var, int); +extern int vfreeze(var); +extern int vthaw(var, retain_fn_t, void*); + +extern int attr_get(var, void*, void**); +extern int attr_set(var, void*, void*); +#endif diff --git a/src/subprojects/librtti/meson.build b/src/subprojects/librtti/meson.build new file mode 100644 index 00000000..c342434f --- /dev/null +++ b/src/subprojects/librtti/meson.build @@ -0,0 +1,18 @@ +project('librtti', + ['c'], + version: '0.0.2', + meson_version: '>=1.5', + default_options: [ + 'c_std=gnu17']) + +add_project_arguments(['-ggdb', + '-g3', + '-Wno-cpp'], + language: ['c']) + +subdir('src') +if get_option('with_debug') == true + subdir('testsuite') +endif +# subdir('examples') + diff --git a/src/subprojects/librtti/meson.options b/src/subprojects/librtti/meson.options new file mode 100644 index 00000000..b4ff5dd3 --- /dev/null +++ b/src/subprojects/librtti/meson.options @@ -0,0 +1 @@ +option('with_debug', type: 'boolean', value: false, yield: true) diff --git a/src/subprojects/librtti/nixSupport/default.nix b/src/subprojects/librtti/nixSupport/default.nix new file mode 100644 index 00000000..8e8d136a --- /dev/null +++ b/src/subprojects/librtti/nixSupport/default.nix @@ -0,0 +1,20 @@ +{ + pkgs, + ... +}: +let + librtti = pkgs.callPackage ./librtti.nix { + inherit pkgs; + withDebug = false; + withAsan = false; + }; + librtti_debug = pkgs.callPackage ./librtti.nix { + inherit pkgs; + withDebug = true; + withAsan = true; + }; +in +{ + librtti = librtti; + librtti_debug = librtti_debug; +} diff --git a/src/subprojects/librtti/nixSupport/librtti.nix b/src/subprojects/librtti/nixSupport/librtti.nix new file mode 100644 index 00000000..3e108322 --- /dev/null +++ b/src/subprojects/librtti/nixSupport/librtti.nix @@ -0,0 +1,35 @@ +{ + lib, + stdenv, + pkgs, + withDebug ? false, + ... +}: + +stdenv.mkDerivation { + + pname = "rtti"; + version = "0.0.2"; + + src = ./..; + + nativeBuildInputs = with pkgs; [ + meson + ninja + pkg-config + which + unity_test_with_color + ]; + + build-system = [ pkgs.meson ]; + + dontStrip = withDebug; + separateDebugInfo = withDebug; + + impureEnvVars = [ "HOME" ]; + + mesonFlags = [ + (lib.optional withDebug "--buildtype=debug -Db_sanitize=address -Dwith_debug=true ") + # (lib.optional (!with_debug) "-Dbuildtype=release") + ]; +} diff --git a/src/subprojects/librtti/src/attr.c b/src/subprojects/librtti/src/attr.c new file mode 100644 index 00000000..e02d8d09 --- /dev/null +++ b/src/subprojects/librtti/src/attr.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "rtti.h" + +int attr_get(var v, void* attr, void** value) +{ + meta_obj_t* obj = NULL; + attr_get_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, attrs, get); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, attr, value); +} + +int attr_set(var v, void* attr, void* value) +{ + meta_obj_t* obj = NULL; + attr_set_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, attrs, set); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, attr, value); +} diff --git a/src/subprojects/librtti/src/bitmap.c b/src/subprojects/librtti/src/bitmap.c new file mode 100644 index 00000000..93df2594 --- /dev/null +++ b/src/subprojects/librtti/src/bitmap.c @@ -0,0 +1,77 @@ +#include +#include +#include + +#include "rtti.h" + +int bit_test(var v, unsigned long idx) +{ + meta_obj_t* obj = NULL; + bit_test_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, bitmap, test); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, idx); +} + +int bit_set(var v, unsigned long idx) +{ + meta_obj_t* obj = NULL; + bit_set_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, bitmap, set); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, idx); +} + +int bit_clr(var v, unsigned long idx) +{ + meta_obj_t* obj = NULL; + bit_clr_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, bitmap, clr); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, idx); +} + +int bit_clrall(var v) +{ + meta_obj_t* obj = NULL; + bit_clrall_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, bitmap, clrall); + if (method == NULL) { + return -EINVAL; + } + + return method(obj); +} diff --git a/src/subprojects/librtti/src/create.c b/src/subprojects/librtti/src/create.c new file mode 100644 index 00000000..46866bcb --- /dev/null +++ b/src/subprojects/librtti/src/create.c @@ -0,0 +1,120 @@ +#include +#include + +#include "rtti.h" + +static meta_obj_t* objAlloc(typeinfo_t* type, size_t sz) +{ + size_t privateSize = RTTI_SIZE_ROUNDUP(type->privateSize); + size_t headerSize = RTTI_OBJ_HEADER_SIZE; + char* p = NULL; + meta_obj_t* obj = NULL; + size_t total = privateSize + headerSize + sz; + + p = (char*)calloc(1, total); + if (p == NULL) { + return NULL; + } + + obj = (meta_obj_t*)(p + privateSize); + obj->type = type; + obj->magic = RTTI_MAGIC; + obj->privdata = p; + obj->data = (void*)(p + privateSize + headerSize); + + return obj; +} + +var makeInstance(typeinfo_t* type, ...) +{ + va_list ap; + va_list ap1; + meta_obj_t* obj; + int rc = 0; + + if ((type == NULL) || (type->init == NULL) || (type->dataSize == NULL)) { + errno = EINVAL; + return NULL; + } + + va_start(ap, type); + va_copy(ap1, ap); + obj = objAlloc(type, type->dataSize(ap1)); + va_end(ap1); + + if (obj == NULL) { + va_end(ap); + return NULL; + } + + rc = type->init(obj, ap); + + va_end(ap); + + if (rc < 0) { + destroy(RTTI_OBJ_TO_DATA(void, obj)); + return NULL; + } + + return obj->data; +} + +static void objDestroy_(meta_obj_t* obj, obj_destroy_fn_t killer) +{ + void* p = NULL; + + if (killer != NULL) { + killer(obj); + } + + p = RTTI_OBJ_TO_PRIV(obj); + free(p); +} + +void destroy_(var v, obj_destroy_fn_t killer) +{ + meta_obj_t* obj = RTTI_DATA_TO_OBJ(v); + + if (RTTI_OBJ_INVALID(obj)) { + return; + } + + objDestroy_(obj, killer); +} + +void destroy(var v) +{ + typeinfo_t* type = NULL; + meta_obj_t* obj = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return; + } + + type = obj->type; + if (type == NULL) { + return; + } + + objDestroy_(obj, type->destroy); + + return; +} + +/* disable address sanitize as it's a possible case that calculated address of + * obj may not be valid */ +#if defined(__GNUC__) +__attribute__((no_sanitize("address"))) +#endif +int is_rtti_obj(var v) +{ + meta_obj_t* obj = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return 0; + } + + return 1; +} diff --git a/src/subprojects/librtti/src/hash.c b/src/subprojects/librtti/src/hash.c new file mode 100644 index 00000000..57c83730 --- /dev/null +++ b/src/subprojects/librtti/src/hash.c @@ -0,0 +1,22 @@ +#include +#include +#include + +#include "rtti.h" + +int32_t hash(var v) { + meta_obj_t* obj = NULL; + hash_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, hash, hash); + if (method == NULL) { + return -EINVAL; + } + + return method(obj); +} diff --git a/src/subprojects/librtti/src/iter.c b/src/subprojects/librtti/src/iter.c new file mode 100644 index 00000000..b39bfb63 --- /dev/null +++ b/src/subprojects/librtti/src/iter.c @@ -0,0 +1,98 @@ +#include +#include +#include + +#include "rtti.h" + +int iter_make(iterator_t* it, var v, ...) +{ + meta_obj_t* obj = NULL; + iter_make_fn_t method = NULL; + va_list ap; + int rc = 0; + + if (it == NULL) { + return -EINVAL; + } + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, iter, make); + if (method == NULL) { + return -EINVAL; + } + + va_start(ap, v); + memset(it, 0x0, sizeof(*it)); + it->obj = obj; + + rc = method(it, ap); + va_end(ap); + + return rc; +} + +int iter_next(iterator_t* it, void** data) +{ + iter_next_fn_t method = NULL; + + if ((it == NULL) || (data == NULL)) { + return -EINVAL; + } + + if (RTTI_OBJ_INVALID(it->obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, it->obj, iter, next); + if (method == NULL) { + return -EINVAL; + } + + return method(it, data); +} + +int iter_reset(iterator_t* it) +{ + iter_reset_fn_t method = NULL; + + if (it == NULL) { + return -EINVAL; + } + + if (RTTI_OBJ_INVALID(it->obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, it->obj, iter, reset); + if (method == NULL) { + return -EINVAL; + } + + return method(it); +} + +void iter_destroy(iterator_t* it) +{ + iter_destroy_fn_t method = NULL; + + if (it == NULL) { + return; + } + + if (RTTI_OBJ_INVALID(it->obj)) { + return; + } + + RTTI_GET_METHOD(method, it->obj, iter, destroy); + if (method == NULL) { + return; + } + + method(it); + + return; +} diff --git a/src/subprojects/librtti/src/kv.c b/src/subprojects/librtti/src/kv.c new file mode 100644 index 00000000..a14eb8aa --- /dev/null +++ b/src/subprojects/librtti/src/kv.c @@ -0,0 +1,59 @@ +#include +#include +#include + +#include "rtti.h" + +int key_add(var v, void* key, void* value) +{ + meta_obj_t* obj = NULL; + key_add_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, kv, add_key); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, key, value); +} + +int key_del(var v, void* key) +{ + meta_obj_t* obj = NULL; + key_del_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, kv, del_key); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, key); +} + +int key_find(var v, void* key, void** value) +{ + meta_obj_t* obj = NULL; + key_find_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, kv, find_key); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, key, value); +} diff --git a/src/subprojects/librtti/src/length.c b/src/subprojects/librtti/src/length.c new file mode 100644 index 00000000..fed03cc9 --- /dev/null +++ b/src/subprojects/librtti/src/length.c @@ -0,0 +1,23 @@ +#include +#include +#include + +#include "rtti.h" + +int64_t length(var v) +{ + meta_obj_t* obj = NULL; + length_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, length, length); + if (method == NULL) { + return -EINVAL; + } + + return method(obj); +} diff --git a/src/subprojects/librtti/src/lock.c b/src/subprojects/librtti/src/lock.c new file mode 100644 index 00000000..5469cd44 --- /dev/null +++ b/src/subprojects/librtti/src/lock.c @@ -0,0 +1,42 @@ +#include +#include + +#include "rtti.h" + +int lock(var v, uint64_t option) +{ + meta_obj_t* obj = NULL; + lock_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, lock, lock); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, option); +} + +void unlock(var v) +{ + meta_obj_t* obj = NULL; + unlock_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return; + } + + RTTI_GET_METHOD(method, obj, lock, unlock); + if (method == NULL) { + return; + } + + method(obj); + + return; +} diff --git a/src/subprojects/librtti/src/meson.build b/src/subprojects/librtti/src/meson.build new file mode 100644 index 00000000..d847fc36 --- /dev/null +++ b/src/subprojects/librtti/src/meson.build @@ -0,0 +1,68 @@ +pkg = import('pkgconfig') + +librtti_c_srcs=[ + 'create.c', + 'typeinfo.c', + 'lock.c', + 'iter.c', + 'ref.c', + 'str.c', + 'hash.c', + 'length.c', + 'bitmap.c', + 'kv.c', + 'varray.c', + 'attr.c', +] + + +librtti_srcs= librtti_c_srcs + +incdir = include_directories('../include', '.') + +rtti_top_headers = [ + '../include/rtti.h', +] + +rtti_headers = [ + '../include/rtti/typeinfo.h', +] + +librtti_deps = [ +] + +librtti = static_library('librtti', + librtti_srcs, + include_directories: incdir, + dependencies: librtti_deps, + install: true) + +install_headers(rtti_top_headers, install_dir: 'include') +install_headers(rtti_headers, install_dir: 'include/rtti') + +dep_librtti = declare_dependency(link_with: librtti) + +pkg.generate(librtti, + name: 'librtti', + description: 'runtime type information library for c', + version: '0.0.2') + +# Register the fallback the parent resolves through this wrap's [provide] +# section: dependency('librtti'). Headers live under ../include/ and +# ../include/rtti/ in-tree (same layout the nix pc's -I${includedir} +# provided); paths are relative to src/ where this meson.build lives. +librtti_sdep = declare_dependency( + link_with: librtti, + include_directories: include_directories('../include'), + version: '0.0.2') +meson.override_dependency('librtti', librtti_sdep) + +# Raw flags for non-meson consumers (frontend/apiserver CGO): the static +# archive lands in this subproject's build dir under src/. Header root is +# the repo-level include/ -- current_source_dir() here is src/. +librtti_raw = declare_dependency( + variables: { + 'cflags': '-I' + meson.current_source_dir() / '..' / 'include', + 'ldflags': '-L' + meson.current_build_dir() + ' -llibrtti', + }) +meson.override_dependency('librtti-raw', librtti_raw) diff --git a/src/subprojects/librtti/src/ref.c b/src/subprojects/librtti/src/ref.c new file mode 100644 index 00000000..d0f03db1 --- /dev/null +++ b/src/subprojects/librtti/src/ref.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "rtti.h" + +int32_t reference(var v) +{ + meta_obj_t* obj = NULL; + reference_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, reference, reference); + if (method == NULL) { + return -EINVAL; + } + + return method(obj); +} + +void dereference(var v) +{ + meta_obj_t* obj = NULL; + dereference_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return; + } + + RTTI_GET_METHOD(method, obj, reference, dereference); + if (method != NULL) { + method(obj); + } + + return; +} diff --git a/src/subprojects/librtti/src/str.c b/src/subprojects/librtti/src/str.c new file mode 100644 index 00000000..d48ad514 --- /dev/null +++ b/src/subprojects/librtti/src/str.c @@ -0,0 +1,30 @@ +#include +#include + +#include "rtti.h" + +char* toString(var v, ...) +{ + meta_obj_t* obj = NULL; + to_string_fn_t method = NULL; + va_list ap; + char* s = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + errno = EINVAL; + return NULL; + } + + RTTI_GET_METHOD(method, obj, toString, toString); + if (method == NULL) { + errno = EINVAL; + return NULL; + } + + va_start(ap, v); + s = method(obj, ap); + va_end(ap); + + return s; +} diff --git a/src/subprojects/librtti/src/typeinfo.c b/src/subprojects/librtti/src/typeinfo.c new file mode 100644 index 00000000..a551039b --- /dev/null +++ b/src/subprojects/librtti/src/typeinfo.c @@ -0,0 +1,27 @@ +#include +#include + +#include "rtti.h" + +typeinfo_t *typeOf(var v) { + meta_obj_t *obj = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return NULL; + } + + return obj->type; +} + +int instanceOf(var v, typeinfo_t *t) { + if ((v == NULL) || (t == NULL)) { + return -EINVAL; + } + + if (typeOf(v) == t) { + return 1; + } + + return 0; +} diff --git a/src/subprojects/librtti/src/varray.c b/src/subprojects/librtti/src/varray.c new file mode 100644 index 00000000..907035dc --- /dev/null +++ b/src/subprojects/librtti/src/varray.c @@ -0,0 +1,168 @@ +#include +#include + +#include "rtti.h" + +int vstore(var v, void* data) +{ + meta_obj_t* obj = NULL; + vstore_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, varray, vstore); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, data); +} + +int vget(var v, int idx, void** data) +{ + meta_obj_t* obj = NULL; + vget_fn_t method = NULL; + + if ((idx < 0) || (data == NULL)) { + return -EINVAL; + } + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, varray, vget); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, idx, data); +} + +int vput(var v, int idx, void* data) +{ + meta_obj_t* obj = NULL; + vput_fn_t method = NULL; + + if (idx < 0) { + return -EINVAL; + } + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, varray, vput); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, idx, data); +} + +int vget_vec(var v, int count, int* idxs, void** data) +{ + meta_obj_t* obj = NULL; + vget_vec_fn_t method = NULL; + + if ((count < 1) || (idxs == NULL) || (data == NULL)) { + return -EINVAL; + } + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, varray, vget_vec); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, count, idxs, data); +} + +int vput_vec(var v, int count, int* idxs, void** data) +{ + meta_obj_t* obj = NULL; + vput_vec_fn_t method = NULL; + + if ((count < 1) || (idxs == NULL) || (data == NULL)) { + return -EINVAL; + } + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, varray, vput_vec); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, count, idxs, data); +} + +int vclear(var v, int idx) +{ + meta_obj_t* obj = NULL; + vclear_fn_t method = NULL; + + if (idx < 0) { + return -EINVAL; + } + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, varray, vclear); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, idx); +} + +int vfreeze(var v) +{ + meta_obj_t* obj = NULL; + vfreeze_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, varray, vfreeze); + if (method == NULL) { + return -EINVAL; + } + + return method(obj); +} + +int vthaw(var v, retain_fn_t fn, void* arg) +{ + meta_obj_t* obj = NULL; + vthaw_fn_t method = NULL; + + obj = RTTI_DATA_TO_OBJ(v); + if (RTTI_OBJ_INVALID(obj)) { + return -EINVAL; + } + + RTTI_GET_METHOD(method, obj, varray, vthaw); + if (method == NULL) { + return -EINVAL; + } + + return method(obj, fn, arg); +} diff --git a/src/subprojects/librtti/testsuite/meson.build b/src/subprojects/librtti/testsuite/meson.build new file mode 100644 index 00000000..4c018f86 --- /dev/null +++ b/src/subprojects/librtti/testsuite/meson.build @@ -0,0 +1,15 @@ +librtti_test_srcs = [ + 'test.c', + 'test_iter.c', + 'test_invalid_obj.c', + 'test_attr.c', +] + +unity_dep = dependency('unity') +librtti_test_deps = [dep_librtti, unity_dep] + +librtti_test = executable('rtti_test', + librtti_test_srcs, + include_directories: [incdir], + dependencies: librtti_test_deps, + install: true) diff --git a/src/subprojects/librtti/testsuite/test.c b/src/subprojects/librtti/testsuite/test.c new file mode 100644 index 00000000..0a29d8f6 --- /dev/null +++ b/src/subprojects/librtti/testsuite/test.c @@ -0,0 +1,34 @@ +#include +#include + +#include + +void setUp(void) +{ + return; +} + +void tearDown(void) +{ + printf(">>"); + return; +} + +extern void test_type(void); +extern void test_iter(void); +extern void test_invalid(void); +extern void test_attr(void); + +#define TEST(x) x() + +int main(int argc, char* argv[]) +{ + UNITY_BEGIN(); + + TEST(test_type); + TEST(test_iter); + TEST(test_invalid); + TEST(test_attr); + + return UNITY_END(); +} diff --git a/src/subprojects/librtti/testsuite/test_attr.c b/src/subprojects/librtti/testsuite/test_attr.c new file mode 100644 index 00000000..4ccb6c48 --- /dev/null +++ b/src/subprojects/librtti/testsuite/test_attr.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include + +#include "rtti.h" + +#define ATTR_ID (0) +#define ATTR_NAME (1) + +typedef struct { + int id; + char* name; +} my_attrset_t; + +static int my_attrset_init(meta_obj_t* obj, va_list ap) +{ + my_attrset_t* attrs = RTTI_OBJ_TO_DATA(my_attrset_t, obj); + + attrs->id = -1; + attrs->name = NULL; + + return 1; +} + +static void my_attrset_destroy(meta_obj_t* obj) +{ + /* do nothing */ + return; +} + +static int my_attrset_get(meta_obj_t* obj, void* attr, void** value) +{ + my_attrset_t* attrs = RTTI_OBJ_TO_DATA(my_attrset_t, obj); + + switch ((int)(long)attr) { + case ATTR_ID: + *value = (void*)(long)attrs->id; + break; + case ATTR_NAME: + *value = (void*)attrs->name; + break; + default: + return -EINVAL; + } + + return 1; +} + +static int my_attrset_set(meta_obj_t* obj, void* attr, void* value) +{ + my_attrset_t* attrs = RTTI_OBJ_TO_DATA(my_attrset_t, obj); + + switch ((int)(long)attr) { + case ATTR_ID: + attrs->id = (int)(long)value; + break; + case ATTR_NAME: + attrs->name = (char*)value; + break; + default: + return -EINVAL; + } + + return 1; +} + +static size_t my_attrset_datasize(va_list ap) +{ + size_t sz = sizeof(my_attrset_t); + + return sz; +} + +static typeinfo_t my_attrset_type + = { .name = "my_attrset", + .privateSize = 0, + .dataSize = (datasize_fn_t)my_attrset_datasize, + .init = (obj_init_fn_t)my_attrset_init, + .destroy = (obj_destroy_fn_t)my_attrset_destroy, + .interfaces = { .attrs = &(intf_attr_t) { + .get = (attr_get_fn_t)my_attrset_get, + .set = (attr_set_fn_t)my_attrset_set } } }; + +static void test_attr_setget(void) +{ + var attrs = makeInstance(&my_attrset_type); + void* id; + char* name; + int rc = 0; + + TEST_ASSERT_TRUE(attrs != NULL); + + rc = attr_set(attrs, (void*)(long)ATTR_ID, (void *)(long)1); + + TEST_ASSERT_TRUE(rc >= 0); + + rc = attr_set(attrs, (void*)(long)ATTR_NAME, "tester"); + TEST_ASSERT_TRUE(rc >= 0); + + rc = attr_get(attrs, (void*)(long)ATTR_ID, &id); + TEST_ASSERT_TRUE(rc >= 0); + + TEST_ASSERT_TRUE((int)(long)id == 1); + + rc = attr_get(attrs, (void*)(long)ATTR_NAME, (void**)&name); + TEST_ASSERT_TRUE(rc >= 0); + + TEST_ASSERT_TRUE((strcmp(name, "tester") == 0)); + + destroy(attrs); +} + +void test_attr(void) +{ + printf("\n attr test\n\n"); + + RUN_TEST(test_attr_setget); +} diff --git a/src/subprojects/librtti/testsuite/test_invalid_obj.c b/src/subprojects/librtti/testsuite/test_invalid_obj.c new file mode 100644 index 00000000..a71d0f8d --- /dev/null +++ b/src/subprojects/librtti/testsuite/test_invalid_obj.c @@ -0,0 +1,26 @@ +#include +#include +#include + +#include "rtti.h" + +static void test_c_str_invalid(void) +{ + char* hello = "Hello, world"; + + TEST_ASSERT_TRUE(is_rtti_obj(hello) == 0); +} + +static void test_intptr_invalid(void) { + int x = 20; + + TEST_ASSERT_TRUE(is_rtti_obj(&x) == 0); +} + +void test_invalid(void) +{ + printf("\n invalid object\n\n"); + + RUN_TEST(test_c_str_invalid); + RUN_TEST(test_intptr_invalid); +} diff --git a/src/subprojects/librtti/testsuite/test_iter.c b/src/subprojects/librtti/testsuite/test_iter.c new file mode 100644 index 00000000..4867b824 --- /dev/null +++ b/src/subprojects/librtti/testsuite/test_iter.c @@ -0,0 +1,176 @@ +#include +#include +#include + +#include "rtti.h" + +typedef struct { + int count; + int* data; +} myArray_t; + +static size_t my_array_datasize(va_list ap) { return sizeof(myArray_t); } + +static int my_array_init(meta_obj_t* obj, va_list ap) +{ + myArray_t* a = RTTI_OBJ_TO_DATA(myArray_t, obj); + int count; + int i; + + count = va_arg(ap, int); + if (count <= 0) { + return -EINVAL; + } + + a->data = (int*)calloc(count, sizeof(int)); + if (a->data == NULL) { + return -ENOMEM; + } + + a->count = count; + for (i = 0; i < count; i++) { + a->data[i] = va_arg(ap, int); + } + + return 1; +} + +static void my_array_destroy(meta_obj_t* obj) +{ + myArray_t* a = RTTI_OBJ_TO_DATA(myArray_t, obj); + if (a->data != NULL) { + free(a->data); + a->data = NULL; + } +} + +static int my_array_make_iter(iterator_t* iter, va_list ap) +{ + iter->data = (void*)(long)0; + + return RTTI_ITER_OK; +} + +static int my_array_iter_next(iterator_t* iter, void** data) +{ + myArray_t* a = RTTI_OBJ_TO_DATA(myArray_t, iter->obj); + int idx = (int)(long)iter->data; + + if (idx >= a->count) { + /* no data */ + return RTTI_ITER_NO_DATA; + } + + *data = (void*)(long)a->data[idx]; + iter->data = (void*)(long)(idx + 1); + + return RTTI_ITER_OK; +} + +static int my_array_iter_reset(iterator_t* iter) +{ + iter->data = (void*)(long)0; + + return RTTI_ITER_OK; +} + +static void my_array_iter_destroy(iterator_t* iter) { return; } + +static typeinfo_t myintArray + = { .name = "myintArray", + .privateSize = 0, + .dataSize = (datasize_fn_t)my_array_datasize, + .init = (obj_init_fn_t)my_array_init, + .destroy = (obj_destroy_fn_t)my_array_destroy, + .interfaces + = { .iter = &(intf_iterator_t) { + .make = (iter_make_fn_t)my_array_make_iter, + .next = (iter_next_fn_t)my_array_iter_next, + .reset = (iter_reset_fn_t)my_array_iter_reset, + .destroy = (iter_destroy_fn_t)my_array_iter_destroy } } }; + +static void test_typeof(void) +{ + var array = makeInstance(&myintArray, 5, 0, 1, 2, 3, 4); + int rc; + typeinfo_t* t = NULL; + + t = typeOf(array); + TEST_ASSERT_TRUE(t == &myintArray); + + rc = instanceOf(array, &myintArray); + TEST_ASSERT_TRUE(rc == 1); + + destroy(array); +} + +static void test_array_iter(void) +{ + var array = makeInstance(&myintArray, 5, 0, 1, 2, 3, 4); + iterator_t it; + int rc, sum; + void* data; + + TEST_ASSERT_TRUE(array != NULL); + TEST_ASSERT_TRUE(is_rtti_obj(array) == 1); + rc = iter_make(&it, array); + TEST_ASSERT_TRUE(rc == 1); + + rc = iter_next(&it, (void**)&data); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE((int)(long)data == 0); + + rc = iter_next(&it, (void**)&data); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE((int)(long)data == 1); + + rc = iter_next(&it, (void**)&data); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE((int)(long)data == 2); + + rc = iter_next(&it, (void**)&data); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE((int)(long)data == 3); + + rc = iter_next(&it, (void**)&data); + TEST_ASSERT_TRUE(rc >= 0); + TEST_ASSERT_TRUE((int)(long)data == 4); + + rc = iter_next(&it, (void**)&data); + TEST_ASSERT_TRUE(rc == RTTI_ITER_NO_DATA); + + sum = 0; + rc = iter_reset(&it); + TEST_ASSERT_TRUE(rc >= 0); + + for (;;) { + rc = iter_next(&it, &data); + TEST_ASSERT_TRUE(rc >= 0); + if (rc == RTTI_ITER_NO_DATA) { + break; + } + + sum += (int)(long)data; + } + + TEST_ASSERT_TRUE(sum == 10); + + iter_destroy(&it); + + destroy(array); + + return; +} + +void test_type(void) { + printf("\n type info test\n\n"); + + RUN_TEST(test_typeof); +} + +void test_iter(void) +{ + printf("\n iterator test\n\n"); + + RUN_TEST(test_array_iter); +} diff --git a/src/subprojects/packagefiles/c-capnproto.patch b/src/subprojects/packagefiles/c-capnproto.patch new file mode 100644 index 00000000..3ca536a8 --- /dev/null +++ b/src/subprojects/packagefiles/c-capnproto.patch @@ -0,0 +1,39 @@ +# c-capnproto (shen390s fork of capnproto/c-capnproto) has a meson.build but +# it neither installs the library/headers nor installs the capnpc-c codegen +# binary -- the nix packaging (xbuild's capnpc package) built it with CMake +# (CMakeLists.txt) and hand-wrote c-capnproto.pc (Libs: -lCapnC_Runtime, +# Cflags: -I, codegen=${bindir}/capnpc-c). The XCE build consumes +# exactly those three things via pkg-config ('c-capnproto' dep) + +# find_program('capnpc-c'). This patch adds install:true and a pkgconfig +# module to the existing meson.build, keeping the upstream lib/executable +# targets untouched. +# +# It also registers the dependency/program overrides the parent resolves +# through this wrap's [provide] section, plus a 'c-capnproto-raw' override +# carrying the nix pc's flags as raw strings for frontend/apiserver's CGO +# flag extraction (dep.get_variable(); Go's cgo cannot consume meson +# dependency objects). +# +# Note: upstream CMake names the library CapnC_Runtime; the meson.build here +# names it 'capnp'. The nix .pc pointed -lCapnC_Runtime at a CMake-built +# lib. To keep link flags identical to the nix layout (and any code pinning +# -lCapnC_Runtime), the meson library is renamed CapnC_Runtime here. + +diff --git a/compiler/capnpc-c.c b/compiler/capnpc-c.c +index 6e95212..d72bc9a 100644 +--- a/compiler/capnpc-c.c ++++ b/compiler/capnpc-c.c +@@ -2334,6 +2334,13 @@ static void define_struct(capnp_ctx_t *ctx, struct node *n, const char *extattr, + &(ctx->SRC), + "\nvoid encode_%s(struct capn_segment *cs,struct %s *d, %s *s) {\n", + n->name.str, n->name.str, buf); ++ /* Zero the destination first: encode_member skips fields the codec has ++ * no mapping for (Data fields land as a bare comment), while write_X ++ * unconditionally reads every member. Without this, d is a caller's ++ * uninitialized stack local and those skipped members feed garbage ++ * (e.g. a wild capn_ptr.seg) straight into capn_setp -- a SIGSEGV that ++ * only shows up when the stack layout changes. */ ++ str_addf(&(ctx->SRC), "\tmemset(d, 0, sizeof(*d));\n"); + str_addf(&(ctx->SRC), "%s\n", s.encoder.str); + str_addf(&(ctx->SRC), "}\n"); + str_addf(&(ctx->SRC), "\nvoid decode_%s(%s *d, struct %s *s) {\n", diff --git a/src/subprojects/packagefiles/c-capnproto/meson.build b/src/subprojects/packagefiles/c-capnproto/meson.build new file mode 100644 index 00000000..e6d7ed5f --- /dev/null +++ b/src/subprojects/packagefiles/c-capnproto/meson.build @@ -0,0 +1,130 @@ +project('capnp-c', ['c','cpp'], meson_version: '>=1.0.0', default_options : ['c_std=c99', 'cpp_std=c++14']) + +pkg = import('pkgconfig') +cc = meson.get_compiler('c') + +common_c_args = [] +common_cpp_args = ['-std=c++14'] +libcapnp_c_args = [] +libcapnp_src = [ + 'lib' / 'capn-malloc.c', + 'lib' / 'capn-stream.c', + 'lib' / 'capn.c', +] + +libcapnp = library('capnp', libcapnp_src, + c_args : common_c_args + libcapnp_c_args, + dependencies: [], + implicit_include_directories: false, + include_directories: include_directories(['compiler', 'lib']) +) + +libcapnp_dep = declare_dependency( + link_with: libcapnp, + dependencies: [], + include_directories: include_directories(['compiler', 'lib']) +) + +capnpc_src = [ + 'compiler' / 'capnpc-c.c', + 'compiler' / 'schema.capnp.c', + 'compiler' / 'str.c' +] + +capnpc_c = executable('capnpc-c', capnpc_src, + include_directories: include_directories(['lib']), + dependencies: [libcapnp_dep], + c_args : common_c_args, +) + +capnp_install_lib = static_library('CapnC_Runtime', + ['lib' / 'capn-malloc.c', + 'lib' / 'capn-stream.c', + 'lib' / 'capn.c'], + include_directories: include_directories(['compiler', 'lib']), + dependencies: [], + implicit_include_directories: false, + install: true, +) + +install_headers(['lib' / 'capnp_c.h']) + +capnpc_c_install = executable('capnpc-c-install', + ['compiler' / 'capnpc-c.c', + 'compiler' / 'schema.capnp.c', + 'compiler' / 'str.c'], + include_directories: include_directories(['lib']), + link_with: capnp_install_lib, + c_args : common_c_args, + install: true) + +meson.add_install_script('sh', '-c', + 'mv "$MESON_INSTALL_DESTDIR_PREFIX/bin/capnpc-c-install" "$MESON_INSTALL_DESTDIR_PREFIX/bin/capnpc-c"') + +pkg.generate(capnp_install_lib, + name: 'c-capnproto', + description: 'Cap\'n Proto C bindings', + version: '1.0.1') + +# Register the fallbacks the parent resolves through this wrap's [provide] +# section: dependency('c-capnproto') and find_program('capnpc-c'). Without +# these the subproject builds but the parent lookup fails ("did not override +# ... dependency"). +capnp_c_dep = declare_dependency( + link_with: capnp_install_lib, + include_directories: include_directories('lib'), + version: '1.0.1') +meson.override_dependency('c-capnproto', capnp_c_dep) +meson.override_find_program('capnpc-c', capnpc_c) + +# Raw flags for non-meson consumers (frontend/apiserver reads them via +# dep.get_variable() to fill CGO_CFLAGS/CGO_LDFLAGS -- Go's cgo cannot +# consume meson dependency objects). Mirrors the nix c-capnproto.pc +# (Libs: -L${libdir} -lCapnC_Runtime, Cflags: -I${includedir}); the archive +# lands in this subproject's build-dir root. +capnp_c_raw = declare_dependency( + variables: { + 'cflags': '-I' + meson.current_source_dir() / 'lib', + 'ldflags': '-L' + meson.current_build_dir() + ' -lCapnC_Runtime', + }) +meson.override_dependency('c-capnproto-raw', capnp_c_raw) + +capn_test_src = [ + 'tests' / 'capn-test.cpp', + 'tests' / 'capn-stream-test.cpp', + 'tests' / 'example-test.cpp', + 'tests' / 'addressbook.capnp.c', + 'compiler' / 'test.capnp.c', + 'compiler' / 'schema-test.cpp', + 'compiler' / 'schema.capnp.c' +] + +if get_option('enable_tests') and not meson.is_subproject() + + thread_dep = dependency('threads') + + gtest_proj = subproject('gtest') + gtest_dep = gtest_proj.get_variable('gtest_dep') + gmock_dep = gtest_proj.get_variable('gmock_dep') + + test_dependencies = [libcapnp_dep, gtest_dep, gmock_dep, thread_dep] + + if get_option('b_sanitize').contains('address') + test_dependencies += cc.find_library('asan') + endif + if get_option('b_sanitize').contains('undefined') + test_dependencies += cc.find_library('ubsan') + endif + + exe = executable('capn-test', capn_test_src, + include_directories: include_directories(['lib', 'tests', 'compiler']), + dependencies: test_dependencies, + c_args : common_c_args, + cpp_args : common_cpp_args, + install: false, + install_rpath: '', + implicit_include_directories: false + ) + test('capn-test', exe) + +endif diff --git a/src/subprojects/packagefiles/librtti.patch b/src/subprojects/packagefiles/librtti.patch new file mode 100644 index 00000000..a1965135 --- /dev/null +++ b/src/subprojects/packagefiles/librtti.patch @@ -0,0 +1,39 @@ +# librtti upstream (gitea rshen/librtti) has a meson.build that declares the +# library + pkg.generate(), but never registers the dependency override, so +# the parent project's dependency('librtti') fallback fails ("Subproject +# 'librtti' did not override 'librtti' dependency"). Consumers include +# and ; the nix librtti.pc exposed +# Cflags: -I${includedir} with headers under include/ and include/rtti/. +# This patch appends the override to the existing src/meson.build. +# +# A second override ('librtti-raw') carries the same flags the nix pc file +# exposed as raw compiler/linker strings (-I/-L/-l) for non-meson consumers +# -- frontend/apiserver reads them via dep.get_variable() to fill CGO flags +# (Go's cgo cannot consume meson dependency objects). +diff -ruN a/src/meson.build b/src/meson.build +--- a/src/meson.build ++++ b/src/meson.build +@@ -46,3 +46,23 @@ + name: 'librtti', + description: 'runtime type information library for c', + version: '0.0.2') ++ ++# Register the fallback the parent resolves through this wrap's [provide] ++# section: dependency('librtti'). Headers live under ../include/ and ++# ../include/rtti/ in-tree (same layout the nix pc's -I${includedir} ++# provided); paths are relative to src/ where this meson.build lives. ++librtti_sdep = declare_dependency( ++ link_with: librtti, ++ include_directories: include_directories('../include'), ++ version: '0.0.2') ++meson.override_dependency('librtti', librtti_sdep) ++ ++# Raw flags for non-meson consumers (frontend/apiserver CGO): the static ++# archive lands in this subproject's build dir under src/. Header root is ++# the repo-level include/ -- current_source_dir() here is src/. ++librtti_raw = declare_dependency( ++ variables: { ++ 'cflags': '-I' + meson.current_source_dir() / '..' / 'include', ++ 'ldflags': '-L' + meson.current_build_dir() + ' -llibrtti', ++ }) ++meson.override_dependency('librtti-raw', librtti_raw) diff --git a/src/subprojects/packagefiles/packcc/meson.build b/src/subprojects/packagefiles/packcc/meson.build new file mode 100644 index 00000000..54617322 --- /dev/null +++ b/src/subprojects/packagefiles/packcc/meson.build @@ -0,0 +1,15 @@ +project('packcc', + ['c'], + version: '2.2.0', + meson_version: '>=1.0', + default_options: ['c_std=gnu89', 'optimization=2']) + +packcc_exe = executable('packcc', 'src/packcc.c', + c_args: ['-fsigned-char', '-Wall', '-Wextra', + '-Wno-unused-parameter', '-Wno-overlength-strings', + '-pedantic'], + install: not meson.is_subproject()) + +# Register the fallback the parent resolves through this wrap's [provide] +# section: find_program('packcc'). +meson.override_find_program('packcc', packcc_exe) diff --git a/src/subprojects/packagefiles/struct2json.patch b/src/subprojects/packagefiles/struct2json.patch new file mode 100644 index 00000000..30c18026 --- /dev/null +++ b/src/subprojects/packagefiles/struct2json.patch @@ -0,0 +1,33 @@ +# struct2json upstream (github.com/shen390s/struct2json) has a meson.build, +# but it only declares targets and pkg.generate() -- it never registers the +# dependency override, so the parent project's dependency('struct2json') +# fallback fails ("Subproject 'struct2json' did not override 'struct2json' +# dependency"). +# +# Include layout: XCE consumers use / +# (lowercase dir), which is what the nix struct2json.pc provided (Cflags: +# -I${includedir}, headers under include/cjson/). The upstream tree has +# cJSON/ (mixed case) and struct2json/inc/. The lowercase include path is +# provided by forwarding shims under cjson/ (shipped alongside this patch in +# packagefiles/struct2json/cjson/), and the override carries the include +# dirs both the shims and the library's own quoted includes need. +diff -ruN a/meson.build b/meson.build +--- a/meson.build ++++ b/meson.build +@@ -42,3 +42,16 @@ + name:'struct2json', + description: 'struct to json', + version:'1.0.0') ++ ++# Register the fallback the parent resolves through this wrap's [provide] ++# section: dependency('struct2json'). Includes: '.' exposes the cjson/ ++# forwarding shims ( etc.); 'cJSON' and 'struct2json/inc' ++# keep the library headers' own quoted includes resolving, exactly like the ++# upstream incdir. ++struct2json_sdep = declare_dependency( ++ link_with: libstruct2json, ++ include_directories: [include_directories('.'), ++ include_directories('cJSON'), ++ include_directories('struct2json/inc')], ++ version: '1.0.0') ++meson.override_dependency('struct2json', struct2json_sdep) diff --git a/src/subprojects/packagefiles/struct2json/cjson/cJSON.h b/src/subprojects/packagefiles/struct2json/cjson/cJSON.h new file mode 100644 index 00000000..3738b012 --- /dev/null +++ b/src/subprojects/packagefiles/struct2json/cjson/cJSON.h @@ -0,0 +1,13 @@ +/* + * Lowercase-include shim for the meson wrap build of struct2json. + * + * XCE consumers include (the layout the nix packaging + * provided: headers installed under include/cjson/), but the upstream tree + * keeps cJSON.h under cJSON/ (mixed case). This shim forwards to the real + * header so the wrap path needs no build-time header synthesis. The nix + * packaging never enters this path (it installs the real headers). + */ +#ifndef CJSON_SHIM_CJSON_H +#define CJSON_SHIM_CJSON_H +#include "../cJSON/cJSON.h" +#endif /* CJSON_SHIM_CJSON_H */ diff --git a/src/subprojects/packagefiles/struct2json/cjson/s2j.h b/src/subprojects/packagefiles/struct2json/cjson/s2j.h new file mode 100644 index 00000000..7e2288d0 --- /dev/null +++ b/src/subprojects/packagefiles/struct2json/cjson/s2j.h @@ -0,0 +1,9 @@ +/* + * Lowercase-include shim for the meson wrap build of struct2json. + * Forwards to the real header under struct2json/inc/. + * See cjson/cJSON.h shim for rationale. + */ +#ifndef CJSON_SHIM_S2J_H +#define CJSON_SHIM_S2J_H +#include "../struct2json/inc/s2j.h" +#endif /* CJSON_SHIM_S2J_H */ diff --git a/src/subprojects/packagefiles/struct2json/cjson/s2jdef.h b/src/subprojects/packagefiles/struct2json/cjson/s2jdef.h new file mode 100644 index 00000000..3098093d --- /dev/null +++ b/src/subprojects/packagefiles/struct2json/cjson/s2jdef.h @@ -0,0 +1,9 @@ +/* + * Lowercase-include shim for the meson wrap build of struct2json. + * Forwards to the real header under struct2json/inc/. + * See cjson/cJSON.h shim for rationale. + */ +#ifndef CJSON_SHIM_S2JDEF_H +#define CJSON_SHIM_S2JDEF_H +#include "../struct2json/inc/s2jdef.h" +#endif /* CJSON_SHIM_S2JDEF_H */ diff --git a/src/subprojects/packagefiles/tinylog/meson.build b/src/subprojects/packagefiles/tinylog/meson.build new file mode 100644 index 00000000..13172a5f --- /dev/null +++ b/src/subprojects/packagefiles/tinylog/meson.build @@ -0,0 +1,43 @@ +project('tinylog', + ['c'], + version: '1.0.0', + meson_version: '>=1.0', + default_options: ['c_std=gnu99', 'warning_level=2']) + +pkg = import('pkgconfig') + +incdir = include_directories('.') + +libtlog = shared_library('tlog', + ['tlog.c'], + include_directories: incdir, + install: not meson.is_subproject()) + +if not meson.is_subproject() + install_headers(['tlog.h']) + + pkg.generate(libtlog, + name: 'tinylog', + description: 'Tinylog is a lightweight C-language high performance log component for UNIX environment', + version: meson.project_version()) +endif + +# Register the fallback the parent resolves through this wrap's [provide] +# section: dependency('tinylog'). +tinylog_sdep = declare_dependency( + link_with: libtlog, + include_directories: incdir, + version: meson.project_version()) +meson.override_dependency('tinylog', tinylog_sdep) + +# Raw flags for non-meson consumers (frontend/apiserver reads them via +# dep.get_variable() to fill CGO_CFLAGS/CGO_LDFLAGS -- Go's cgo cannot +# consume meson dependency objects). Mirrors the nix tinylog.pc +# (Libs: -L${libdir} -ltlog, Cflags: -I${includedir}); the shared object +# lands in this subproject's build-dir root. +tinylog_raw = declare_dependency( + variables: { + 'cflags': '-I' + meson.current_source_dir(), + 'ldflags': '-L' + meson.current_build_dir() + ' -ltlog', + }) +meson.override_dependency('tinylog-raw', tinylog_raw) diff --git a/src/subprojects/packagefiles/unity.patch b/src/subprojects/packagefiles/unity.patch new file mode 100644 index 00000000..a2500ee9 --- /dev/null +++ b/src/subprojects/packagefiles/unity.patch @@ -0,0 +1,79 @@ +# Unity v2.6.1 upstream ships its own meson.build, but it cannot serve as a +# meson wrap fallback for this repo as-is: +# 1. It unconditionally evaluates generator(find_program( +# 'auto/generate_test_runner.rb')) -- a hard ruby requirement at +# configure time. XCE suites use unity's built-in RUN_TEST macro +# (unity_internals.h) and never consume the generated runner, so the +# generator block is dropped. +# 2. The nix packaging (xbuild unity_test_with_color) built libunity.a with +# -DUNITY_OUTPUT_COLOR=1 (its libunity.a contains the ANSI escapes). +# Reproduce that on the library only -- consumers don't need the macro, +# matching the nix pc (Cflags had no -DUNITY_OUTPUT_COLOR). +# 3. It never registers the dependency override, so the parent's +# dependency('unity') fallback would fail ("did not override"). +# +# Include layout (consumers): most suites use ; a few use bare +# . Under nix, unity.pc exposed includedir=/include (parent +# of the unity/ header dir) via dependency.get_variable('includedir') and +# Cflags -I${includedir}/unity. The wrap path mirrors this: the wrap's +# patch_directory ships a unity/ dir with the two headers into the source +# tree, and the override carries variables: {'includedir': } + +# include_directories('src') for the bare-include consumers. The parent +# sites that call unity_dep.get_variable('includedir') then resolve +# exactly as before. +--- a/meson.build ++++ b/meson.build +@@ -18,7 +18,7 @@ + + meson_version: '>=0.47.0', + default_options: [ +- 'werror=true', ++ 'werror=false', + 'c_std=c11' + ] + ) +@@ -50,7 +50,7 @@ + + unity_lib = static_library(meson.project_name(), + sources: unity_src, +- c_args: unity_args, ++ c_args: unity_args + ['-DUNITY_OUTPUT_COLOR=1'], + include_directories: unity_inc, + install: not meson.is_subproject(), + ) +@@ -60,6 +60,23 @@ + include_directories: unity_inc + ) + ++# Wrap-fallback plumbing (see file header): register the parent's ++# dependency('unity') resolution and reproduce the nix header layout -- ++# includedir variable points at the source tree root, which contains a ++# unity/ dir holding the two headers (shipped by this wrap's ++# patch_directory). include_directories('src') covers bare-include ++# consumers, mirroring the nix pc's -I${includedir}/unity. ++unity_sdep = declare_dependency( ++ link_with: unity_lib, ++ include_directories: [unity_inc, include_directories('.')], ++ variables: {'includedir': meson.current_source_dir()}, ++ version: meson.project_version()) ++meson.override_dependency('unity', unity_sdep) ++ ++# XCE does not consume the ruby-generated test runner (its suites use ++# unity's built-in RUN_TEST macro) and the build environment has no ruby, ++# so the upstream generator block is not registered. ++ + # Generate pkg-config file. + if not meson.is_subproject() + pkg = import('pkgconfig') +@@ -70,11 +87,3 @@ + description: 'C Unit testing framework.' + ) + endif +- +-# Create a generator that can be used by consumers of our build system to generate +-# test runners. +-gen_test_runner = generator( +- find_program('auto/generate_test_runner.rb'), +- output: '@BASENAME@_Runner.c', +- arguments: ['@INPUT@', '@OUTPUT@'] +-) diff --git a/src/subprojects/packagefiles/unity/unity/unity.h b/src/subprojects/packagefiles/unity/unity/unity.h new file mode 100644 index 00000000..9e2a97b7 --- /dev/null +++ b/src/subprojects/packagefiles/unity/unity/unity.h @@ -0,0 +1,698 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 6 +#define UNITY_VERSION_BUILD 1 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/*------------------------------------------------------- + * Build Directives + *------------------------------------------------------- + + * These macros do nothing, but they are useful for additional build context. + * Tools (like Ceedling) can scan for these directives and make use of them for + * per-test-executable #include search paths and linking. */ + +/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ +#define TEST_SOURCE_FILE(a) + +/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ +#define TEST_INCLUDE_PATH(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/subprojects/packagefiles/unity/unity/unity_internals.h b/src/subprojects/packagefiles/unity/unity/unity_internals.h new file mode 100644 index 00000000..562f5b6d --- /dev/null +++ b/src/subprojects/packagefiles/unity/unity/unity_internals.h @@ -0,0 +1,1183 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else + #define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +/* UNITY_NORETURN is only required if we have setjmp.h. */ +#ifndef UNITY_EXCLUDE_SETJMP_H + #ifndef UNITY_NORETURN + #if defined(__cplusplus) + #if __cplusplus >= 201103L + #define UNITY_NORETURN [[ noreturn ]] + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L + /* _Noreturn keyword is used from C11 but deprecated in C23. */ + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #if defined(__GNUC__) + /* The header collides with __attribute(noreturn)__ from GCC. */ + #define UNITY_NORETURN _Noreturn + #else + #include + #define UNITY_NORETURN noreturn + #endif + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L + /* Since C23, the keyword _Noreturn has been replaced by the attribute noreturn, based on: */ + /* https://en.cppreference.com/w/c/language/attributes/noreturn */ + #define UNITY_NORETURN [[ noreturn ]] + #endif + #endif + #ifndef UNITY_NORETURN + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) + #endif +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isnan macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_NAN +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define UNITY_IS_NAN(n) ((n != n) ? 1 : 0) +#else +#define UNITY_IS_NAN(n) isnan(n) +#endif +#endif + +/* isinf macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_INF +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define UNITY_IS_INF(n) (UNITY_IS_NAN((n) - (n)) && !UNITY_IS_NAN(n)) +#else +#define UNITY_IS_INF(n) isinf(n) +#endif +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() (void)0 + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) || defined(__APPLE__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x0, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifdef UNITY_TEST_PROTECT +#define TEST_PROTECT() UNITY_TEST_PROTECT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#else +#define TEST_PROTECT() 1 +#endif +#endif + +#ifdef UNITY_TEST_ABORT +#define TEST_ABORT() UNITY_TEST_ABORT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_ABORT() return +#endif +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX) + #define TEST_MATRIX(...) + #endif + #endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((line), (message)); } } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/src/subprojects/packcc.wrap b/src/subprojects/packcc.wrap new file mode 100644 index 00000000..3e0f0d85 --- /dev/null +++ b/src/subprojects/packcc.wrap @@ -0,0 +1,9 @@ +[wrap-git] +directory = packcc +url = https://github.com/arithy/packcc +revision = v2.2.0 +depth = 1 +patch_directory = packcc + +[provide] +program_names = packcc diff --git a/src/subprojects/packcc/.github/workflows/testing.yml b/src/subprojects/packcc/.github/workflows/testing.yml new file mode 100644 index 00000000..8d77d686 --- /dev/null +++ b/src/subprojects/packcc/.github/workflows/testing.yml @@ -0,0 +1,38 @@ +name: run test cases + +on: + push: + branches: [v2] + pull_request: + branches: [v2] + +jobs: + testing: + strategy: + matrix: + os: [ubuntu-22.04, ubuntu-24.04] + compiler: [gcc, clang] + + runs-on: ${{ matrix.os }} + + env: + CC: ${{ matrix.compiler }} + + steps: + - uses: actions/checkout@v4 + - name: install bats + run: | + curl -L -o bats-core-1.2.1.tar.gz https://github.com/bats-core/bats-core/archive/v1.2.1.tar.gz + tar zxvf bats-core-1.2.1.tar.gz + cd bats-core-1.2.1 && + sudo ./install.sh /usr/local + - name: install uncrustify + run: | + curl -LO http://launchpadlibrarian.net/516341795/uncrustify_0.72.0+dfsg1-2_amd64.deb + sudo dpkg -i uncrustify_0.72.0+dfsg1-2_amd64.deb || true + - name: build packcc + run: | + ( + cd build/$CC + make all check + ) diff --git a/src/subprojects/packcc/.gitignore b/src/subprojects/packcc/.gitignore new file mode 100644 index 00000000..696f9410 --- /dev/null +++ b/src/subprojects/packcc/.gitignore @@ -0,0 +1,11 @@ +*.o +*.obj +/build/**/tmp/ +/build/**/bin/ +/build/msvc/**/x86/ +/build/msvc/**/x64/ +/build/msvc/**/.vs/ +/benchmark/tmp/ +/.vscode/ +/.cache/ +__pycache__/ diff --git a/src/subprojects/packcc/LICENSE b/src/subprojects/packcc/LICENSE new file mode 100644 index 00000000..b5a39d5f --- /dev/null +++ b/src/subprojects/packcc/LICENSE @@ -0,0 +1,21 @@ +PackCC: a packrat parser generator for C. + +Copyright (c) 2014, 2019-2025 Arihiro Yoshida. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/subprojects/packcc/README.md b/src/subprojects/packcc/README.md new file mode 100644 index 00000000..68fdba46 --- /dev/null +++ b/src/subprojects/packcc/README.md @@ -0,0 +1,936 @@ +# PackCC + +## Overview + +**PackCC** is a parser generator for C. +Its main features are as follows: + +- Generates your parser in C from a grammar described in a **PEG**, +- Gives your parser great efficiency by **packrat parsing**, +- Supports direct and indirect **left-recursive** grammar rules. + +The grammar of your parser can be described in a **PEG** ([Parsing Expression Grammar](http://en.wikipedia.org/wiki/Parsing_expression_grammar)). +The PEG is a [top-down parsing language](http://en.wikipedia.org/wiki/Top-down_parsing_language), +and is similar to the [regular-expression](http://en.wikipedia.org/wiki/Regular_expression) grammar. +Compared with a bottom-up parsing language, like Yacc's one, the PEG is much more intuitive and cannot be ambiguous. +The PEG does not require tokenization to be a separate step, and tokenization rules can be written in the same way as any other grammar rules. + +Your generated parser can parse inputs very efficiently by **packrat parsing**. +The packrat parsing is the [recursive descent parsing](http://en.wikipedia.org/wiki/Recursive_descent_parser) algorithm +that is accelerated using [memoization](http://en.wikipedia.org/wiki/Memoization). +By using packrat parsing, any input can be parsed in linear time. +Without it, however, the resulting parser could exhibit exponential time performance in the worst case due to the unlimited look-ahead capability. + +Unlike common packrat parsers, PackCC can support direct and indirect **left-recursive** grammar rules. +This powerful feature enables you to describe your language grammar in a much simpler way. +(The algorithm is based on the paper [*"Packrat Parsers Can Support Left Recursion"*](http://www.cs.ucla.edu/~todd/research/pub.php?id=pepm08) +authored by A. Warth, J. R. Douglass, and T. Millstein.) + +Some additional features are as follows: + +- Thread-safe and reentrant, +- Supports UTF-8 multibyte characters (version 1.4.0 or later), +- Generates more ease-of-understanding parser source codes, +- Consists of just a single compact source file, +- Under MIT license. (not under a certain contagious license!) + +The generated code is beautified and as ease-of-understanding as possible. +Actually, it uses lots of *goto* statements, but the control flows are much more traceable +than *goto* spaghetti storms generated by Yacc or other parser generators. +This feature is irrelevant to common users, but helpful for PackCC developers to debug it. + +PackCC itself is under MIT license, but you can distribute your generated code under any license you like. + +## Installation + +You can obtain the executable `packcc` by compiling [`src/packcc.c`](src/packcc.c) using your favorite C compiler. +For convenience, the build environments using GCC, Clang, and Microsoft Visual Studio are prepared under [`build`](build) directory. + +### Using GCC + +#### Other than MinGW + +`packcc` will be built in both directories `build/gcc/debug/bin` and `build/gcc/release/bin` using `gcc` by executing the following commands: + +``` +cd build/gcc +make +make check # bats-core and uncrustify are required (see tests/README.md) +``` + +`packcc` in the directory `build/gcc/release/bin` is suitable for practical use. + +#### MinGW + +`packcc` will be built in both directories `build/mingw-gcc/debug/bin` and `build/mingw-gcc/release/bin` using `gcc` by executing the following commands: + +``` +cd build/mingw-gcc +make +make check # bats-core and uncrustify are required (see tests/README.md) +``` + +`packcc` in the directory `build/mingw-gcc/release/bin` is suitable for practical use. + +### Using Clang + +#### Other than MinGW + +`packcc` will be built in both directories `build/clang/debug/bin` and `build/clang/release/bin` using `clang` by executing the following commands: + +``` +cd build/clang +make +make check # bats-core and uncrustify are required (see tests/README.md) +``` + +`packcc` in the directory `build/clang/release/bin` is suitable for practical use. + +#### MinGW + +`packcc` will be built in both directories `build/mingw-clang/debug/bin` and `build/mingw-clang/release/bin` using `clang` by executing the following commands: + +``` +cd build/mingw-clang +make +make check # bats-core and uncrustify are required (see tests/README.md) +``` + +`packcc` in the directory `build/mingw-clang/release/bin` is suitable for practical use. + +### Using Microsoft Visual Studio + +You have to install Microsoft Visual Studio 2019 in advance. +After that, you can build `packcc.exe` by the following instructions: + +- Open the solution file `build\msvc\msvc.sln`, +- Select a preferred solution configuration (*Debug* or *Release*) and a preferred solution platform (*x64* or *x86*), +- Invoke the *Build Solution* menu item. + +`packcc.exe` will appear in `build\msvc\XXX\YYY` directory. +Here, `XXX` is `x64` or `x86`, and `YYY` is `Debug` or `Release`. +`packcc.exe` in the directory `build\msvc\XXX\Release` is suitable for practical use. + +## Usage + +### Command + +You must prepare a PEG source file in advance. +For details of the PEG source syntax, see the section "Syntax". +Here, let the file name `example.peg` for example. + +``` +packcc example.peg +``` + +By running this, the parser source `example.h` and `example.c` are generated. + +If no PEG file name is specified, the PEG source is read from the standard input, and `-.h` and `-.c` will be generated. + +The base name of the parser source files can be changed by `-o` option. + +``` +packcc -o parser example.peg +``` + +By running this, the parser source `parser.h` and `parser.c` are generated. +This option can be specified only once. + +A directory to search for import files can be added by `-I` option (version 2.0.0 or later). +This option can be specified as many times as needed. +The firstly specified directory will be searched first, the secondly specified directory will be searched next, and so on. + +``` +packcc -I foo -I bar/baz example.peg +``` + +By running this, the directory `foo` is searched first, and the directory `bar/baz` is searched next. +The directories specified by this option have higher priority than those specified in the environment variable `PCC_IMPORT_PATH` and the default directories. +For more details of import, see the explanation of `%import` written in the section "Syntax". + +If you want to disable UTF-8 support, specify the command line option `-a` or `--ascii` (version 1.4.0 or later). + +If you want to insert `#line` directives in the generated source and header files, specify the command line option `-l` or `--lines` (version 1.7.0 or later). +It is helpful to trace compilation errors of the generated source and header files back to the codes written in the PEG source file. + +If you want to confirm the version of the `packcc` command, execute the below. + +``` +packcc -v +``` + +### Syntax + +A grammar consists of a set of named rules. +A rule definition can be split into multiple lines. + +**_rulename_ `<-` _pattern_** + +The _rulename_ is the name of the rule to define. +The _pattern_ is a text pattern that contains one or more of the following elements. + +**_rulename_** + +The element stands for the entire pattern in the rule with the name given by _rulename_. + +**_variable_`:`_rulename_** + +The element stands for the entire pattern in the rule with the name given by _rulename_. +The _variable_ is an identifier associated with the semantic value returned from the rule by assigning to `$$` in its action. +The identifier can be referred to in subsequent actions as a variable. +The example is shown below. + +``` +term <- l:term _ '+' _ r:factor { $$ = l + r; } +``` + +A variable identifier must consist of alphabets (both uppercase and lowercase letters), digits, and underscores. +The first letter must be an alphabet. +The reserved keywords in C cannot be used. + +**_sequence1_ `/` _sequence2_ `/` ... `/` _sequenceN_** + +Each _sequence_ is tried in turn until one of them matches, at which time matching for the overall pattern succeeds. +If no _sequence_ matches then the matching for the overall pattern fails. +The operator slash (`/`) has the least priority. +The example is shown below. + +``` +'foo' rule1 / 'bar'+ [0-9]? / rule2 +``` + +This pattern tries matching of the first sequence (`'foo' rule1`). +If it succeeds, then the overall pattern matching succeeds and ends without evaluating the subsequent sequences. +Otherwise, it tries matching of the next sequence (`'bar'+ [0-9]?`). +If it succeeds, then the overall pattern matching succeeds and ends without evaluating the subsequent sequence. +Finally, it tries matching of the last sequence (`rule2`). +If it succeeds, then the overall pattern matching succeeds. +Otherwise, the overall pattern matching fails. + +**`'`_string_`'`** + +A character or string enclosed in single quotes is matched literally. +The ANSI C escape sequences are recognized within the characters. +The UNICODE escape sequences (ex. `\u20AC`) are also recognized including surrogate pairs, +if the command line option `-a` is not specified (version 1.4.0 or later). +The example is shown below. + +``` +'foo bar' +``` + +**`"`_string_`"`** + +A character or string enclosed in double quotes is matched literally. +The ANSI C escape sequences are recognized within the characters. +The UNICODE escape sequences (ex. `\u20AC`) are also recognized including surrogate pairs, +if the command line option `-a` is not specified (version 1.4.0 or later). +The example is shown below. + +``` +"foo bar" +``` + +**`[`_character class_`]`** + +A set of characters enclosed in square brackets matches any single character from the set. +The ANSI C escape sequences are recognized within the characters. +The UNICODE escape sequences (ex. `\u20AC`) are also recognized including surrogate pairs, +if the command line option `-a` is not specified (version 1.4.0 or later). +If the set begins with a caret (`^`), the set is negated (the element matches any character not in the set). +Any pair of characters separated with a dash (`-`) represents the range of characters from the first to the second, inclusive. +The examples are shown below. + +``` +[abc] +[^abc] +[a-zA-Z0-9_] +``` + +**`.`** + +A dot (`.`) matches any single character. +Note that the only time this fails is at the end of the input, where there is no character to match. + +**`^`** + +A caret (`^`) matches the beginning of the input (version 2.1.0 or later). + +**_element_ `?`** + +The _element_ is optional. +If present on the input, it is consumed and the match succeeds. +If not present on the input, no text is consumed and the match succeeds anyway. + +**_element_ `*`** + +The _element_ is optional and repeatable. +If present on the input, one or more occurrences of the _element_ are consumed and the match succeeds. +If no occurrence of the _element_ is present on the input, the match succeeds anyway. + +**_element_ `+`** + +The _element_ is repeatable. +If present on the input, one or more occurrences of the _element_ are consumed and the match succeeds. +If no occurrence of the _element_ is present on the input, the match fails. + +**`&` _element_** + +The predicate succeeds only if the _element_ can be matched. +The input text scanned while matching _element_ is not consumed from the input and remains available for subsequent matching. + +**`!` _element_** + +The predicate succeeds only if the _element_ cannot be matched. +The input text scanned while matching _element_ is not consumed from the input and remains available for subsequent matching. +A popular idiom is the following, which matches the end of the input, after the last character of the input has already been consumed. + +``` +!. +``` + +**`(` _pattern_ `)`** + +Parentheses are used for grouping (modifying the precedence of the _pattern_). + +**`<` _pattern_ `>`** + +Angle brackets are used for grouping (modifying the precedence of the _pattern_) and text capturing. +The captured text is numbered in evaluation order, and can be referred to later using `$1`, `$2`, etc. + +**`$`_n_** + +A dollar (`$`) followed by a positive integer represents a text previously captured. +The positive integer corresponds to the order of capturing. +A `$1` represents the first captured text. +The examples are shown below. + +``` +< [0-9]+ > 'foo' $1 +``` + +This matches `0foo0`, `123foo123`, etc. + +``` +'[' < '='* > '[' ( !( ']' $1 ']' ) . )* ( ']' $1 ']' ) +``` + +This matches `[[`...`]]`, `[=[`...`]=]`, `[==[`...`]==]`, etc. + +**`{` _c source code_ `}`** + +Curly braces surround an action. +The action is arbitrary C source code to be executed at the end of matching. +Any braces within the action must be properly nested. +Note that braces in directive lines and in comments (`/*`...`*/` and `//`...) are appropriately ignored. +One or more actions can be inserted in any places between elements in the pattern. +Actions are not executed where matching fails. + +``` +[0-9]+ 'foo' { puts("OK"); } 'bar' / [0-9]+ 'foo' 'baz' +``` + +In this example, if the input is `012foobar`, the action `{ puts("OK"); }` is to be executed, but if the input is `012foobaz`, +the action is not to be executed. +All matched actions are guaranteed to be executed only once. + +In the action, the C source code can use the predefined variables below. + +- **`$$`** : + The output variable, to which the result of the rule is stored. + The data type is the one specified by `%value`. + The default data type is `int`. +- **`auxil`** : + The user-defined data that has been given via the API function `pcc_create()`. + The data type is the one specified by `%auxil`. + The default data type is `void *`. +- _variable_ : + The result of another rule that has already been evaluated. + If the rule has not been evaluated, it is ensured that the value is zero-cleared (version 1.7.1 or later). + The data type is the one specified by `%value`. + The default data type is `int`. +- **`$`**_n_ : + The string of the captured text. + The _n_ is the positive integer that corresponds to the order of capturing. + The variable `$1` holds the string of the first captured text. +- **`$`**_n_**`s`** : + The start position in the input of the captured text, inclusive. + The _n_ is the positive integer that corresponds to the order of capturing. + The variable `$1s` holds the start position of the first captured text. +- **`$`**_n_**`e`** : + The end position in the input of the captured text, exclusive. + The _n_ is the positive integer that corresponds to the order of capturing. + The variable `$1e` holds the end position of the first captured text. +- **`$0`** : + The string of the text between the start position in the input at which the rule pattern begins to match + and the current position in the input at which the element immediately before the action ends to match. +- **`$0s`** : + The start position in the input at which the rule pattern begins to match. +- **`$0e`** : + The current position in the input at which the element immediately before the action ends to match. + +An example is shown below. + +``` +term <- l:term _ '+' _ r:factor { $$ = l + r; } +factor <- < [0-9]+ > { $$ = atoi($1); } +_ <- [ \t]* +``` + +Note that the string data held by `$`_n_ and `$0` are discarded immediately after evaluation of the action. +If the string data are needed after the action, they must be copied in `$$` or `auxil`. +If they are required to be copied in `$$`, it is recommended to define a structure as the type of output data using `%value`, +and to copy the necessary string data in its member variable. +Similarly, if they are required to be copied in `auxil`, it is recommended to define a structure as the type of user-defined data using `%auxil`, +and to copy the necessary string data in its member variable. + +The position values are 0-based; that is, the first position is 0. +The data type is `size_t` (before version 1.4.0, it was `int`). + +**_element_ `~` `{` _c source code_ `}`** + +Curly braces following tilde (`~`) surround an error action. +The error action is arbitrary C source code to be executed at the end of matching only if the preceding _element_ matching fails. +Any braces within the error action must be properly nested. +Note that braces in directive lines and in comments (`/*`...`*/` and `//`...) are appropriately ignored. +One or more error actions can be inserted in any places after elements in the pattern. +The operator tilde (`~`) binds less tightly than any other operator except alternation (`/`) and sequencing. +The error action is intended to make error handling and recovery code easier to write. +In the error action, all predefined variables described above are available as well. +The examples are shown below. + +``` +rule1 <- e1 e2 e3 ~{ error("e[12] ok; e3 has failed"); } +rule2 <- (e1 e2 e3) ~{ error("one of e[123] has failed"); } +``` + +**`%header` `{` _c source code_ `}`** + +The specified C source code is copied verbatim to the C header file before the generated parser API function declarations. +Any braces in the C source code must be properly nested. +Note that braces in directive lines and in comments (`/*`...`*/` and `//`...) are appropriately ignored. +When `%header` is used multiple times, the respective C source codes are copied in order of their appearance. + +**`%source` `{` _c source code_ `}`** + +The specified C source code is copied verbatim to the C source file before the generated parser implementation code. +Any braces in the C source code must be properly nested. +Note that braces in directive lines and in comments (`/*`...`*/` and `//`...) are appropriately ignored. +When `%source` is used multiple times, the respective C source codes are copied in order of their appearance. + +**`%common` `{` _c source code_ `}`** + +The specified C source code is copied verbatim to both of the C header file and the C source file +before the generated parser API function declarations and the implementation code respectively. +This has the same effect as `%header {` _c source code_ `} %source {` _c source code_ `}`. +Any braces in the C source code must be properly nested. +Note that braces in directive lines and in comments (`/*`...`*/` and `//`...) are appropriately ignored. + +**`%earlyheader` `{` _c source code_ `}`** + +**`%earlysource` `{` _c source code_ `}`** + +**`%earlycommon` `{` _c source code_ `}`** + +Same as `%header`, `%source` and `%common`, respectively. +The only difference is that these directives place the code at the very beginning of the generated file, +before any code or includes generated by PackCC. +This can be useful for example when it is necessary to modify behavior of standard libraries via a macro definition. + +**`%value` `"`_output data type_`"`** + +The type of output data, which is output as `$$` in each action and can be retrieved from the parser API function `pcc_parse()`, +is changed to the specified one from the default `int`. +This can be used only once and cannot be used in imported files. + +**`%auxil` `"`_user-defined data type_`"`** + +The type of user-defined data, which is passed to the parser API function `pcc_create()`, +is changed to the specified one from the default `void *`. +This can be used only once and cannot be used in imported files. + +**`%prefix` `"`_prefix_`"`** + +The prefix of the parser API functions is changed to the specified one from the default `pcc`. +This can be used only once and cannot be used in imported files. + +**`%import` `"`_import file name_`"`** + +The content of the specified import file is expanded at the text location of `%import` (version 2.0.0 or later). +This can be used multiple times anywhere and can be used also in imported files. +The _import file name_ can be a relative path to the current directory or an absolute path. +If it is a relative path, the directories listed below are searched for the import file in the listed order. + +1. the directory where the file that imports the import file is located +2. the directories specified with `-I` options + - They are prioritized in order of their appearance in the command line. +3. the directories specified by the environment variable `PCC_IMPORT_PATH` + - They are prioritized in order of their appearance in the value of this variable. + - The character used as a delimiter between directory names is the colon `':'` if PackCC is built for a Unix-like platform such as Linux, macOS, and MinGW. + The character is the semicolon `';'` if PackCC is built as a native Windows executable. + (This is exactly the same manner as the environment variable `PATH`.) +4. the per-user default directory + - This is the subdirectory `.packcc/import` in the home directory if PackCC is built for a Unix-like platform, + and in the user profile directory, "`C:\Users\`_username_" for example, if PackCC is built as a native Windows executable. +5. the system-wide default directory + - This is the directory `/usr/share/packcc/import` if PackCC is built for a Unix-like platform, + and is the subdirectory `packcc/import` in the common application data directory, "`C:\ProgramData`" for example. + +Note that the file imported once is silently ignored when it is attempted to be imported again. + +**`#`_comment_** + +A comment can be inserted between `#` and the end of the line. + +**`%%`** + +A double percent `%%` terminates the section for rule definitions of the grammar. +All text following `%%` is copied verbatim to the C source file after the generated parser implementation code. + +(The specification is determined by referring to [peg/leg](http://piumarta.com/software/peg/) developed by Ian Piumarta.) + +### Import Files + +The following import files are currently bundled. + +- **Character Matching Rules** + - [`char/ascii_character_group.peg`](import/char/ascii_character_group.peg) : + This provides various rules to match an ASCII character belonging to a specific character group. + - [`char/unicode_general_category.peg`](import/char/unicode_general_category.peg) : + This provides various rules to match a Unicode character belonging to a specific [general category](https://unicode.org/reports/tr44/#General_Category_Values). +- **Utility Codes** + - [`code/pcc_ast.peg`](import/code/pcc_ast.peg) : + This provides codes to make it easier to build an AST (abstract syntax tree). + +For details, see [here](import). + +### Macros + +Some macros are prepared to customize the parser. +The macro definition should be **in `%source` section** in the PEG source. + +```c +%source { +#define PCC_GETCHAR(auxil) get_character((auxil)->input) +#define PCC_BUFFERSIZE 1024 +} +``` + +The following macros are available. + +**`PCC_GETCHAR(`**_auxil_**`)`** + +The function macro to get a character from the input. +The user-defined data passed to the API function `pcc_create()` can be retrieved from the argument _auxil_. +It can be ignored if no user-defined data. +This macro must return a character code as an `int` type, or `-1` if the input ends. + +The default is defined as below. + +```c +#define PCC_GETCHAR(auxil) getchar() +``` + +**`PCC_ERROR(`**_auxil_**`)`** + +The function macro to handle a syntax error. +The user-defined data passed to the API function `pcc_create()` can be retrieved from the argument _auxil_. +It can be ignored if no user-defined data. +This macro need not return a value. +It may abort the process (by using `exit()` for example) when a fatal error occurs, and can also return normally to deal with warnings. + +The default is defined as below. + +```c +#define PCC_ERROR(auxil) pcc_error() +static void pcc_error(void) { + fprintf(stderr, "Syntax error\n"); + exit(1); +} +``` + +**`PCC_MALLOC(`**_auxil_**`,`**_size_**`)`** + +The function macro to allocate a memory block. +The user-defined data passed to the API function `pcc_create()` can be retrieved from the argument _auxil_. +It can be ignored if no user-defined data. +The argument _size_ is the number of bytes to allocate. +This macro must return a pointer to the allocated memory block, or `NULL` if no sufficient memory is available. + +The default is defined as below. + +```c +#define PCC_MALLOC(auxil, size) pcc_malloc_e(size) +static void *pcc_malloc_e(size_t size) { + void *p = malloc(size); + if (p == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + return p; +} +``` + +**`PCC_REALLOC(`**_auxil_**`,`**_ptr_**`,`**_size_**`)`** + +The function macro to reallocate the existing memory block. +The user-defined data passed to the API function `pcc_create()` can be retrieved from the argument _auxil_. +It can be ignored if no user-defined data. +The argument _ptr_ is the pointer to the previously allocated memory block. +The argument _size_ is the new number of bytes to reallocate. +This macro must return a pointer to the reallocated memory block, or `NULL` if no sufficient memory is available. +The contents of the memory block should be left unchanged in any case even if the reallocation fails. + +The default is defined as below. + +```c +#define PCC_REALLOC(auxil, ptr, size) pcc_realloc_e(ptr, size) +static void *pcc_realloc_e(void *ptr, size_t size) { + void *p = realloc(ptr, size); + if (p == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + return p; +} +``` + +**`PCC_FREE(`**_auxil_**`,`**_ptr_**`)`** + +The function macro to free the existing memory block. +The user-defined data passed to the API function `pcc_create()` can be retrieved from the argument _auxil_. +It can be ignored if no user-defined data. +The argument _ptr_ is the pointer to the previously allocated memory block. +This macro need not return a value. + +The default is defined as below. + +```c +#define PCC_FREE(auxil, ptr) free(ptr) +``` + +**`PCC_DEBUG(`**_auxil_**`,`**_event_**`,`**_rule_**`,`**_level_**`,`**_pos_**`,`**_buffer_**`,`**_length_**`)`** + +The function macro for debugging (version 1.5.0 or later). +Sometimes, especially for complex parsers, it is useful to see how exactly the parser processes the input. +This macro is called on important *events* and allows to log or display the current state of the parser. +The argument `rule` is a string that contains the name of the currently evaluated rule. +The non-negative integer `level` specifies how deep in the rule hierarchy the parser currently is. +The argument `pos` holds the position from the start of the current context in bytes. +In case of `event == PCC_DBG_MATCH`, the argument `buffer` holds the matched input and `length` is its size. +For other events, `buffer` and `length` indicate a part of the currently loaded input, which is used to evaluate the current rule. + +**Caution:** Since version 1.6.0, the first argument _auxil_ is added to this macro. +The user-defined data passed to the API function `pcc_create()` can be retrieved from this argument. + +There are currently three supported events: + +- `PCC_DBG_EVALUATE` (= 0) - called when the parser starts to evaluate `rule` +- `PCC_DBG_MATCH` (= 1) - called when `rule` is matched, at which point buffer holds entire matched string +- `PCC_DBG_NOMATCH` (= 2) - called when the parser determines that the input does not match currently evaluated `rule` + +A very simple implementation could look like this: + +```c +static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" }; +#define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) \ + fprintf(stderr, "%*s%s %s @%zu [%.*s]\n", (int)((level) * 2), "", dbg_str[event], rule, pos, (int)(length), buffer) +``` + +The default is to do nothing: + +```c +#define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) ((void)0) +``` + +**`PCC_BUFFERSIZE`** + +The initial size (the number of characters) of the text buffer. +The text buffer is expanded as needed. +The default is `256`. + +**`PCC_ARRAYSIZE`** + +The initial size (the number of elements) of the internal arrays other than the text buffer. +The arrays are expanded as needed. +The default is `2`. + +### API + +The parser API has only 3 simple functions below. + +```c +pcc_context_t *pcc_create(void *auxil); +``` + +Creates a parser context. +This context needs to be passed to the functions below. +The `auxil` can be used to pass user-defined data to be bound to the context. +`NULL` can be specified if no user-defined data. + +```c +int pcc_parse(pcc_context_t *ctx, int *ret); +``` + +Parses an input text (from the standard input by default) and returns the result in `ret`. +The `ret` can be `NULL` if no output data is needed. +This function returns `0` if no text is left to be parsed, or a nonzero value otherwise. + +```c +void pcc_destroy(pcc_context_t *ctx); +``` + +Destroys the parser context. +All resources allocated in the parser context are released. + +The type of output data `ret` can be changed. +If you want change it to `char *`, specify `%value "char *"` in the PEG source. +The default is `int`. + +The type of user-defined data `auxil` can be changed. +If you want change it to `long`, specify `%auxil "long"` in the PEG source. +The default is `void *`. + +The prefix `pcc` can be changed. +If you want change it to `foo`, specify `%prefix "foo"` in the PEG source. +The default is `pcc`. + +After the above settings, the API functions change like below. + +```c +foo_context_t *foo_create(long auxil); +``` + +```c +int foo_parse(foo_context_t *ctx, char **ret); +``` + +```c +void foo_destroy(foo_context_t *ctx); +``` + +The typical usage of the API functions is shown below. + +```c +int ret; +pcc_context_t *ctx = pcc_create(NULL); +while (pcc_parse(ctx, &ret)); +pcc_destroy(ctx); +``` + +## Examples + +### Desktop Calculator + +A simple example which provides interactive four arithmetic operations of integers is shown here. +Note that **left-recursive** grammar rules are defined in this example. + +```c +%prefix "calc" + +%source { +#include +#include +} + +statement <- _ e:expression _ EOL { printf("answer=%d\n", e); } + / ( !EOL . )* EOL { printf("error\n"); } + +expression <- e:term { $$ = e; } + +term <- l:term _ '+' _ r:factor { $$ = l + r; } + / l:term _ '-' _ r:factor { $$ = l - r; } + / e:factor { $$ = e; } + +factor <- l:factor _ '*' _ r:unary { $$ = l * r; } + / l:factor _ '/' _ r:unary { $$ = l / r; } + / e:unary { $$ = e; } + +unary <- '+' _ e:unary { $$ = +e; } + / '-' _ e:unary { $$ = -e; } + / e:primary { $$ = e; } + +primary <- < [0-9]+ > { $$ = atoi($1); } + / '(' _ e:expression _ ')' { $$ = e; } + +_ <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' / ';' + +%% +int main() { + calc_context_t *ctx = calc_create(NULL); + while (calc_parse(ctx, NULL)); + calc_destroy(ctx); + return 0; +} +``` + +An execution example is as follows. + +``` +$ ./calc↵ +1+2*(3+4*(5+6))↵ +answer=95 +5*6*7*8/(1*2*3*4)↵ +answer=70 +``` + +### Simple AST builder + +An example which builds an AST (abstract syntax tree) and dumps it is shown here. +This example accepts the same inputs as *Desktop Calculator* shown above. + +```c +%prefix "calc" + +%value "pcc_ast_node_t *" # <-- must be set + +%auxil "pcc_ast_manager_t *" # <-- must be set + +%header { +#define PCC_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */ + +typedef struct text_data_tag { /* <-- node custom data type */ + char *text; +} pcc_ast_node_custom_data_t; +} + +%source { +#include +#include +} + +statement <- _ e:expression _ EOL { $$ = e; } + / ( !EOL . )* EOL { $$ = NULL; } + +expression <- e:term { $$ = e; } + +term <- l:term _ '+' _ r:factor { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("+"); } + / l:term _ '-' _ r:factor { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("-"); } + / e:factor { $$ = e; } + +factor <- l:factor _ '*' _ r:unary { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("*"); } + / l:factor _ '/' _ r:unary { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("/"); } + / e:unary { $$ = e; } + +unary <- '+' _ e:unary { $$ = pcc_ast_node__create_1(e); $$->custom.text = strdup("+"); } + / '-' _ e:unary { $$ = pcc_ast_node__create_1(e); $$->custom.text = strdup("-"); } + / e:primary { $$ = e; } + +primary <- < [0-9]+ > { $$ = pcc_ast_node__create_0(); $$->custom.text = strdup($1); } + / '(' _ e:expression _ ')' { $$ = e; } + +_ <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' / ';' + +%import "code/pcc_ast.peg" # <-- provides AST build functions + +%% +void pcc_ast_node_custom_data__initialize(pcc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */ + obj->text = NULL; +} + +void pcc_ast_node_custom_data__finalize(pcc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */ + free(obj->text); +} + +static void dump_ast(const pcc_ast_node_t *obj, int depth) { + if (obj) { + switch (obj->type) { + case PCC_AST_NODE_TYPE_NULLARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "nullary", obj->custom.text); + break; + case PCC_AST_NODE_TYPE_UNARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "unary", obj->custom.text); + dump_ast(obj->data.unary.node, depth + 1); + break; + case PCC_AST_NODE_TYPE_BINARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "binary", obj->custom.text); + dump_ast(obj->data.binary.node[0], depth + 1); + dump_ast(obj->data.binary.node[1], depth + 1); + break; + case PCC_AST_NODE_TYPE_TERNARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "ternary", obj->custom.text); + dump_ast(obj->data.ternary.node[0], depth + 1); + dump_ast(obj->data.ternary.node[1], depth + 1); + dump_ast(obj->data.ternary.node[2], depth + 1); + break; + case PCC_AST_NODE_TYPE_VARIADIC: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "variadic", obj->custom.text); + { + size_t i; + for (i = 0; i < obj->data.variadic.len; i++) { + dump_ast(obj->data.variadic.node[i], depth + 1); + } + } + break; + default: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "(unknown)", obj->custom.text); + break; + } + } + else { + printf("%*s(null)\n", 2 * depth, ""); + } +} + +int main(int argc, char **argv) { + pcc_ast_manager_t mgr; + pcc_ast_manager__initialize(&mgr); + { + calc_context_t *ctx = calc_create(&mgr); + pcc_ast_node_t *ast = NULL; + while (calc_parse(ctx, &ast)) { + dump_ast(ast, 0); + pcc_ast_node__destroy(ast); + } + calc_destroy(ctx); + } + pcc_ast_manager__finalize(&mgr); + return 0; +} +``` + +The key point is the line `%import "code/pcc_ast.peg"`. +The import file [`code/pcc_ast.peg`](import/code) makes it easier to build ASTs. +For more details, see [here](import/code/README.md). + +An execution example is as follows. + +``` +$ ./ast-calc↵ +1+2*(3+4*(5+6))↵ +binary: "+" + nullary: "1" + binary: "*" + nullary: "2" + binary: "+" + nullary: "3" + binary: "*" + nullary: "4" + binary: "+" + nullary: "5" + nullary: "6" +5*6*7*8/(1*2*3*4)↵ +binary: "/" + binary: "*" + binary: "*" + binary: "*" + nullary: "5" + nullary: "6" + nullary: "7" + nullary: "8" + binary: "*" + binary: "*" + binary: "*" + nullary: "1" + nullary: "2" + nullary: "3" + nullary: "4" +``` + +### AST Builder for Tiny-C + +You can find the more practical example in the directory [`examples/ast-tinyc`](examples/ast-tinyc). +It builds an AST from an input source file +written in [Tiny-C](http://www.iro.umontreal.ca/~felipe/IFT2030-Automne2002/Complements/tinyc.c) and dumps the AST. diff --git a/src/subprojects/packcc/benchmark/benchmark.sh b/src/subprojects/packcc/benchmark/benchmark.sh new file mode 100755 index 00000000..5fce3bbb --- /dev/null +++ b/src/subprojects/packcc/benchmark/benchmark.sh @@ -0,0 +1,190 @@ +#!/usr/bin/env bash +# +# Generates, builds and runs parsers from grammars directory for each git reference supplied as argument. +# Each action is performed multiple times and the times are averaged. Peak memory consumption is also measured. +# First reference is always taken as a "baseline" and others are compared to it. This should allow to compare +# how any given commit affects PackCCs performance. +# +# Usage: +# ./benchmark.sh ... +# +# Environment: +# CC Compiler to use, default: "cc -O2" +# GEN_REPEATS How many times to generate the parser, default: 10 +# BUILD_REPEATS How many times to build the parser, default: 5 +# RUN_REPEATS How many times to run the given parser, default: 20 +# +# Example: +# CC="clang -O3" ./benchmark.sh origin/master 6015afc HEAD + +build() { + echo "Building packcc..." + $CC -o "$PACKCC" $ROOTDIR/src/packcc.c +} + +clean() { + rm -rf "$BENCHDIR/tmp" +} + +format() { + TIME="$1" + if [ $((TIME / 1000000000)) -gt 10 ]; then + echo "$((TIME / 1000000000)) s" + elif [ $((TIME / 1000000)) -gt 10 ]; then + echo "$((TIME / 1000000)) ms" + elif [ $((TIME / 1000)) -gt 10 ]; then + echo "$((TIME / 1000)) us" + else + echo "$TIME ns" + fi +} + +format_mem() { + MEM="$1" + if [ -z "$TIME_CMD" ]; then + echo "??? kB" + elif [ $((MEM / 1048576)) -gt 10 ]; then + echo "$((MEM / 1048576)) GB" + elif [ $((MEM / 1024)) -gt 10 ]; then + echo "$((MEM / 1024)) MB" + else + echo "$MEM kB" + fi +} + +measure() { + COUNT="$1" + shift + MEM=0 + if [ "$TIME_CMD" ]; then + MEM="$(${TIME_CMD[@]} -f %M "$@" 2>&1 >/dev/null)" + fi + START="$(date '+%s%N')" + for ((i=0; i /dev/null + done + END="$(date '+%s%N')" + TIME=$(( END - START )) +} + +benchmark() { + KEY="${GRAMMAR}_${REF//\//_}" + NAME="tmp/parser_$KEY" + + echo "Generating $GRAMMAR parser in $REF ($GEN_REPEATS times)..." + measure "$GEN_REPEATS" "$PACKCC" -o "$NAME" "$GRAMMAR_FILE" + GEN_TIME["$KEY"]=$TIME + GEN_MEM["$KEY"]=$MEM + echo " Repeated $GEN_REPEATS times in $(format $TIME), peak memory $(format_mem $MEM)" + + echo "Building $GRAMMAR parser in $REF ($BUILD_REPEATS times)..." + measure "$BUILD_REPEATS" $CC -I. "$NAME".c -o "$NAME" + BUILD_TIME["$KEY"]=$TIME + BUILD_MEM["$KEY"]=$MEM + echo " Built $BUILD_REPEATS times in $(format $TIME), peak memory $(format_mem $MEM)" + + echo "Running $GRAMMAR parser in $REF ($RUN_REPEATS times)..." + measure "$RUN_REPEATS" "./$NAME" "$INPUT" + RUN_TIME["$KEY"]=$TIME + RUN_MEM["$KEY"]=$MEM + echo " Repeated $RUN_REPEATS times in $(format $TIME), peak memory $(format_mem $MEM)" +} + +print_table() { + declare -n RESULTS_TIME="${1}_TIME" + declare -n RESULTS_MEM="${1}_MEM" + printf "%-12s" "" + for REF in "${REFS[@]}"; do + printf "%-32s" "$REF" + done + printf "\n" + MEMORY=0 + RELATIVE_MEM="???" + COLOR_MEM=0 + for GRAMMAR in "${GRAMMARS[@]}"; do + printf "%-12s" "$GRAMMAR" + for REF in "${REFS[@]}"; do + KEY="${GRAMMAR}_${REF//\//_}" + BASE="${GRAMMAR}_${REFS[0]//\//_}" + TIME="$((${RESULTS_TIME["$KEY"]} / RUN_REPEATS))" + RELATIVE_TIME="$((100 * RESULTS_TIME["$KEY"] / RESULTS_TIME["$BASE"]))" + COLOR=$((RELATIVE_TIME == 100 ? 0 : ( RELATIVE_TIME > 100 ? 31 : 32))) + if [ "$TIME_CMD" ]; then + MEMORY="${RESULTS_MEM["$KEY"]}" + RELATIVE_MEM="$((100 * RESULTS_MEM["$KEY"] / RESULTS_MEM["$BASE"]))" + COLOR_MEM=$((RELATIVE_MEM == 100 ? 0 : ( RELATIVE_MEM > 100 ? 31 : 32))) + fi + printf "\033[0;${COLOR}m%-16s\033[0;${COLOR_MEM}m%-16s\033[0m" "$(format $TIME) ($RELATIVE_TIME%)" "$(format_mem $MEMORY) ($RELATIVE_MEM%)" + done + printf "\n" + done +} + +print_results() { + echo + echo "Generation performance:" + echo "=======================" + print_table GEN + echo + echo "Build performance:" + echo "==================" + print_table BUILD + echo + echo "Run performance:" + echo "================" + print_table RUN + echo +} + +main() { + set -e + + BENCHDIR="$(cd "$(dirname "$0")" && pwd)" + ROOTDIR="$BENCHDIR/.." + declare -a GRAMMARS=() + declare -A BUILD_TIME GEN_TIME RUN_TIME BUILD_MEM GEN_MEM RUN_MEM + + declare -i GEN_REPEATS="${GEN_REPEATS:-1}" + declare -i BUILD_REPEATS="${BUILD_REPEATS:-1}" + declare -i RUN_REPEATS="${RUN_REPEATS:-1}" + CC="${CC:-cc -O2}" + REFS=("$@") + + if [[ $# -eq 0 || "$1" =~ -h|--help|--usage ]]; then + sed -n '3,/^$/s/^#//p' "$0" + exit 0 + fi + + if which busybox &> /dev/null; then + TIME_CMD=(busybox time) + elif which time &> /dev/null; then + TIME_CMD=("$(which time)") + else + echo "NOTE: No time command found, please install GNU time or busybox to measure memory consumption." + TIME_CMD="" + fi + + START_REF="$(git name-rev --name-only HEAD)" + trap "echo 'Returning to $START_REF...' && git checkout $START_REF" EXIT ERR INT + + cd "$BENCHDIR" + clean + mkdir "tmp" + cp -aL inputs grammars tmp/ + + for REF in "${REFS[@]}"; do + PACKCC="tmp/packcc_${REF//\//_}" + git checkout "$REF" + build + for GRAMMAR_FILE in "tmp/grammars"/*.peg ; do + GRAMMAR="$(basename "$GRAMMAR_FILE" .peg)" + [ "$REF" == "${REFS[0]}" ] && GRAMMARS+=("$GRAMMAR") + INPUT="$(ls "tmp/inputs/$GRAMMAR"*)" + benchmark + done + done + + print_results +} + +main "$@" diff --git a/src/subprojects/packcc/benchmark/grammars/calc.peg b/src/subprojects/packcc/benchmark/grammars/calc.peg new file mode 100644 index 00000000..c86faeb6 --- /dev/null +++ b/src/subprojects/packcc/benchmark/grammars/calc.peg @@ -0,0 +1,40 @@ +%prefix "calc" + +%source { +#include +#include +} + +statement <- _ e:expression _ EOL { printf("answer=%d\n", e); } + / ( !EOL . )* EOL { printf("error\n"); } + +expression <- e:term { $$ = e; } + +term <- l:term _ '+' _ r:factor { $$ = l + r; } + / l:term _ '-' _ r:factor { $$ = l - r; } + / e:factor { $$ = e; } + +factor <- l:factor _ '*' _ r:unary { $$ = l * r; } + / l:factor _ '/' _ r:unary { $$ = l / r; } + / e:unary { $$ = e; } + +unary <- '+' _ e:unary { $$ = +e; } + / '-' _ e:unary { $$ = -e; } + / e:primary { $$ = e; } + +primary <- < [0-9]+ > { $$ = atoi($1); } + / '(' _ e:expression _ ')' { $$ = e; } + +_ <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' / ';' + +%% +int main(int argc, char **argv) { + if (argc > 1) { + freopen(argv[1], "r", stdin); + } + calc_context_t *ctx = calc_create(NULL); + while (calc_parse(ctx, NULL)); + calc_destroy(ctx); + return 0; +} diff --git a/src/subprojects/packcc/benchmark/grammars/json.peg b/src/subprojects/packcc/benchmark/grammars/json.peg new file mode 100644 index 00000000..51e95c0b --- /dev/null +++ b/src/subprojects/packcc/benchmark/grammars/json.peg @@ -0,0 +1,23 @@ +%prefix "json" + +file <- _ (object / array) _ +object <- '{' ( pair (',' pair)* / _ ) '}' +pair <- _ string _ ':' value +array <- '[' ( value (',' value)* / _ ) ']' +value <- _ (object / array / boolean / number / string / null) _ +boolean <- 'false' / 'true' +number <- '-'? ('0' / [1-9] [0-9]*) ('.' [0-9]+)? ([eE] [-+]? [0-9]+)? +string <- '"' ('\\"' / [^"])* '"' +null <- 'null' +_ <- [ \n\r\t]* + +%% +int main(int argc, char **argv) { + if (argc > 1) { + freopen(argv[1], "r", stdin); + } + json_context_t *ctx = json_create(NULL); + while (json_parse(ctx, NULL)); + json_destroy(ctx); + return 0; +} diff --git a/src/subprojects/packcc/benchmark/grammars/kotlin.peg b/src/subprojects/packcc/benchmark/grammars/kotlin.peg new file mode 100644 index 00000000..82071039 --- /dev/null +++ b/src/subprojects/packcc/benchmark/grammars/kotlin.peg @@ -0,0 +1,452 @@ +file <- shebangLine? NL* fileAnnotation* _* packageHeader* _* importList* _* (filePart / _ / unparsable)* EOF +filePart <- (topLevelObject / (statement _* semi)) +unparsable <- [^\n]+ NL* { printf("Syntax error at byte %d\n", $0s);} + +### Converted from peg/kotlin/KotlinParser.g4 + +# options +# // SECTION: general +#kotlinFile <- shebangLine? NL* fileAnnotation* _* packageHeader _* importList _* topLevelObject* EOF +#script <- shebangLine? NL* fileAnnotation* _* packageHeader _* importList _* (statement _* semi)* EOF +shebangLine <- ShebangLine _* NL+ +fileAnnotation <- (AT_NO_WS / AT_PRE_WS) FILE NL* COLON _* NL* (LSQUARE _* unescapedAnnotation+ _* RSQUARE / unescapedAnnotation) _* NL* +packageHeader <- PACKAGE _ {printf("%s", $1);} _* semi? +importList <- importHeader+ +importHeader <- IMPORT _ identifier (DOT MULT / importAlias)? _* semi? _* +importAlias <- _ AS _ simpleIdentifier +topLevelObject <- declaration _* semis? +typeAlias <- modifiers? _* TYPE_ALIAS (_ / NL)* {printf("%s\n", $1);} _* (__* typeParameters)? __* ASSIGNMENT __* type +declaration <- classDeclaration / objectDeclaration / functionDeclaration / propertyDeclaration / typeAlias + +# // SECTION: classes +classDeclaration <- modifiers? (CLASS / (FUN __*)? INTERFACE) _ NL* {printf("%s\n", $1);} (__* typeParameters)? (__* primaryConstructor)? (__* COLON __* delegationSpecifiers)? (__* typeConstraints)? (__* classBody / __* enumClassBody)? +primaryConstructor <- (modifiers? CONSTRUCTOR __*)? classParameters +classBody <- LCURL __* classMemberDeclarations __* RCURL +classParameters <- LPAREN __* (classParameter (__* COMMA __* classParameter)* (__* COMMA)?)? __* RPAREN +classParameter <- (modifiers? _* VAL / modifiers? _* VAR / modifiers? _*)? __* {printf("%s\n", $1);} _* COLON __* type (__* ASSIGNMENT __* expression)? +delegationSpecifiers <- annotatedDelegationSpecifier (__* COMMA __* annotatedDelegationSpecifier)* +delegationSpecifier <- constructorInvocation / explicitDelegation / userType / functionType +constructorInvocation <- userType _* valueArguments +annotatedDelegationSpecifier <- annotation* __* delegationSpecifier +explicitDelegation <- (userType / functionType) __* BY __* expression +typeParameters <- LANGLE __* typeParameter (__* COMMA __* typeParameter)* (__* COMMA)? __* RANGLE +typeParameter <- typeParameterModifiers? __* simpleIdentifier (__* COLON __* type)? +typeConstraints <- WHERE __* typeConstraint (__* COMMA __* typeConstraint)* +typeConstraint <- annotation* simpleIdentifier __* COLON __* type + +# // SECTION: classMembers +classMemberDeclarations <- (classMemberDeclaration semis?)* +classMemberDeclaration <- secondaryConstructor / anonymousInitializer / companionObject / declaration +anonymousInitializer <- INIT __* block +companionObject <- modifiers? COMPANION __* OBJECT <(__* simpleIdentifier)?> {printf("%s\n", $1e-$1s != 0 ? $1 : "Companion");} (__* COLON __* delegationSpecifiers)? (__* classBody)? +functionValueParameters <- LPAREN __* (functionValueParameter (__* COMMA __* functionValueParameter)* (__* COMMA)?)? __* RPAREN +functionValueParameter <- parameterModifiers? _* parameter (__* ASSIGNMENT __* expression)? +functionDeclaration <- modifiers? _* FUN _* (__* typeParameters)? _* (__* receiverTypeAndDot)? __* {printf("%s\n", $1);} __* functionValueParameters _* (__* COLON __* type)? _* (__* typeConstraints)? _* (__* functionBody)? +functionBody <- block / ASSIGNMENT __* expression +variableDeclaration <- annotation* __* {printf("%s\n", $1);} (__* COLON __* type)? +multiVariableDeclaration <- LPAREN __* variableDeclaration _* (__* COMMA __* variableDeclaration)* _* (__* COMMA)? __* RPAREN +propertyDeclaration <- modifiers? _* (VAL / VAR) _ (__* typeParameters)? (__* receiverTypeAndDot)? (__* (multiVariableDeclaration / variableDeclaration)) (__* typeConstraints)? (__* (ASSIGNMENT __* expression / propertyDelegate))? (semi? _* setter (NL* semi? _* getter)? / semi? _* getter (NL* semi? _* setter)?)? +propertyDelegate <- BY __* expression +# TODO: better handling of empty getters and setters? +getter <- (modifiers _*)? GET __* LPAREN __* RPAREN (__* COLON __* type)? __* functionBody / (modifiers _*)? GET !(_* [^;\r\n]) +setter <- (modifiers _*)? SET __* LPAREN __* parameterWithOptionalType (__* COMMA)? __* RPAREN (__* COLON __* type)? __* functionBody / (modifiers _*)? SET !(_* [^;\r\n]) +parametersWithOptionalType <- LPAREN __* (parameterWithOptionalType (__* COMMA __* parameterWithOptionalType)* (__* COMMA)?)? __* RPAREN +parameterWithOptionalType <- parameterModifiers? simpleIdentifier __* (COLON __* type)? +parameter <- simpleIdentifier __* COLON __* type +objectDeclaration <- modifiers? _* OBJECT __* {printf("%s\n", $1);} (__* COLON __* delegationSpecifiers)? (__* classBody)? +secondaryConstructor <- modifiers? CONSTRUCTOR __* functionValueParameters (__* COLON __* constructorDelegationCall)? __* block? +constructorDelegationCall <- THIS __* valueArguments / SUPER __* valueArguments + +# // SECTION: enumClasses +enumClassBody <- LCURL __* enumEntries? (__* SEMICOLON __* classMemberDeclarations)? __* RCURL +enumEntries <- enumEntry (__* COMMA __* enumEntry)* __* COMMA? +enumEntry <- (modifiers __*)? simpleIdentifier (__* valueArguments)? (__* classBody)? + +# // SECTION: types +type <- typeModifiers? ( functionType / nullableType / parenthesizedType / typeReference) +typeReference <- userType / DYNAMIC +nullableType <- (typeReference / parenthesizedType) __* quest+ +quest <- !elvis (QUEST_WS / QUEST_NO_WS) +userType <- simpleUserType (__* DOT __* simpleUserType)* +simpleUserType <- simpleIdentifier (__* typeArguments)? +typeProjection <- typeProjectionModifiers? type / MULT +typeProjectionModifiers <- typeProjectionModifier+ +typeProjectionModifier <- varianceModifier __* / annotation +functionType <- (receiverType __* DOT __*)? functionTypeParameters __* ARROW __* type +functionTypeParameters <- LPAREN __* (parameter / type)? _* (__* COMMA __* (parameter / type))* _* (__* COMMA)? __* RPAREN +parenthesizedType <- LPAREN __* type __* RPAREN +receiverType <- (typeModifiers _*)? (nullableType / parenthesizedType / typeReference) +# parenthesizedUserType <- LPAREN __* userType __* RPAREN / LPAREN __* parenthesizedUserType __* RPAREN +receiverTypeAndDot <- (typeModifiers _*)? (nullableType __* DOT __* / parenthesizedType __* DOT __* / (simpleUserType __* DOT __*)+) + +# // SECTION: statements +#statements <- (statement (semis statement)*)? semis? +statements <- (statement _* (semis _* statement _*)*)? _* semis? +statement <- (label / annotation)* ( declaration / assignment / loopStatement / expression) +label <- simpleIdentifier (AT_POST_WS / AT_NO_WS) __* +controlStructureBody <- block / statement +block <- LCURL __* statements __* RCURL +loopStatement <- forStatement / whileStatement / doWhileStatement +forStatement <- FOR __* LPAREN _* annotation* _* (variableDeclaration / multiVariableDeclaration) _ IN _ inside_expression _* RPAREN __* (controlStructureBody)? +whileStatement <- WHILE __* LPAREN _* inside_expression _* RPAREN __* controlStructureBody / WHILE __* LPAREN _* expression _* RPAREN __* SEMICOLON +doWhileStatement <- DO __* controlStructureBody? __* WHILE __* LPAREN _* expression _* RPAREN +assignment <- directlyAssignableExpression _* ASSIGNMENT __* expression / assignableExpression _* assignmentAndOperator __* expression +semi <- (_* (SEMICOLON / NL) _*) NL* +semis <- (_* (SEMICOLON / NL) _*)+ + +# // SECTION: expressions +expression <- disjunction +disjunction <- conjunction (__* DISJ __* conjunction)* +conjunction <- equality (__* CONJ __* equality)* +equality <- comparison (_* equalityOperator __* comparison _*)* +comparison <- genericCallLikeComparison (_* comparisonOperator __* genericCallLikeComparison _*)* +genericCallLikeComparison <- infixOperation (_* callSuffix)* +infixOperation <- elvisExpression (_* inOperator __* elvisExpression / _* isOperator __* type)* +elvisExpression <- infixFunctionCall (__* elvis __* infixFunctionCall)* +elvis <- QUEST_NO_WS COLON +infixFunctionCall <- rangeExpression (_* simpleIdentifier __* rangeExpression)* +rangeExpression <- additiveExpression (_* RANGE __* additiveExpression)* +additiveExpression <- multiplicativeExpression (_* additiveOperator __* multiplicativeExpression)* +multiplicativeExpression <- asExpression (_* multiplicativeOperator __* asExpression)* +asExpression <- prefixUnaryExpression (__* asOperator __* type)* +prefixUnaryExpression <- (unaryPrefix _*)* postfixUnaryExpression +unaryPrefix <- annotation / label / prefixUnaryOperator __* +postfixUnaryExpression <- primaryExpression (_* postfixUnarySuffix)+ / primaryExpression +postfixUnarySuffix <- postfixUnaryOperator / typeArguments / callSuffix / indexingSuffix / navigationSuffix +directlyAssignableExpression <- postfixUnaryExpression _* assignableSuffix / postfixUnaryExpression / simpleIdentifier / parenthesizedDirectlyAssignableExpression +parenthesizedDirectlyAssignableExpression <- LPAREN __* inside_directlyAssignableExpression __* RPAREN +assignableExpression <- prefixUnaryExpression / parenthesizedAssignableExpression +parenthesizedAssignableExpression <- LPAREN __* inside_assignableExpression __* RPAREN +assignableSuffix <- navigationSuffix / typeArguments / indexingSuffix +indexingSuffix <- LSQUARE __* inside_expression (__* COMMA __* inside_expression)* (__* COMMA)? __* RSQUARE +navigationSuffix <- __* memberAccessOperator __* (simpleIdentifier / parenthesizedExpression / CLASS) +callSuffix <- typeArguments? _* valueArguments? _* annotatedLambda / typeArguments? _* valueArguments +annotatedLambda <- annotation* _* label? __* lambdaLiteral +typeArguments <- LANGLE __* typeProjection (__* COMMA __* typeProjection)* (__* COMMA)? __* RANGLE +valueArguments <- LPAREN __* RPAREN / LPAREN __* inside_valueArgument (__* COMMA __* inside_valueArgument)* (__* COMMA)? __* RPAREN +#valueArgument <- annotation? __* (simpleIdentifier __* ASSIGNMENT __*)? MULT? __* expression +primaryExpression <- thisExpression / superExpression / ifExpression / whenExpression / tryExpression / jumpExpression / parenthesizedExpression/ callableReference / stringLiteral / functionLiteral / objectLiteral / collectionLiteral / simpleIdentifier / literalConstant +parenthesizedExpression <- LPAREN __* inside_expression __* RPAREN +collectionLiteral <- LSQUARE __* inside_expression (__* COMMA __* inside_expression)* (__* COMMA)? __* RSQUARE / LSQUARE __* RSQUARE +literalConstant <- BooleanLiteral / CharacterLiteral / NullLiteral / RealLiteral / UnsignedLiteral / LongLiteral / HexLiteral / BinLiteral / IntegerLiteral +stringLiteral <- multiLineStringLiteral / lineStringLiteral +lineStringLiteral <- QUOTE_OPEN (lineStringExpression / lineStringContent)* QUOTE_CLOSE +#lineStringLiteral <- QUOTE_OPEN (lineStringExpression / EscapedIdentifier / UniCharacterLiteral / stringChar)* QUOTE_CLOSE +multiLineStringLiteral <- TRIPLE_QUOTE_OPEN (multiLineStringExpression / multiLineStringContent / MultiLineStringQuote)* TRIPLE_QUOTE_CLOSE +#multiLineStringLiteral <- TRIPLE_QUOTE_OPEN (multiLineStringExpression / MultiLineStringQuote / EscapedIdentifier / UniChracterLiteral / stringChar)* TRIPLE_QUOTE_CLOSE +lineStringContent <- LineStrText / LineStrEscapedChar / LineStrRef +lineStringExpression <- LineStrExprStart __* expression __* RCURL +multiLineStringContent <- MultiLineStrRef / MultiLineStrText / MultiLineStringQuote +multiLineStringExpression <- MultiLineStrExprStart __* expression __* RCURL + +inside_expression <- inside_disjunction +inside_disjunction <- inside_conjunction (__* DISJ __* inside_conjunction)* +inside_conjunction <- inside_equality (__* CONJ __* inside_equality)* +inside_equality <- inside_comparison ((_ / NL)* equalityOperator __* inside_comparison (_ / NL)*)* +inside_comparison <- inside_genericCallLikeComparison ((_ / NL)* comparisonOperator __* inside_genericCallLikeComparison (_ / NL)*)* +inside_genericCallLikeComparison <- inside_infixOperation ((_ / NL)* callSuffix)* +inside_infixOperation <- inside_elvisExpression ((_ / NL)* inOperator __* inside_elvisExpression / (_ / NL)* isOperator __* type)* +inside_elvisExpression <- inside_infixFunctionCall (__* elvis __* inside_infixFunctionCall)* +inside_infixFunctionCall <- inside_rangeExpression ((_ / NL)* simpleIdentifier __* inside_rangeExpression)* +inside_rangeExpression <- inside_additiveExpression ((_ / NL)* RANGE __* inside_additiveExpression)* +inside_additiveExpression <- inside_multiplicativeExpression ((_ / NL)* additiveOperator __* inside_multiplicativeExpression)* +inside_multiplicativeExpression <- inside_asExpression ((_ / NL)* multiplicativeOperator __* inside_asExpression)* +inside_asExpression <- inside_prefixUnaryExpression (__* asOperator __* type)* +inside_prefixUnaryExpression <- (inside_unaryPrefix (_ / NL)*)* inside_postfixUnaryExpression +inside_unaryPrefix <- annotation / label / prefixUnaryOperator __* +inside_postfixUnaryExpression <- primaryExpression ((_ / NL)* inside_postfixUnarySuffix)+ / primaryExpression +inside_postfixUnarySuffix <- postfixUnaryOperator / typeArguments / callSuffix / indexingSuffix / navigationSuffix +inside_directlyAssignableExpression <- inside_postfixUnaryExpression (_ / NL)* assignableSuffix / inside_postfixUnaryExpression / simpleIdentifier / parenthesizedDirectlyAssignableExpression +inside_assignableExpression <- inside_prefixUnaryExpression / parenthesizedAssignableExpression +inside_valueArgument <- annotation? __* (simpleIdentifier __* ASSIGNMENT __*)? MULT? __* inside_expression + + +#characterLiteral <- "'" (UniCharacterLiteral / EscapedIdentifier / [^\n\r'\\]) "'" +#stringChar <- [^"] + +lambdaLiteral <- LCURL {printf("\n");} __* statements __* RCURL / LCURL {printf("\n");} __* lambdaParameters? __* ARROW __* statements __* RCURL +lambdaParameters <- lambdaParameter (__* COMMA __* lambdaParameter)* (__* COMMA)? +lambdaParameter <- variableDeclaration / multiVariableDeclaration (__* COLON __* type)? +anonymousFunction <- FUN {printf("");} (__* type __* DOT)? __* parametersWithOptionalType (__* COLON __* type)? (__* typeConstraints)? (__* functionBody)? +functionLiteral <- lambdaLiteral / anonymousFunction +objectLiteral <- OBJECT __* COLON __* delegationSpecifiers __* classBody / OBJECT __* classBody +thisExpression <- THIS_AT / THIS !(Letter / UnicodeDigit) +superExpression <- SUPER_AT / SUPER (LANGLE __* type __* RANGLE)? (AT_NO_WS simpleIdentifier)? +ifExpression <- IF __* LPAREN __* expression __* RPAREN __* controlStructureBody? __* SEMICOLON? __* ELSE __* (controlStructureBody / SEMICOLON) / IF __* LPAREN __* expression __* RPAREN __* (controlStructureBody / SEMICOLON) +whenSubject <- LPAREN (annotation* __* VAL __* variableDeclaration __* ASSIGNMENT __*)? expression RPAREN +whenExpression <- WHEN __* whenSubject? __* LCURL __* (whenEntry __*)* __* RCURL +whenEntry <- whenCondition (__* COMMA __* whenCondition)* (__* COMMA)? __* ARROW __* controlStructureBody semi? / ELSE __* ARROW __* controlStructureBody semi? +whenCondition <- expression / rangeTest / typeTest +rangeTest <- inOperator __* expression +typeTest <- isOperator __* type +tryExpression <- TRY __* block ((__* catchBlock)+ (__* finallyBlock)? / __* finallyBlock) +catchBlock <- CATCH __* LPAREN _* (annotation _*)* simpleIdentifier _* COLON _* type (__* COMMA)? _* RPAREN __* block +finallyBlock <- FINALLY __* block +jumpExpression <- THROW __* expression / (RETURN_AT / RETURN) _* expression? / CONTINUE_AT / CONTINUE / BREAK_AT / BREAK +callableReference <- (receiverType? __* COLONCOLON __* (simpleIdentifier / CLASS)) +assignmentAndOperator <- ADD_ASSIGNMENT / SUB_ASSIGNMENT / MULT_ASSIGNMENT / DIV_ASSIGNMENT / MOD_ASSIGNMENT +equalityOperator <- EQEQEQ / EQEQ / EXCL_EQEQ / EXCL_EQ +comparisonOperator <- LE / GE / LANGLE / RANGLE +inOperator <- IN / NOT_IN +isOperator <- IS / NOT_IS +additiveOperator <- ADD / SUB +multiplicativeOperator <- MULT / DIV / MOD +asOperator <- AS_SAFE / AS +prefixUnaryOperator <- INCR / DECR / SUB / ADD / excl +postfixUnaryOperator <- INCR / DECR / EXCL_NO_WS excl +excl <- EXCL_WS / EXCL_NO_WS +memberAccessOperator <- DOT / safeNav / COLONCOLON +safeNav <- QUEST_NO_WS DOT + +# // SECTION: modifiers +modifiers <- (annotation / modifier)+ +parameterModifiers <- (annotation / parameterModifier)+ +modifier <- (classModifier / memberModifier / visibilityModifier / functionModifier / propertyModifier / inheritanceModifier / parameterModifier / platformModifier) __* +typeModifiers <- typeModifier+ +typeModifier <- annotation / SUSPEND __* +classModifier <- ENUM / SEALED / ANNOTATION / DATA / INNER +memberModifier <- OVERRIDE / LATEINIT +visibilityModifier <- PUBLIC / PRIVATE / INTERNAL / PROTECTED +varianceModifier <- IN / OUT +typeParameterModifiers <- typeParameterModifier+ +typeParameterModifier <- reificationModifier __* / varianceModifier __* / annotation +functionModifier <- TAILREC / OPERATOR / INFIX / INLINE / EXTERNAL / SUSPEND +propertyModifier <- CONST +inheritanceModifier <- ABSTRACT / FINAL / OPEN +parameterModifier <- VARARG / NOINLINE / CROSSINLINE +reificationModifier <- REIFIED +platformModifier <- EXPECT / ACTUAL + +# // SECTION: annotations +annotation <- (singleAnnotation / multiAnnotation) __* +singleAnnotation <- annotationUseSiteTarget __* unescapedAnnotation / (AT_NO_WS / AT_PRE_WS) unescapedAnnotation +multiAnnotation <- annotationUseSiteTarget __* LSQUARE unescapedAnnotation+ RSQUARE / (AT_NO_WS / AT_PRE_WS) LSQUARE unescapedAnnotation+ RSQUARE +annotationUseSiteTarget <- (AT_NO_WS / AT_PRE_WS) (FIELD / PROPERTY / GET / SET / RECEIVER / PARAM / SETPARAM / DELEGATE) __* COLON +unescapedAnnotation <- constructorInvocation / userType + +# // SECTION: identifiers +simpleIdentifier <- !(hardKeyword !(Letter / '_' / UnicodeDigit)) Identifier / ABSTRACT / ANNOTATION / BY / CATCH / COMPANION / CONSTRUCTOR / CROSSINLINE / DATA / DYNAMIC / ENUM / EXTERNAL / FINAL / FINALLY / GET / IMPORT / INFIX / INIT / INLINE / INNER / INTERNAL / LATEINIT / NOINLINE / OPEN / OPERATOR / OUT / OVERRIDE / PRIVATE / PROTECTED / PUBLIC / REIFIED / SEALED / TAILREC / SET / VARARG / WHERE / FIELD / PROPERTY / RECEIVER / PARAM / SETPARAM / DELEGATE / FILE / EXPECT / ACTUAL / CONST / SUSPEND +identifier <- simpleIdentifier (__* DOT simpleIdentifier)* + +hardKeyword <- AS / BREAK / CLASS / CONTINUE / DO / ELSE / FOR / FUN / IF / IN / INTERFACE / IS / NullLiteral / OBJECT / PACKAGE / RETURN / SUPER / THIS / THROW / TRY / TYPE_ALIAS / TYPEOF / VAL / VAR / WHEN / WHILE / BooleanLiteral + + +### Converted from peg/kotlin/KotlinLexer.g4 + + +# // SECTION: lexicalGeneral +ShebangLine <- '#!' [^\r\n]* +DelimitedComment <- '/*' (DelimitedComment / !'*/' .)* '*/' +LineComment <- '//' [^\r\n]* +#WS <- [\u0020\u0009\u000C] +#NL <- '\n' / '\r' '\n'? +Hidden <- DelimitedComment / LineComment / WS + +# // SECTION: separatorsAndOperations +#RESERVED <- '...' +DOT <- '.' +COMMA <- ',' +LPAREN <- '(' +RPAREN <- ')' +LSQUARE <- '[' +RSQUARE <- ']' +LCURL <- '{' +# /* +# * When using another programming language (not Java) to generate a parser, +# * please replace this code with the corresponding code of a programming language you are using. +# */ +RCURL <- '}' +MULT <- '*' +MOD <- '%' +DIV <- '/' +ADD <- '+' +SUB <- '-' +INCR <- '++' +DECR <- '--' +CONJ <- '&&' +DISJ <- '||' +EXCL_WS <- '!' Hidden +EXCL_NO_WS <- '!' +COLON <- ':' +SEMICOLON <- ';' +ASSIGNMENT <- '=' !'=' +ADD_ASSIGNMENT <- '+=' +SUB_ASSIGNMENT <- '-=' +MULT_ASSIGNMENT <- '*=' +DIV_ASSIGNMENT <- '/=' +MOD_ASSIGNMENT <- '%=' +ARROW <- '->' +#DOUBLE_ARROW <- '=>' +RANGE <- '..' +COLONCOLON <- '::' +#DOUBLE_SEMICOLON <- ';;' +#HASH <- '#' +AT_NO_WS <- '@' +AT_POST_WS <- '@' (Hidden / NL) +AT_PRE_WS <- (Hidden / NL) '@' +#AT_BOTH_WS <- (Hidden / NL) '@' (Hidden / NL) +QUEST_WS <- '?' Hidden +QUEST_NO_WS <- '?' +LANGLE <- '<' +RANGLE <- '>' +LE <- '<=' +GE <- '>=' +EXCL_EQ <- '!=' +EXCL_EQEQ <- '!==' +AS_SAFE <- 'as?' +EQEQ <- '==' +EQEQEQ <- '===' +#SINGLE_QUOTE <- '\'' + +# // SECTION: keywords +RETURN_AT <- 'return@' Identifier +CONTINUE_AT <- 'continue@' Identifier +BREAK_AT <- 'break@' Identifier +THIS_AT <- 'this@' Identifier +SUPER_AT <- 'super@' Identifier +FILE <- 'file' !(Letter / UnicodeDigit) +FIELD <- 'field' !(Letter / UnicodeDigit) +PROPERTY <- 'property' !(Letter / UnicodeDigit) +GET <- 'get' !(Letter / UnicodeDigit) +SET <- 'set' !(Letter / UnicodeDigit) +RECEIVER <- 'receiver' !(Letter / UnicodeDigit) +PARAM <- 'param' !(Letter / UnicodeDigit) +SETPARAM <- 'setparam' !(Letter / UnicodeDigit) +DELEGATE <- 'delegate' !(Letter / UnicodeDigit) +PACKAGE <- 'package' !(Letter / UnicodeDigit) +IMPORT <- 'import' !(Letter / UnicodeDigit) +CLASS <- 'class' !(Letter / UnicodeDigit) +INTERFACE <- 'interface' !(Letter / UnicodeDigit) +FUN <- 'fun' !(Letter / UnicodeDigit) +OBJECT <- 'object' !(Letter / UnicodeDigit) +VAL <- 'val' !(Letter / UnicodeDigit) +VAR <- 'var' !(Letter / UnicodeDigit) +TYPE_ALIAS <- 'typealias' !(Letter / UnicodeDigit) +CONSTRUCTOR <- 'constructor' !(Letter / UnicodeDigit) +BY <- 'by' !(Letter / UnicodeDigit) +COMPANION <- 'companion' !(Letter / UnicodeDigit) +INIT <- 'init' !(Letter / UnicodeDigit) +THIS <- 'this' !(Letter / UnicodeDigit) +SUPER <- 'super' !(Letter / UnicodeDigit) +TYPEOF <- 'typeof' !(Letter / UnicodeDigit) +WHERE <- 'where' !(Letter / UnicodeDigit) +IF <- 'if' !(Letter / UnicodeDigit) +ELSE <- 'else' !(Letter / UnicodeDigit) +WHEN <- 'when' !(Letter / UnicodeDigit) +TRY <- 'try' !(Letter / UnicodeDigit) +CATCH <- 'catch' !(Letter / UnicodeDigit) +FINALLY <- 'finally' !(Letter / UnicodeDigit) +FOR <- 'for' !(Letter / UnicodeDigit) +DO <- 'do' !(Letter / UnicodeDigit) +WHILE <- 'while' !(Letter / UnicodeDigit) +THROW <- 'throw' !(Letter / UnicodeDigit) +RETURN <- 'return' !(Letter / UnicodeDigit) +CONTINUE <- 'continue' !(Letter / UnicodeDigit) +BREAK <- 'break' !(Letter / UnicodeDigit) +AS <- 'as' !(Letter / UnicodeDigit) +IS <- 'is' !(Letter / UnicodeDigit) +IN <- 'in' !(Letter / UnicodeDigit) +NOT_IS <- '!is' !(Letter / UnicodeDigit) +NOT_IN <- '!in' !(Letter / UnicodeDigit) +OUT <- 'out' !(Letter / UnicodeDigit) +DYNAMIC <- 'dynamic' !(Letter / UnicodeDigit) + +# // SECTION: lexicalModifiers +PUBLIC <- 'public' !(Letter / UnicodeDigit) +PRIVATE <- 'private' !(Letter / UnicodeDigit) +PROTECTED <- 'protected' !(Letter / UnicodeDigit) +INTERNAL <- 'internal' !(Letter / UnicodeDigit) +ENUM <- 'enum' !(Letter / UnicodeDigit) +SEALED <- 'sealed' !(Letter / UnicodeDigit) +ANNOTATION <- 'annotation' !(Letter / UnicodeDigit) +DATA <- 'data' !(Letter / UnicodeDigit) +INNER <- 'inner' !(Letter / UnicodeDigit) +TAILREC <- 'tailrec' !(Letter / UnicodeDigit) +OPERATOR <- 'operator' !(Letter / UnicodeDigit) +INLINE <- 'inline' !(Letter / UnicodeDigit) +INFIX <- 'infix' !(Letter / UnicodeDigit) +EXTERNAL <- 'external' !(Letter / UnicodeDigit) +SUSPEND <- 'suspend' !(Letter / UnicodeDigit) +OVERRIDE <- 'override' !(Letter / UnicodeDigit) +ABSTRACT <- 'abstract' !(Letter / UnicodeDigit) +FINAL <- 'final' !(Letter / UnicodeDigit) +OPEN <- 'open' !(Letter / UnicodeDigit) +CONST <- 'const' !(Letter / UnicodeDigit) +LATEINIT <- 'lateinit' !(Letter / UnicodeDigit) +VARARG <- 'vararg' !(Letter / UnicodeDigit) +NOINLINE <- 'noinline' !(Letter / UnicodeDigit) +CROSSINLINE <- 'crossinline' !(Letter / UnicodeDigit) +REIFIED <- 'reified' !(Letter / UnicodeDigit) +EXPECT <- 'expect' !(Letter / UnicodeDigit) +ACTUAL <- 'actual' !(Letter / UnicodeDigit) + +# // SECTION: literals +DecDigit <- [0-9] +DecDigitNoZero <- [1-9] +DecDigitOrSeparator <- DecDigit / '_' +DecDigits <- DecDigit DecDigitOrSeparator* / DecDigit +DoubleExponent <- [eE] [-+]? DecDigits +RealLiteral <- FloatLiteral / DoubleLiteral +FloatLiteral <- DoubleLiteral [fF] / DecDigits [fF] +DoubleLiteral <- DecDigits? '.' DecDigits DoubleExponent? / DecDigits DoubleExponent +IntegerLiteral <- DecDigitNoZero DecDigitOrSeparator* / DecDigit +#IntegerLiteral <- DecDigitNoZero DecDigitOrSeparator* DecDigit / DecDigit +HexDigit <- [0-9a-fA-F] +HexDigitOrSeparator <- HexDigit / '_' +HexLiteral <- '0' [xX] HexDigit HexDigitOrSeparator* / '0' [xX] HexDigit +BinDigit <- [01] +BinDigitOrSeparator <- BinDigit / '_' +BinLiteral <- '0' [bB] BinDigit BinDigitOrSeparator* / '0' [bB] BinDigit +UnsignedLiteral <- (HexLiteral / BinLiteral / IntegerLiteral) [uU] [lL]? +LongLiteral <- (HexLiteral / BinLiteral / IntegerLiteral) [lL] +BooleanLiteral <- 'true'/ 'false' +NullLiteral <- 'null' +CharacterLiteral <- '\'' (EscapeSeq / [^\n\r'\\]) '\'' + +# // SECTION: lexicalIdentifiers +#UnicodeDigit <- UNICODE_CLASS_ND +Identifier <- '`' [^`\r\n]+ '`' / (Letter / '_') (Letter / '_' / UnicodeDigit)* +IdentifierOrSoftKey <- Identifier / ABSTRACT / ANNOTATION / BY / CATCH / COMPANION / CONSTRUCTOR / CROSSINLINE / DATA / DYNAMIC / ENUM / EXTERNAL / FINAL / FINALLY / IMPORT / INFIX / INIT / INLINE / INNER / INTERNAL / LATEINIT / NOINLINE / OPEN / OPERATOR / OUT / OVERRIDE / PRIVATE / PROTECTED / PUBLIC / REIFIED / SEALED / TAILREC / VARARG / WHERE / GET / SET / FIELD / PROPERTY / RECEIVER / PARAM / SETPARAM / DELEGATE / FILE / EXPECT / ACTUAL / CONST / SUSPEND +FieldIdentifier <- '$' IdentifierOrSoftKey +UniCharacterLiteral <- '\\' 'u' HexDigit HexDigit HexDigit HexDigit +EscapedIdentifier <- '\\' ('t' / 'b' / 'r' / 'n' / '\'' / '"' / '\\' / '$') +EscapeSeq <- UniCharacterLiteral / EscapedIdentifier + +# // SECTION: characters +Letter <- [\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376-\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E-\u066F\u0671-\u06D3\u06D5\u06E5-\u06E6\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4-\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0-\u0AE1\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B35-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58-\u0C59\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0-\u0CE1\u0CF1-\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E46\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065-\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE-\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5-\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400\u4DB5\u4E00\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A-\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5-\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC] +UnicodeDigit <- [\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19] + +# // SECTION: strings +QUOTE_OPEN <- '"' !'""' +TRIPLE_QUOTE_OPEN <- '"""' +QUOTE_CLOSE <- '"' +LineStrRef <- FieldIdentifier +#LineStrText <- [^\\"$]+ / '$' +LineStrText <- [^\\"$]+ / '$' +LineStrEscapedChar <- EscapedIdentifier / UniCharacterLiteral +LineStrExprStart <- '${' +TRIPLE_QUOTE_CLOSE <- '"""""'/ '""""' / '"""' +MultiLineStringQuote <- '""' !'"' / '"' !'""' +MultiLineStrRef <- FieldIdentifier +#MultiLineStrText <- !('"' / '$')+ / '$' +MultiLineStrText <- [^"$]+ / '$' +MultiLineStrExprStart <- '${' + +_ <- (WS / DelimitedComment / LineComment)+ +__ <- ([ \t\f\r\n] / DelimitedComment / LineComment)+ +WS <- [ \t\f] +NL <- _* ('\n' / '\r' '\n'?) _* +EOF <- !. + +%% + +int main(int argc, char **argv) { + if (argc > 1) { + freopen(argv[1], "r", stdin); + } + int ret; + pcc_context_t *ctx = pcc_create(NULL); + while (pcc_parse(ctx, &ret)); + pcc_destroy(ctx); + return 0; +} diff --git a/src/subprojects/packcc/benchmark/inputs/calc.txt b/src/subprojects/packcc/benchmark/inputs/calc.txt new file mode 100644 index 00000000..0c5c0611 --- /dev/null +++ b/src/subprojects/packcc/benchmark/inputs/calc.txt @@ -0,0 +1,10000 @@ +(30738 * 23264 / 22572 - 17872) +1640 * 8600 +(25293 + 5446 - 8430 + 6829) +(15570 + 16599 + ((1337 * 5346 - 11359 * 551) - 14960 * 30086)) +(15111 - 10927 * 32362 * 30025) +2359 * 5371 +349 * 4918 +17726 - 4964 +21226 * 10055 +(12300 + 29101 / 6378 * 20914) +((11797 * 14761 + (6890 + 15914 - (12389 * 7100 + 12149 - 21937))) * 15504 + 27079) +17781 * 4188 +((9967 + 13537 + 15725 - 20613) + 19564 + 30449) +6369 + 13026 +31538 + 16603 +(32429 - 11401 - 29047 / 7680) +25959 / 22650 +5895 - 13849 +(10312 - 29915 - 5292 + 23978) +30068 + 16134 +2861 * 8574 +26934 - 28979 +32018 / 6956 +6212 - 30754 +(9830 - 23018 / 13028 + 26275) +27569 - 21485 +7290 * 4748 +(20627 - 22687 - 31239 + 16810) +29095 + 8258 +(6580 * 906 / 8953 * 13690) +((((7022 - 21448 * 4992 + 3119) + 7593 - 19496) - 10951 - 9656) * 30712 - 5950) +10576 + 20743 +(10717 + 17747 * (10356 - 9307 + 11102 + 28593)) +13473 / 31245 +(12932 + 18199 - (28264 - 8372 - 137 * 8561)) +14984 - 30779 +31927 - 1032 +15865 + 14649 +9017 - 15493 +(25994 / 2721 * 7519 - 28718) +18363 * 4094 +32400 * 15307 +9955 - 29447 +10145 - 23332 +19398 / 27840 +25211 + 18210 +7390 / 14898 +9684 * 20873 +22019 * 25856 +(22917 * 12251 + 2116 / 30593) +6159 * 1093 +(3369 - 22622 * 189 + 25500) +13591 - 23285 +4624 - 8496 +1526 * 26734 +25487 * 24467 +26978 - 11784 +25231 / 32150 +(16562 + 9845 - 1800 - 26662) +13272 + 25482 +6100 * 2582 +11746 - 1865 +(12063 + 31285 / 31472 - 2136) +29673 + 3276 +7352 + 7640 +17332 - 10580 +20018 + 19408 +3789 - 29602 +(2698 * 21913 * 3475 * 18309) +28133 - 22075 +23938 + 8482 +31078 + 2157 +((2164 * 13086 - 27911 - 15836) + 16167 * 16942) +28747 + 24283 +7609 + 26933 +350 + 31322 +3211 - 24132 +17377 / 24456 +(5617 + 26664 / 15323 * 16105) +(11993 - 3222 + 6596 - 13502) +69 - 4410 +13148 - 26051 +29113 * 5140 +4971 - 2480 +9004 * 31434 +4938 * 12479 +22208 + 18717 +16219 - 19760 +(24354 + 28868 + 17160 + 891) +16612 * 15115 +(8901 + 18373 + 9219 + 3461) +32201 + 2520 +2198 + 8169 +16976 * 19706 +27944 + 21145 +((((14831 * 23714 / (6009 + 9540 * 20975 * 25927)) + 17053 * 30858) * 28367 - 6786) - (29865 - 6534 - 27873 + 9266)) +7094 + 206 +1073 * 12801 +((23077 + 20149 + 15143 - 27488) - 273 + 32595) +2194 + 9039 +24877 - 23845 +25295 / 5245 +8217 - 20458 +8546 + 27458 +(24309 + 12145 * (22443 - 30463 - 30236 * 1703)) +22813 * 10323 +3330 * 20141 +26507 * 9196 +29584 / 24636 +7149 * 13523 +16938 + 3809 +6294 + 12226 +8900 - 17000 +25208 + 19246 +((6037 * 13555 + 14284 * 21791) + (5349 + 3450 / 23612 + 28052)) +6675 / 6796 +19691 - 1212 +213 + 6075 +27091 * 136 +10669 + 26101 +12133 * 11535 +9656 + 18280 +(565 + 17828 - 1442 - 11480) +5163 - 28433 +20155 - 22361 +32304 - 24801 +20647 - 3930 +22777 * 28776 +23321 / 13717 +(17178 / 19708 + 986 + 12167) +20370 + 30148 +19384 / 19146 +21571 - 14130 +(24851 / 12795 - 15519 * 6649) +3138 * 21611 +28154 * 26774 +19783 - 12607 +4955 + 18822 +19545 + 24256 +17215 - 29977 +1408 + 8629 +16213 + 15310 +(15275 + 23538 + 21405 * 1105) +3630 + 20070 +15529 - 29199 +9142 - 11431 +23408 * 1114 +((25900 + 4274 * (24911 - 32542 * 10309 + 5346)) + (((11575 * 30450 - (29267 * 26970 + (3136 + 17669 / ((12060 - 31442 + 8633 + 32310) * (9411 + 818 * 20733 + 17653))))) / 11344 * 24312) * 14580 - 24497)) +13700 + 13632 +15957 - 18223 +(1557 + 346 + 32585 - 14061) +13411 / 25013 +11721 / 14292 +7388 * 30130 +9089 - 6362 +(14970 * 10975 + 26047 * 30934) +25741 * 31468 +((18291 + 5490 * 32468 + 1744) / 31399 + 14471) +((20897 * 1777 * (32727 / 7055 + 18317 + 20042)) / 29694 * 31329) +(24760 - 20648 * (5593 - 28482 + 10087 * 20703)) +28949 + 23916 +((10296 - 26205 * 7144 + 16039) * 26252 * 56) +18288 - 9099 +2911 + 8446 +24181 + 23159 +24631 * 10930 +24351 - 28742 +9105 + 8743 +23031 * 4316 +30420 + 31574 +(8318 / 29120 * 672 + 23957) +10406 * 28690 +2923 * 27254 +(8330 * 7744 - 22299 + 10942) +22344 - 19987 +1496 + 2564 +((3046 + 11944 + 26989 + 21418) - 1385 + 11817) +25723 + 27814 +21267 + 21342 +20936 * 2944 +26845 * 19725 +14069 - 7907 +2793 - 15917 +20638 + 15156 +(4239 - 3476 - 30309 + 11708) +27291 * 3936 +31941 * 9708 +24351 * 21910 +(21785 + 22414 * 6183 - 13624) +1832 * 13496 +15873 / 29782 +(14612 / 17926 * (((6878 + 3668 * (17770 - 4276 * 13093 - 4571)) + ((12047 - 21759 * 32610 - 12332) * 12183 - 13356)) * 28084 + 5010)) +32225 + 4402 +14236 * 20520 +14082 / 9476 +((7621 / 4222 - (((30925 + 2778 + ((((15941 * 6329 + 4321 - 15383) - 18553 * 297) + 15702 - 30333) - 3534 + 24773)) - ((30872 + 10789 + 18480 * 23129) * 30351 + 24229)) * 15168 / 29510)) + 761 - 4275) +22701 + 20509 +25571 + 6543 +17427 - 20317 +12637 * 7607 +7436 * 2072 +25519 * 22448 +1161 * 6743 +(16441 * 18665 + 17442 / 29564) +29208 + 2244 +(9969 - 6308 * 15788 + 24477) +22408 - 9239 +(31369 * 12152 * 27000 + 25185) +(8364 * 15610 + 18016 - 19371) +15626 * 19893 +(15977 - 9634 * 3280 * 2466) +28038 - 15379 +15332 - 748 +(10227 * 17128 / 1323 + 8809) +632 * 26935 +13650 * 10629 +29662 + 59 +11169 - 21997 +11684 - 31064 +((16241 - 1859 + ((8735 - 4189 / 25725 * 11254) + 16703 * 1303)) - 12447 + 770) +(27706 - 14823 * 18219 - 8403) +1096 - 20150 +(((31916 - 32280 + (17686 * 20864 + 2938 + 12659)) - 976 * 12429) - ((22495 + 11056 - 8113 / 32302) * (12947 + 18475 + 24002 + 1344))) +(26381 + 14564 + 22649 + 25579) +25173 * 18798 +23334 + 7119 +14936 + 7286 +7966 * 8457 +21356 / 18946 +31071 / 16787 +3682 * 5258 +27087 + 10536 +25013 * 18029 +(14269 - 18297 + 5923 * 21477) +((22522 * 32446 * 25930 + 17113) + 20486 * 22451) +(9412 - 16318 - 5352 + 12582) +31129 - 15157 +5162 / 23603 +10690 + 15733 +(17829 - 7520 * 13437 + 13974) +9488 * 17743 +6024 / 25571 +(5927 / 2178 * 11218 + 28906) +16895 * 5536 +(30590 - 12817 - 29716 + 32049) +29665 - 28910 +11435 * 16241 +24419 + 21630 +31759 * 14656 +4873 / 29234 +15572 + 18832 +(23833 * 9834 + 1113 / 31508) +((3065 * 1718 + 200 - 12759) - 16871 * 24762) +22097 - 1822 +2324 + 24512 +2533 * 8576 +1456 * 24595 +27050 + 10394 +14640 * 23498 +7792 + 30461 +((26032 - 15623 * 1997 + 30) * 29610 + 950) +24951 - 17755 +(16058 * 414 + 6783 + 21677) +9376 - 32673 +(25796 * 25848 * 4038 + 6599) +(1952 + 20135 * 26124 * 7306) +12291 - 26449 +4980 - 300 +(28482 * 26342 + 14699 + 12742) +4036 * 10520 +27995 + 13651 +((26746 - 32370 - 7669 + 19521) + 7964 * 19189) +(8512 * 28870 * 23008 - 24569) +(18156 - 8767 + 12612 * 22434) +((23888 * 5552 + (28132 * 2612 - 5289 + 8995)) * (10265 - 2635 + 26592 * 19887)) +14355 * 15627 +12900 + 24233 +20192 - 3431 +241 * 18936 +30668 * 13771 +4132 - 22926 +25074 * 8585 +13634 * 23647 +14419 / 19393 +4001 * 31779 +30721 + 11353 +(16792 + 21500 - 5865 * 127) +((14093 * 22221 + ((558 * 8253 - (28562 + 25729 - 1224 + 19291)) * 19394 + 15316)) * 11344 - 6877) +13593 - 16021 +15169 + 25189 +30858 * 29583 +(27827 * 23081 + 31247 / 2064) +14448 + 27054 +30843 - 30116 +23627 / 838 +30862 + 7548 +31547 + 13818 +16169 + 19291 +24093 * 15872 +11188 - 32211 +18469 + 17051 +17781 - 14794 +1672 * 11462 +(18143 * 11116 - 8118 + 18762) +21451 + 22476 +(10425 + 1195 - 4281 - 8751) +25399 * 24857 +((17881 / 4465 - 1195 * 19233) * 21199 + 23580) +3718 - 7690 +((29753 * 15564 / 28480 * 3254) * 14960 * 16808) +((15986 / 17147 + 24132 * 32446) * 14299 - 28226) +31846 * 26093 +32102 - 23859 +15904 * 30086 +2445 - 19230 +(15298 - 22323 + 22722 / 12455) +(11016 - 13619 * (6172 / 12052 + 4456 - 27989)) +17054 + 11784 +3222 - 28979 +(27842 * 6936 * 17585 * 639) +23668 * 17171 +(16119 * 26379 + 19926 * 26495) +((15326 + 11741 - 20805 - 13260) * 20990 - 22745) +12050 * 4356 +15056 / 21764 +21299 + 10263 +23843 - 17593 +27537 * 12718 +((9372 / 21711 / 2857 * 29068) * 8433 * 31642) +15605 * 6078 +32391 + 26019 +(23115 * 11770 - 8176 - 20952) +1743 * 16185 +20307 - 12413 +5946 * 26223 +25499 + 5652 +(1308 * 18017 * 12897 * 6873) +10752 * 19570 +(5008 + 9 - 29921 * 16374) +20750 * 28536 +(22335 * 5590 * 9619 + 24349) +18414 / 30188 +22322 - 13818 +8154 + 7068 +27313 + 30691 +(1123 * 3368 * (30001 - 16644 * (12306 - 14753 - 17914 - 8230))) +(2437 * 19709 * 24392 * 13519) +800 - 19137 +4171 - 20123 +(22280 - 30914 + 28304 - 1044) +11414 - 16576 +(16250 * 10876 - 30832 + 6904) +8606 + 21935 +3696 + 26632 +2375 + 22584 +2579 + 11504 +26385 * 15479 +((387 - 1101 + 17596 * 29244) - 19240 - 23802) +7204 + 30751 +10892 - 24718 +20805 * 13685 +31062 + 17893 +31746 - 29513 +13898 + 4176 +16861 - 10801 +6552 - 18788 +4543 / 21602 +20584 * 12612 +1038 + 790 +31751 / 31250 +24751 + 28369 +(22316 * 2648 * 19476 * 20247) +30569 + 18381 +(426 * 28225 * 12933 * 1575) +(15679 * 23610 - 30880 + 8522) +32446 + 22299 +17288 - 9470 +7680 + 24816 +(25980 - 9879 / 21850 + 28250) +30231 * 27135 +(13843 + 6561 * (9176 - 3216 - 15097 + 28206)) +17021 / 13186 +(646 - 14337 * 12151 - 14500) +(29693 + 2945 - 16313 * 31784) +6459 + 27702 +25894 + 24441 +4119 + 7229 +30024 - 32569 +17125 * 12070 +24066 / 6726 +30375 - 14429 +(((6610 - 31267 * 10666 + 31954) - 4335 * 10443) * 23478 * 3500) +30327 + 9427 +14306 + 10444 +(27166 / 8995 + 11750 + 10221) +20250 * 27204 +(28511 - 28992 - 1751 / 26887) +(30906 + 8043 + 22547 * 24638) +19527 / 685 +((32111 * 22259 - 3398 + 2494) * 27161 - 20169) +28116 * 19578 +13652 * 17678 +(25746 + 17734 * 24929 + 20578) +20967 + 18812 +(25604 + 22663 - 1166 * 8627) +12211 * 29336 +9698 / 5620 +23567 + 30102 +(((9440 / 19874 - 11313 - 26560) + 22437 * 5489) + 4059 - 8166) +(467 - 29276 + 13765 - 9774) +(16133 + 15914 - ((14910 / 3875 * 6429 + 18758) * (9018 - 8668 * 2698 * 18288))) +2283 + 19490 +30836 + 24698 +(10346 + 20354 - 16549 / 1327) +4478 + 2401 +31821 / 21676 +13207 - 4090 +4048 * 31361 +15430 + 21345 +(26949 - 21948 * 3750 + 27628) +21020 - 25859 +((9598 + 32368 + 29347 + 20374) * 17539 - 6694) +21371 + 15288 +26920 + 11145 +18822 * 30119 +(28541 + 1102 - 16777 - 2463) +28563 * 20483 +18165 - 28374 +13247 - 27928 +15170 + 30685 +30474 + 26294 +32095 + 12048 +21476 + 13010 +23180 * 7346 +23054 - 16102 +7820 + 24825 +18393 * 28104 +21189 * 12714 +(20868 * 23217 * 4753 - 6162) +11210 + 9171 +(10653 * 17024 * 23825 * 32451) +27164 + 20613 +22956 - 3511 +15263 * 18167 +1818 + 27899 +9591 / 5073 +21464 / 24477 +(11392 * 24347 + (32260 * 2479 - 23284 - 5865)) +13667 + 712 +((29321 - 8080 * (20784 + 8814 - 22133 - 24887)) - 19626 * 8737) +19902 + 21564 +((5442 - 8223 + 1214 + 1033) * 20760 + 2815) +(7993 - 5562 * 26301 - 27373) +4580 - 18176 +21470 + 12098 +2302 * 19140 +(31779 + 11211 * 22916 + 27594) +(23791 - 10546 / 10259 - 8598) +((8411 + 20601 + 7247 + 13524) - (27838 * 27766 + (19431 * 20888 + 16770 - 42))) +3007 - 5115 +24261 - 22191 +13246 - 13622 +28034 - 5410 +12421 - 12595 +11663 * 30799 +8490 + 31267 +16020 - 30712 +2587 - 22686 +9968 + 22218 +(13489 + 21455 - 30304 + 24625) +((13161 * 11668 + (((31854 * 22611 * 17922 / 6338) - 25642 * 2959) - 26590 - 25377)) - 13071 - 2189) +(30197 + 17200 - 6853 - 287) +22920 * 24612 +27488 - 1959 +18932 * 29658 +6816 - 5442 +26717 * 14044 +27108 * 12860 +(9395 * 26863 / (((12175 - 2816 * 2052 * 16635) + 32019 / 7585) - 31866 - 21166)) +7392 * 13702 +12605 - 28488 +8382 + 21965 +10560 - 7074 +4622 - 4078 +21541 - 18584 +26322 * 3953 +19161 - 29206 +9889 * 26539 +22830 / 18243 +18393 * 3709 +22420 - 9446 +24301 * 17172 +18054 - 16384 +19558 - 24155 +(8649 * 9502 * (12883 / 25082 + (22016 * 14854 - (7618 + 8596 - 6868 / 32446)))) +11157 - 1312 +31922 * 9436 +21058 * 18414 +26121 * 14983 +28266 * 24847 +(3115 + 7524 + 10178 - 15029) +25263 * 1493 +20838 + 383 +12993 * 19987 +28691 + 26301 +3528 + 6992 +(2326 - 8822 + 7504 + 11547) +(12925 + 10240 * 26871 * 14790) +22667 * 25051 +(3254 - 18274 + 24854 - 31215) +(3201 / 23389 * 821 + 29085) +29830 + 13156 +6828 + 28067 +(17129 - 2955 * (29950 + 31757 - 10341 * 32226)) +24066 - 20275 +23202 - 14724 +9891 * 1225 +17629 - 4913 +6009 + 16000 +(7639 / 30805 * 16930 - 28780) +(7429 + 8177 - (7413 * 31700 + (4404 - 1335 * 9116 / 2917))) +9997 - 8112 +((12271 + 12544 - 11005 * 18518) - 26373 - 12112) +22101 - 15352 +20964 / 15858 +(14318 * 31755 + 17573 - 738) +13002 + 31919 +(24658 - 12027 / (((24466 * 30750 + 4162 + 26353) + 29524 - 20574) * 29025 * 8759)) +10441 - 14880 +20931 * 2927 +10891 * 18464 +22922 - 13010 +(29439 + 1027 * 2963 * 128) +26705 * 25286 +343 - 639 +20369 + 29500 +(24984 + 27506 - 29 - 2612) +(2462 + 32175 * 9933 - 4264) +24285 - 3325 +21631 - 25174 +20323 * 27887 +18258 * 20021 +30432 * 31013 +17180 - 16902 +29736 - 31158 +17577 - 6706 +25432 - 906 +24777 - 28732 +(11112 + 31154 * 29841 * 6681) +25055 + 13203 +((31244 - 206 / 27258 - 11939) - 29634 + 26965) +10112 * 25070 +20355 * 18894 +(19741 * 2635 + 27666 / 12060) +15531 + 10097 +18879 - 23949 +30993 * 23035 +21605 + 20014 +(13230 - 21135 - 10039 / 8935) +27436 - 25893 +655 - 4826 +31664 * 7568 +9190 + 188 +16359 * 29108 +10604 + 3980 +1321 * 10271 +30385 * 22935 +11921 - 18778 +15745 - 10366 +27115 + 18765 +((2095 - 27853 / (8091 * 10652 + 8271 + 5576)) * 27646 * 32264) +(10594 + 9843 / 29870 - 27913) +14783 * 6497 +(16700 * 10820 * 11538 * 6111) +(18288 + 12044 - 4051 + 25311) +(14380 + 22854 - 24113 / 11663) +23878 - 9060 +5364 * 8228 +19499 + 15288 +(13244 + 23760 + (7432 * 17292 / 1283 + 18148)) +627 * 12273 +(22187 - 28819 + 18883 * 11618) +10069 - 26605 +23998 + 29153 +30404 * 12057 +12363 + 24828 +(26055 - 21239 * 20678 + 26358) +17684 - 26943 +20386 / 13946 +(7799 * 24907 - (27600 - 17925 + 20046 + 18357)) +412 - 29425 +26551 - 28693 +8215 - 24805 +134 + 13266 +(16639 - 173 - (9046 * 25655 - (4632 + 1596 / 27442 - 7100))) +9896 * 31648 +17129 + 26945 +9272 * 12423 +9358 * 10571 +14001 - 20800 +(30484 * 1257 + 20778 - 21235) +21716 + 8512 +(16308 + 10620 * (6991 * 31396 * 23908 + 27220)) +21069 + 780 +26783 / 1531 +(8878 * 9998 - 7523 + 14644) +14938 + 13414 +2504 - 7174 +5938 + 6898 +(1921 + 24857 + 13081 / 8568) +23806 - 6220 +11932 + 2944 +32705 + 32621 +20550 + 18280 +(19850 * 21895 - 4517 - 32258) +25754 + 4433 +10527 + 17731 +7357 * 7785 +((12789 * 22128 + (17441 - 26387 + 15164 * 6840)) + 18552 - 6114) +12004 + 3680 +17820 - 17759 +27957 * 12709 +30278 + 28047 +22430 + 27535 +10278 * 15120 +((20097 / 24534 - 1230 * 30145) * 3484 + 20651) +11337 * 17808 +9553 - 6820 +20816 + 1114 +((14582 - 12183 * 1069 - 10024) * (13489 - 2970 - 11310 + 22034)) +12055 + 4738 +(14978 * 13008 * (22912 + 26414 - (30759 + 9829 - 26056 - 27675))) +29482 - 26316 +19455 + 18119 +23493 + 27756 +23293 + 863 +(((16648 * 29405 - 15467 - 25782) * ((((22801 - 31887 * 25734 / 2276) + 31569 / 3905) - 27295 * 243) + 10778 * 14659)) - 10947 + 29436) +19882 + 571 +8161 + 5047 +14831 * 16315 +31567 - 392 +11774 + 14711 +15975 * 2201 +17711 * 4178 +3127 - 24491 +485 + 24688 +30526 + 4881 +(16364 * 8123 * 8035 - 29535) +17137 * 31035 +11407 - 12428 +16029 - 10179 +((23819 - 7302 + 15796 * 28985) + 16009 + 18403) +24918 + 20465 +23792 + 24999 +6703 / 3916 +21941 + 29407 +(31828 * 5628 * 4609 + 11630) +30202 + 12479 +(23612 + 15763 + 30780 * 27326) +11769 * 23342 +24124 - 9658 +27976 / 11114 +28 - 25124 +19308 * 1699 +(23199 + 10545 * (22933 * 11662 * (11325 * 2135 + 29242 + 11337))) +29657 - 30 +13345 * 5984 +12165 + 5883 +25460 + 159 +2745 - 3703 +(31586 - 20873 + (19202 + 23192 * 18961 - 13077)) +19151 * 20501 +27758 - 7372 +16434 * 30447 +25279 - 24445 +32112 - 24967 +(29232 - 12365 * 27071 + 28165) +20205 + 27619 +24740 - 25665 +31785 + 31955 +11954 + 4476 +32645 * 18265 +13130 - 902 +27575 * 6687 +5704 - 17919 +5617 / 8283 +(13246 - 11014 * 17371 + 3582) +11839 * 17352 +(8847 * 7914 - 28282 + 14161) +21397 - 6613 +(22891 + 14140 + 7628 - 16616) +14219 - 22489 +17981 + 2038 +23444 - 10234 +15576 - 13127 +10114 / 15651 +8545 * 61 +24674 + 19051 +((12813 - 6245 * (18115 / 25123 * 5892 - 18430)) * 19819 + 23032) +3616 - 6281 +32766 + 20632 +(26763 / 9279 + 368 / 30602) +24057 - 15188 +28890 + 23939 +16596 + 12279 +29569 / 19505 +13810 - 6861 +1546 * 2496 +20329 * 2245 +6369 * 29055 +13206 - 19749 +1047 + 24759 +5537 + 21872 +31622 - 29796 +15746 - 17848 +(7143 / 14281 - ((730 + 2806 + 17733 - 30937) - 25146 + 8272)) +7043 / 28350 +20535 + 14833 +27960 * 3383 +7083 - 21151 +9848 - 24828 +(25642 * 7602 * 3906 / 25699) +(8613 - 21330 - 27782 * 12223) +30990 * 27796 +10178 - 16870 +497 + 31472 +(((12902 - 31792 + 10973 * 8390) * 18830 + 27421) - 27796 + 15256) +13998 * 27851 +22192 * 7718 +2391 - 3325 +30838 + 9207 +20206 * 29654 +(10946 * 32472 * 16678 + 7944) +24905 + 27309 +30800 + 10997 +20311 - 25414 +(15761 * 23279 * 15653 + 24337) +3071 / 1458 +21899 * 27454 +(29434 - 1449 - 3691 - 7960) +15791 * 19869 +12119 * 31958 +(32139 * 6703 - 17194 - 23415) +(19514 - 3066 - (7470 + 31971 - 29964 / 14755)) +(30241 + 23062 + 17249 - 11630) +(22610 * 26274 - 11544 * 26719) +16311 * 5981 +8871 + 21612 +28763 / 14935 +27562 * 9890 +24512 * 5867 +14992 - 18535 +(19669 * 30690 - (14149 - 12048 - (13410 + 14315 + 18551 * 10256))) +29184 * 3273 +16343 * 6941 +(20093 / 29318 + 23883 + 17039) +(((17218 - 16446 + ((1477 - 17229 / (19107 + 12638 * 16256 + 14774)) - 15670 - 30864)) * 25165 + 29899) - 32306 * 9474) +(6896 + 10118 + 1506 * 31291) +8641 + 23376 +2649 + 21603 +4963 * 19826 +2116 - 17823 +31017 * 28956 +(11639 - 13348 + 15984 + 21345) +25342 * 18503 +2637 * 4655 +24959 - 2405 +2497 + 6488 +(20227 + 5525 * 10705 - 6795) +((6734 * 18218 + 31001 * 28528) * 22309 - 11398) +15670 * 9569 +28566 - 7015 +5895 * 6161 +13602 - 13870 +7850 + 2631 +9476 * 19912 +(24625 + 8352 + 23841 + 30905) +31228 * 14087 +9498 / 30296 +17886 * 29886 +(((4165 + 31900 - 816 - 13399) * 8610 + 31788) + 16522 + 10807) +1301 / 13507 +(20720 * 27583 / 31463 / 15157) +2829 - 4811 +31045 / 19407 +7956 * 5368 +25360 * 6090 +(3236 + 7637 * ((25977 + 1422 + 30596 + 5320) + 673 - 5667)) +(17784 - 27458 * 7190 * 13128) +15807 + 6886 +((19866 / 22263 + 28829 - 14040) + (((33 - 3785 * 27263 - 21646) + 7270 * 21570) + 19206 - 2032)) +15346 + 12310 +2849 + 18276 +17595 * 14435 +10900 + 2991 +(20842 + 9815 + 111 * 32389) +6946 * 4299 +(((32453 * 12072 + 21997 * 29324) - (32663 + 5708 / 4599 + 31322)) + (4806 + 24969 + (30945 / 7961 / 21746 + 19012))) +(31005 - 5151 - ((((8863 - 23838 * 25527 / 8376) - 1944 - 12705) + 1939 + 10476) - 29435 + 10225)) +31322 - 25233 +29036 + 20226 +5087 * 3318 +5012 + 32340 +((4895 + 2402 * 11403 * 26362) * 11488 + 20530) +15103 - 9325 +5975 + 30372 +13221 + 10837 +(13475 + 15534 * 26361 + 8115) +21388 - 19375 +21144 + 29884 +30847 * 18782 +17557 + 1888 +25016 + 925 +(24863 - 19580 + 7562 / 27141) +14753 + 8273 +2082 - 11574 +12747 - 28238 +26124 + 16783 +(26510 - 19938 * 24945 + 10085) +8540 + 3726 +16491 * 32700 +5330 - 6774 +(4585 - 23149 - 8459 / 22359) +(9336 - 27650 + 22580 - 19240) +4295 / 28710 +25041 + 14059 +23767 + 699 +14737 * 15553 +13254 / 29491 +17461 + 27398 +20423 + 5058 +(5228 * 1017 * (32659 + 15259 - 16428 - 22732)) +(23464 - 2012 + (3022 + 20435 * 14186 * 14936)) +(12155 - 481 + 7318 * 20345) +(3303 * 635 - 9072 + 32600) +19622 * 15192 +3698 * 32751 +29407 + 28559 +(((16909 / 22789 + 5270 * 17583) - (29235 - 8058 - 9512 - 3077)) - 25320 - 23484) +8742 - 1380 +(32715 * 1612 - 27861 + 22474) +8120 - 32328 +32222 + 14081 +15250 - 1564 +(12419 * 10123 - 5598 + 2412) +(30654 + 6813 - 6566 + 13965) +31968 - 28080 +20763 * 25574 +21933 / 29580 +18293 / 24488 +(4466 - 30987 - 32270 * 13750) +31000 + 4314 +8992 * 14841 +28057 - 5795 +28846 - 20000 +29379 * 20302 +4296 + 22213 +(11194 + 8171 * 4092 / 11291) +14072 + 27151 +28576 / 17938 +((3293 * 21985 - 15922 + 29938) * 29184 - 8193) +(24551 - 30141 * 29731 / 31437) +(28257 - 21492 + (17091 + 6316 + ((5008 + 4332 + 18530 - 12055) - 25121 - 27267))) +(29077 - 10069 - 25152 - 25269) +30814 - 27977 +(((31080 / 4982 + (13238 / 27700 * 13683 - 31545)) * 26984 - 23861) * 16234 * 24468) +(30972 - 13896 - 19920 - 15496) +1687 * 13826 +15961 + 21787 +25003 - 1743 +(14440 * 21204 - 22529 - 7581) +14220 - 16646 +24446 + 11752 +21908 + 554 +10709 * 9356 +9441 - 7832 +19922 * 8351 +2970 - 19080 +(7624 - 11362 * 30972 + 1081) +9621 * 27431 +(13664 * 10684 * 31766 * 26672) +17487 - 17843 +27522 - 31518 +16725 + 24283 +32130 + 22224 +32418 + 8732 +(22717 + 19051 - (8262 + 13313 * 21864 + 29344)) +27832 / 4825 +17877 - 15534 +9608 - 15731 +(15470 - 23950 * 23620 - 27926) +28040 + 20443 +15401 / 10406 +7116 - 5380 +20843 - 12667 +17006 * 30135 +12020 * 13349 +(11341 * 22398 * 31427 - 11384) +28463 * 9869 +12139 + 6696 +6823 * 8816 +22856 - 2694 +(3312 * 28423 * 9632 + 5248) +11720 * 19660 +6047 * 30189 +20581 * 20857 +(11491 - 9670 * 24011 * 5923) +2927 - 3901 +5177 * 24260 +(6103 + 19213 - 16462 + 28431) +26677 + 19840 +20825 - 25583 +(((20579 + 21000 - 3110 - 13610) * 23151 + 15265) * 8699 * 1932) +(12610 * 3521 / 32117 + 28655) +2867 * 30223 +4352 + 28457 +2192 * 14141 +4455 - 7277 +18446 * 2494 +31077 - 6299 +2470 + 1467 +24244 + 7091 +(17954 + 15780 - 25867 - 12857) +(18583 - 14507 + 7568 * 22248) +16991 - 27897 +26276 * 10326 +25017 + 31414 +(15888 + 29784 - 13362 / 789) +24507 - 20061 +11854 / 5111 +(24719 + 19606 * 6411 - 21719) +2206 + 13486 +13360 - 16127 +21667 + 10165 +14623 + 30166 +(26748 * 28504 / 297 - 17224) +29801 - 10300 +5162 * 8266 +17541 / 27779 +(31 - 26415 - 2222 + 16208) +(22146 * 5782 + (12139 * 18548 - (17725 * 9500 - 12202 * 19140))) +30193 + 22046 +24416 - 21150 +14096 + 2402 +(((10141 - 32421 * 9292 + 26139) * 24108 - 4564) * 11605 - 20892) +668 + 22996 +5694 + 17583 +13335 * 29486 +26681 - 13504 +25553 + 23687 +13338 * 15564 +((21781 - 30953 - 8450 + 24455) + 26313 - 501) +7817 - 32735 +7387 + 9877 +(((((18143 * 12185 + (19671 * 6981 + 1024 + 20677)) - (17299 + 14705 * 32439 - 499)) * 22101 + 27833) - 24360 * 7196) * (25059 - 6994 - 21562 * 6695)) +16586 - 5203 +15882 - 10341 +24829 - 27919 +(20473 + 30180 + 20246 * 2186) +16991 + 27897 +26650 + 5192 +9558 - 31320 +21826 - 18799 +16959 - 26078 +15087 - 28467 +(10479 / 17824 + 21421 * 26339) +1295 + 9773 +((1494 + 20226 * 19653 * 3989) * 5526 * 23002) +9513 * 6023 +5798 + 29998 +7918 * 30979 +24242 / 25560 +16536 - 16952 +3661 - 5499 +(29107 + 3632 * 21804 - 21347) +((6884 * 9818 * (24461 * 6826 / 31989 - 8081)) + 29273 * 1047) +((17811 + 27750 + 27461 - 8637) * (18869 + 27106 * (16758 / 5869 - 23910 * 9391))) +18179 - 29808 +18970 * 1629 +31110 - 86 +26058 - 17583 +3113 + 20951 +(16734 + 6380 + 27196 - 30993) +29473 * 24360 +474 + 1544 +28603 - 16934 +(14792 + 5539 - 32096 + 10766) +(9084 - 12750 - 9988 + 23494) +(((2587 * 10513 - 8793 - 2110) + 22397 + 16645) + (10591 + 26020 / 8055 - 11796)) +15454 + 28209 +7208 - 10427 +(16507 * 7131 * (19153 + 31468 - 21396 - 17962)) +4413 * 31252 +(15315 * 31327 * 29648 - 7312) +19294 - 30469 +25556 - 30525 +31163 + 8050 +7251 * 19787 +1645 + 9138 +3256 * 14677 +14486 * 1876 +866 / 565 +10384 + 4294 +15889 * 18329 +27463 + 22993 +(16644 * 16096 / (12451 - 31198 + 29258 / 15006)) +25287 + 28193 +5265 * 30524 +15450 - 998 +8777 / 23242 +((((3364 + 30282 - 13175 + 6717) + 7528 * 14950) - (8077 - 15504 * 26492 - 5077)) - 17031 * 24999) +24783 + 16530 +15738 - 17407 +7317 - 20453 +(24706 * 11826 + 13081 * 14096) +8325 + 19664 +6343 + 30827 +11518 + 18287 +(11762 - 22682 + 3837 * 2043) +4820 + 16323 +(3378 * 13399 * 12254 + 5119) +(12510 + 3308 + (26124 + 11318 * (24869 / 30042 - 742 + 21266))) +22283 * 16042 +((((20757 - 23126 - 30884 * 24618) + 23453 - 11204) - 18184 + 21520) + 13355 * 30096) +3012 - 25678 +27003 - 10126 +(30590 - 8586 - 31545 - 5277) +8133 + 23193 +5686 - 22162 +15237 * 29477 +15897 - 25237 +30204 + 5191 +(11382 - 20811 * (2518 * 31833 - 22271 + 16477)) +4756 - 8019 +11331 + 16917 +7934 + 8331 +(12754 - 25408 + 15679 * 12090) +8032 * 17180 +7435 * 8648 +(32061 - 30089 + 15008 - 17938) +8223 * 5565 +((19177 + 17243 - 17698 + 12874) + 16311 + 13015) +261 - 3427 +22277 * 20638 +31867 * 28409 +((23675 * 2644 - 26209 + 9814) - 29661 / 27628) +(887 + 10667 - 27913 + 24079) +(18935 * 14187 * (3100 * 9866 * (19324 * 11742 * ((11671 + 1913 + 27775 * 400) * 9917 * 26918)))) +(30307 + 11925 - 30453 * 21102) +6586 + 14208 +21538 + 24650 +14823 - 22694 +4852 - 27180 +18995 * 30860 +13325 + 14576 +16273 - 27949 +24410 * 2878 +12481 * 19417 +18704 / 11838 +30338 + 13359 +(4031 * 19197 - 10350 / 27949) +19727 * 29197 +5418 / 3742 +4984 + 21642 +18391 / 7861 +8540 - 17374 +23914 * 7400 +9787 * 18889 +(27620 - 7487 + 27312 * 2620) +27981 / 5963 +19349 * 3319 +23369 - 24550 +25018 / 8542 +18913 * 32010 +13232 + 30672 +((((2 + 27313 * 17386 - 23306) + 1701 - 2361) * 21236 - 11824) / 17459 * 20799) +32715 * 21755 +((25943 + 3764 + 23430 * 279) + 17666 * 28758) +(16511 * 14559 + 24439 + 8029) +31462 * 12930 +4061 - 24766 +17601 * 20718 +22956 + 8996 +(31658 * 14604 - 13633 * 22354) +(17596 * 3245 + 21392 + 14598) +3318 - 5728 +30344 * 28798 +18244 + 19171 +24420 - 31751 +2300 + 30289 +(31954 - 21276 * ((((26910 / 1548 * 18528 + 11235) * (22969 - 5138 * 25361 - 3221)) * 29575 - 29479) - 19317 * 25637)) +12011 - 19907 +16709 * 27787 +847 - 12610 +(3450 + 19251 - 16515 - 3938) +28864 * 5385 +12113 + 18573 +2151 * 25425 +8678 + 16121 +17355 + 2860 +10843 + 3764 +4652 - 26887 +(17666 * 17142 * 8401 * 18241) +20589 / 4369 +(5033 / 28097 * 23564 * 24681) +9002 + 27519 +23461 - 20709 +10106 - 14229 +((24856 + 16753 - 16142 - 16427) / 28828 - 8518) +27124 + 19539 +13370 - 11678 +10316 - 9663 +13735 - 21806 +31453 - 6852 +18035 * 24168 +28978 + 20182 +1372 + 3179 +(20007 * 20801 + (23787 * 16046 + ((((3655 * 30162 - ((4053 + 29315 * 22164 * 11025) + (4314 - 5643 + ((20838 * 31202 - 11742 / 21787) - 32560 - 8756)))) + 26939 - 131) * 8728 * 32462) - 19178 + 20356))) +4168 / 7716 +20028 * 19727 +11528 / 24609 +11562 + 30911 +11765 + 31970 +14908 * 9663 +3064 + 32124 +15012 + 10107 +28202 / 2453 +29112 - 20969 +(5040 + 7503 - 21195 + 11598) +7590 + 31608 +7831 - 18427 +23068 * 12640 +2903 - 22787 +19272 + 538 +(12451 + 27687 * 16407 - 26857) +29124 - 26371 +18415 + 25346 +19062 + 29186 +9146 * 5007 +16621 + 4504 +23223 + 6761 +((27705 * 7055 + 19066 * 31365) + 408 * 21651) +(3109 - 31010 + 17838 * 1976) +15445 - 31174 +13962 * 29543 +(9122 - 21689 + 8335 + 26424) +9513 + 7558 +13065 / 19907 +(13204 - 11317 * 8131 * 6900) +11705 - 2970 +(1400 / 19776 - 4655 + 16960) +(27566 - 11567 / 24211 - 22857) +17978 - 5111 +14648 + 26138 +11955 - 22388 +24927 + 3894 +(4278 - 6154 / 13451 + 26086) +(26764 + 23336 / 2488 + 5300) +18010 + 3175 +(21223 / 29154 + 14955 + 30817) +3492 - 13294 +17656 + 229 +((3866 - 30502 - 49 + 32598) * (20966 - 5807 - (4527 - 11799 * 31916 * 31325))) +(17592 - 31390 * (5301 * 28972 + 10624 * 30425)) +20785 + 27059 +(2954 - 31418 / 9413 - 20608) +(15133 * 15528 * 9252 - 21385) +(21337 + 16240 * 3949 - 12089) +20350 + 22561 +18557 - 13257 +13493 / 18932 +30316 + 11885 +16396 + 9480 +854 * 17355 +19383 * 18343 +15723 - 30494 +20854 * 30592 +19347 - 6786 +(9512 - 31255 * 27181 * 17066) +(8847 * 24370 - 31574 - 16621) +6271 * 27784 +(27613 * 6473 - 9193 - 12877) +27000 * 30172 +13702 + 4035 +13723 * 7586 +25670 - 1275 +20230 + 10297 +27994 + 27102 +15515 + 13815 +28973 * 11651 +13869 + 16415 +30220 - 30931 +(25457 + 15488 * 19200 * 21356) +(8096 - 5013 + (10915 + 7854 / 11327 + 10701)) +20332 + 13753 +31607 - 16289 +23335 + 10570 +(7005 - 26279 * (((((9406 / 32419 + 30270 - 31158) * (((4440 / 9841 * 4197 + 949) - 14228 - 4904) + 10599 * 8590)) - 18970 - 14950) + (13713 * 6921 - 11365 * 23991)) * 4773 * 20538)) +17840 * 15575 +6988 + 26899 +29994 * 28184 +2042 * 22592 +21517 + 10273 +10572 - 28544 +14531 - 30803 +((4214 / 30951 * 5457 * 15215) + 11746 + 12927) +5108 + 21696 +(16423 + 27590 * ((15248 - 19079 * 646 + 8058) * 14181 - 26196)) +6514 + 23366 +6244 * 14336 +(15423 * 28773 * 27709 - 3243) +11097 * 2617 +8895 / 27204 +22835 - 3438 +(20918 - 24787 - 31677 + 807) +22011 - 28747 +17479 + 26957 +(30294 + 14857 + 30016 + 15111) +(3932 * 9274 + 1258 - 23684) +((26828 * 19658 + 24558 * 11225) * 25253 + 20039) +8444 + 1753 +18904 + 25447 +(22725 + 6887 - (5121 - 15284 + 6354 + 9215)) +489 + 21595 +11164 + 21723 +12906 - 20659 +30001 - 3641 +5979 + 4488 +(4585 / 19196 + 425 * 29959) +15293 - 17860 +(5239 * 29256 - 32209 * 29179) +16970 * 31153 +4746 + 30307 +(29079 + 11793 * 11808 - 10795) +21174 + 4909 +20681 - 4322 +326 + 10449 +30886 - 20604 +26201 * 2443 +(16797 * 21469 - ((29903 - 21468 * 31927 * 27587) - (29537 - 23069 + 2903 + 3998))) +5448 - 24534 +1853 + 15947 +6637 / 6008 +30931 + 31116 +((8409 + 12905 / 12571 + 17629) - ((21269 + 26664 * 8082 - 13472) * 2675 - 8737)) +8334 - 16555 +3693 / 24904 +3842 - 1322 +20683 - 8007 +22849 + 32747 +31783 + 32224 +(15620 / 16939 - 22958 - 28887) +12268 - 16660 +27159 * 16409 +1865 * 32128 +18405 + 8900 +18069 + 30413 +27538 + 15637 +22146 * 10756 +28822 * 27835 +9482 * 11293 +7305 * 21561 +18461 - 19689 +(1914 + 23418 + ((28770 * 23757 / 26597 * 20343) - 23417 + 922)) +(31904 * 22322 * 27063 - 32638) +12187 + 31848 +25428 * 16898 +((4679 - 4333 * (27534 - 13234 - 21217 - 15406)) / (32177 + 9049 - (20119 * 30719 - (12203 + 30864 / 8473 * 29684)))) +(17924 + 24942 + 10781 + 1898) +3528 * 14072 +(3468 * 11764 + 10380 * 12569) +20439 + 18014 +18620 - 21270 +(20195 * 28438 - 19650 * 13121) +(11219 + 16761 + 28423 / 24700) +26674 - 27721 +5521 - 29636 +((8802 + 11066 * 31294 * 1123) * 9957 + 6741) +15392 - 18741 +13633 - 13978 +(19493 + 16539 + 13674 * 31349) +13513 - 29488 +15699 - 10636 +11952 + 23651 +1830 - 23954 +15837 * 5650 +28506 + 26750 +(((27811 * 1120 * 7222 + 3539) * 2298 - 24197) + 10547 * 445) +951 - 11990 +10821 + 18470 +18458 * 9585 +((17445 - 13251 + 27029 * 1708) - 22878 * 22546) +24720 + 12274 +9615 * 22914 +7115 - 19200 +6538 - 10113 +12762 + 14774 +1178 + 5120 +17428 * 9545 +29183 - 18461 +21124 + 3673 +(17974 * 14274 * 793 / 3562) +13965 - 18491 +(19381 * 3579 + 17218 * 27150) +(1539 + 28942 + (3594 * 11190 * ((26777 - 26545 + 10722 - 26069) - ((10715 - 3670 + 31574 - 4529) / 31379 + 23108)))) +30241 - 30840 +18948 * 11390 +((17345 - 12489 - 27824 * 12223) / 20680 - 12616) +18101 + 24861 +29583 + 19200 +16505 / 31098 +17190 * 5255 +21862 - 24130 +13554 - 6707 +23736 - 11554 +6811 - 13363 +(30628 + 23545 * 7698 + 9217) +32661 + 29523 +25400 / 3121 +14277 / 16619 +6656 - 9408 +30345 * 21926 +((26187 - 16736 - 27512 + 27365) * 23301 * 21252) +11174 - 3695 +22278 - 6826 +((27567 + 27514 - (23847 + 5053 * 15917 * 14602)) + 29435 / 7296) +24480 + 6626 +1958 + 10600 +3676 - 15931 +15324 * 15727 +13892 + 14934 +(4244 + 21187 * (16632 - 19184 + ((15222 * 24803 * 7760 + 29299) / 26909 - 19464))) +4203 - 19009 +(30069 * 12759 - 19344 * 630) +23751 + 21863 +4861 + 2698 +22936 + 30928 +25584 - 17844 +8381 + 866 +5552 - 15332 +23704 - 12186 +4356 * 11216 +21366 * 13225 +2040 - 27857 +5806 + 3218 +((697 * 15496 + 14040 - 15205) + 20969 - 4361) +11015 * 21220 +16810 - 20782 +10028 * 28332 +20551 - 13645 +565 * 24735 +(26393 * 11062 - (8416 + 2154 + 13474 + 18115)) +30195 * 30539 +8443 * 7336 +14218 + 3668 +(26294 * 29192 + 7696 * 4072) +11396 + 31985 +10638 - 3338 +14597 - 22477 +1540 + 6320 +((20311 - 26249 - 1364 / 21910) + 17606 * 11093) +(24534 + 22198 - 10844 - 20591) +(12626 * 32696 + 29947 * 6463) +(8526 + 28447 + 20677 - 15987) +(8722 * 14210 - 25917 - 4755) +21976 * 7918 +19677 - 23013 +29539 * 14235 +24365 + 1938 +16062 * 23522 +(27124 * 13609 + 7266 - 18678) +3128 * 23992 +9706 / 25085 +17619 + 14560 +188 + 5129 +14225 + 23509 +(3483 + 770 + 17391 * 8097) +14060 - 24862 +(19102 - 19201 + (23703 + 26395 * 26863 + 31377)) +26901 / 22818 +1079 + 3175 +25806 + 13449 +2364 * 9567 +(2187 + 19064 / ((1224 - 7334 - 5347 * 27501) / (2601 + 24609 - 11877 - 28949))) +4878 + 27098 +12152 - 7351 +12255 + 10419 +(17154 * 10854 + 11129 * 8425) +(((1213 + 7026 / 212 + 15861) * 24965 - 11636) * 13370 + 16464) +18990 / 19913 +30389 - 17565 +15767 - 13401 +3626 + 2150 +18735 - 9372 +(23172 + 23112 - (30813 - 12132 - 31814 * 7935)) +31822 * 14055 +(12595 - 6594 - 3892 - 22237) +6955 * 12683 +((5392 + 15979 + 1048 - 23667) + 27074 - 4996) +(13700 + 18211 * 17262 - 28801) +10998 * 21101 +(5977 * 12515 + 16985 - 31054) +14405 - 11267 +5596 + 13291 +31268 + 12523 +12138 + 15742 +(10645 + 16489 * 14975 + 6009) +24747 * 1585 +((((7806 * 28358 - 22416 + 27630) + 20704 - 13092) - 2568 - 3448) / 30155 + 13229) +14810 + 29920 +(26104 * 3846 * 19132 * 22603) +(1579 + 11559 + 20822 * 12675) +13534 + 3054 +(9993 + 18827 + (10089 * 31869 + (13140 * 7220 + 24863 + 24000))) +29065 - 13211 +1297 + 1702 +17942 * 13150 +21869 - 25810 +18477 + 5790 +7542 + 20391 +7717 + 4615 +20724 - 4851 +3323 * 12803 +(18890 * 22274 - 6629 * 24129) +3540 * 1215 +31356 - 4257 +28140 + 32597 +30545 - 28740 +8259 - 13649 +19157 * 5824 +(1270 + 15378 * 1866 + 15035) +8955 - 9901 +20237 + 10160 +(30062 + 11647 + 23097 - 7419) +((16459 + 10418 * 2093 + 21072) - 10586 / 18695) +19043 + 13181 +(4186 + 15417 + 9514 - 21274) +(2748 - 4220 + 19265 / 5722) +23957 - 31567 +6300 - 7928 +(7705 * 20567 + 20703 * 21504) +10294 + 20652 +3978 * 14454 +7736 * 5919 +32099 + 14028 +16008 + 17990 +14817 + 19791 +18467 - 27998 +366 / 4485 +7989 / 30308 +152 - 3303 +(832 - 16494 + 13052 + 13996) +25243 / 9467 +32226 + 10183 +(24392 + 20637 * 5662 + 5756) +17759 / 8364 +13136 - 19846 +5048 * 2251 +31776 + 726 +24312 + 16882 +6892 + 19991 +32658 + 26502 +((15036 + 9875 * 24508 * 5468) - ((29192 * 8054 / (28003 * 27761 / 10247 / 26166)) + 14314 * 186)) +29836 + 10129 +11527 - 31135 +28670 * 7452 +1718 + 8925 +32755 + 4528 +((16174 * 27593 * 5080 + 7229) + 14263 + 7580) +27192 * 481 +30093 / 28655 +(24739 + 556 + 29867 * 29530) +(21564 * 7004 - 23787 / 14535) +(27850 * 25037 / 17540 - 742) +10635 * 19113 +26662 + 490 +((27650 + 8311 + 4017 * 15330) * 15522 - 20729) +25219 * 10754 +19006 - 13439 +(22173 - 15842 * (13211 * 7124 - 7463 / 2142)) +31377 + 29741 +17963 - 29216 +8688 - 4624 +2552 - 22410 +(3623 - 20445 / (9587 * 27793 + 9854 + 3133)) +(539 * 8154 * 22637 + 9139) +3477 - 9172 +29180 * 7686 +1232 * 23449 +32390 + 20441 +17914 * 21047 +9992 * 29694 +32736 * 17919 +19918 * 18878 +(22735 * 12788 - 28367 + 1896) +(6626 + 31100 + (((6006 - 2548 * 5917 + 19831) + (31980 / 25191 - 11062 + 9576)) * 26628 / 28028)) +17566 + 21778 +((23691 + 28120 * 13266 - 26666) * 15755 * 11281) +14597 * 90 +22004 / 18673 +2943 * 2415 +(19847 - 11746 - 1555 - 6470) +(12520 * 16383 - 5994 / 1492) +28275 - 29412 +2175 + 551 +(19021 - 29832 - 12157 * 11475) +11395 + 17635 +16887 * 6371 +7057 * 30158 +(25948 - 14876 + 5519 - 4829) +7781 - 293 +(28230 * 15096 + ((17504 + 12400 * 32200 + 27252) - 4552 - 1243)) +((22971 - 5710 + (8848 + 4154 / 1627 * 22079)) - ((3395 - 28567 + 12509 * 6893) - 12888 + 4887)) +(15896 - 19915 - 21720 - 13908) +30419 - 15467 +(159 - 11853 + 28116 + 6921) +7974 + 2346 +(20926 - 1964 - 10065 * 3220) +9440 * 6282 +28478 * 20431 +((13002 - 4564 * 8293 - 29970) - 6409 + 17851) +29667 + 31635 +6777 - 18707 +1697 * 16061 +11776 + 28294 +7651 * 17616 +24099 + 27080 +8337 + 19783 +28583 + 22392 +21716 - 18243 +2484 * 31501 +(17087 * 9674 * 19844 - 1330) +(12997 - 6935 - 20069 + 22151) +((17806 + 11899 + (((((26667 - 6823 + 13026 * 11963) + 11629 / 16456) + 140 - 28068) * (4609 - 2106 / 15311 - 23908)) - (22419 + 27358 * 20393 * 10371))) - 32721 - 18217) +9191 * 24385 +18186 * 9559 +(21836 * 12898 + (9835 / 26878 * 27318 - 10133)) +(24304 * 23783 * 19146 * 20314) +32058 + 5267 +23761 / 4876 +27792 + 14962 +31984 + 1844 +((26410 - 14674 + (2153 * 23833 + 14615 - 17280)) * 16623 + 16500) +25042 - 26026 +(6805 - 29647 - 5350 - 6831) +(13015 / 24260 * (30979 + 9658 - 31769 * 26303)) +30032 * 12288 +6222 * 30854 +(26314 - 5994 - 19102 * 9966) +11069 + 5637 +4402 * 1599 +27620 + 12277 +18649 - 15879 +((26045 - 5915 * 6931 * 8887) - 5398 + 21) +29597 * 30053 +27100 * 13976 +27382 * 18856 +23250 * 17618 +32601 / 26667 +5748 * 23017 +21574 + 7143 +1501 * 26556 +5952 * 23960 +11338 - 5723 +28080 + 25531 +31374 + 28675 +1746 * 21576 +9191 * 255 +8683 + 15349 +2049 - 25693 +20688 * 32699 +7394 * 4126 +(17115 + 9611 * (((18419 * 29595 + 29002 - 18806) + 5337 / 26943) - (1324 - 1451 + 7837 * 24388))) +19424 + 17508 +(28325 + 8625 * 32424 - 23254) +21573 - 31990 +3403 + 18489 +10488 * 29446 +19526 + 3894 +26394 - 7526 +13846 - 29095 +664 * 2853 +756 * 522 +(8124 * 8994 - 8761 * 3906) +9172 - 27178 +30727 - 12071 +5998 * 15774 +8237 - 23490 +12103 - 5473 +28214 + 23694 +((((22353 * 22062 + (11954 + 13872 - 5130 - 9615)) - 4190 - 13412) - 28420 / 30832) - 1482 / 949) +24910 + 1559 +3406 - 30207 +13034 + 5185 +(25758 / 846 - 3031 - 30082) +19279 + 29885 +10715 * 23437 +(20733 - 10442 - 3270 + 20240) +18641 - 27357 +26446 * 14424 +(16385 * 31612 - (((4322 - 11801 / 18714 - 3123) - 27981 * 18207) - 19750 - 6808)) +7162 + 23195 +1553 + 17882 +3461 - 4834 +10837 - 8736 +9848 - 19913 +((29314 - 549 - 6505 - 12113) - ((9807 - 9494 + (1041 - 26508 - 10246 + 9472)) / (19391 + 25124 * 16664 - 20576))) +(3423 * 28110 * 6194 + 23004) +(5404 * 16068 - 6778 / 12352) +10536 * 7526 +30136 + 2749 +3776 + 23482 +9621 - 21353 +17486 * 22926 +(((4237 + 1454 * 14124 + 3093) * 4644 + 3298) * ((29950 * 6135 * 11461 * 31667) * 6755 * 5593)) +6649 + 9027 +(3332 * 18233 + 1069 + 22181) +31901 + 14158 +15151 * 16505 +11321 * 15970 +((24612 * 8005 * (19355 - 8001 + ((12389 * 18269 * 22658 * 29905) + 23880 * 24266))) - 7518 - 3098) +10435 + 29885 +8834 * 16895 +2239 / 4273 +(2627 + 32379 - 4147 + 8036) +(3315 * 3180 - 8016 - 5301) +26105 + 27243 +31337 - 20817 +(20723 * 27883 - ((4765 + 16204 * 7895 - 15783) * 16306 + 21458)) +19434 - 12622 +19485 - 13772 +(12027 * 11788 * 5557 * 16031) +3722 * 10830 +18965 + 23572 +22337 - 27002 +3043 * 26027 +(8076 * 5363 - 16013 - 26311) +10890 + 21359 +18096 * 13502 +30182 / 17357 +10796 * 28420 +29180 + 11702 +26983 - 29535 +1214 * 12471 +15787 - 22028 +24021 / 22246 +20037 - 9595 +(6372 + 3077 * 4119 + 3700) +23438 - 13340 +26055 / 30391 +13020 + 13091 +18464 - 19247 +9814 + 25551 +5538 * 27953 +(17715 + 15142 * 32341 * 5838) +(16261 - 21129 + ((15763 + 11435 + 31234 + 20637) - (22828 + 14824 - 23236 - 5673))) +18400 + 26847 +30045 * 17625 +10610 + 6840 +19581 - 23540 +11410 - 11004 +((((2416 + 18249 - 2378 - 21940) / ((22962 * 3864 * 28220 * 31152) + 17222 - 20511)) + 1191 - 761) + (791 * 2371 + 5178 + 13021)) +12329 - 15495 +((20117 + 25695 * (23006 * 3143 + 6032 * 30240)) + 8929 - 25812) +20801 + 5811 +1874 + 30577 +(31421 * 22235 * 10461 * 14769) +31043 - 9704 +17991 * 19971 +1249 * 7942 +19936 - 6707 +13738 * 30839 +26514 * 2390 +((17165 - 16986 / 22435 - 121) / 32593 + 4951) +9029 - 12733 +14683 + 16057 +32608 * 30701 +((8805 * 13344 - 9123 + 15908) - 13596 * 22702) +8079 * 5496 +23144 + 29727 +24846 / 19466 +23413 * 14146 +19992 / 15332 +3498 + 4643 +(((31243 - 7906 * (2483 * 22079 * (11461 * 28779 - 29343 * 10958))) - 3041 * 25053) / 25428 - 9030) +27182 * 27225 +(8133 + 10434 - 21321 * 10235) +27839 - 18046 +23381 + 17395 +21553 - 1785 +28848 - 24400 +3250 * 28997 +16006 + 2460 +9940 + 22726 +16679 + 9910 +15393 * 21269 +17388 + 18452 +29037 + 8424 +10410 * 9345 +26257 / 1902 +18465 + 1127 +31781 / 22613 +15776 / 30682 +((8225 * 8281 + ((12484 - 29463 + 674 / 25397) - 19256 * 31087)) * 8808 * 6905) +(16814 / 29681 + 17864 - 22911) +29823 * 14479 +(14090 + 893 * 22862 - 17218) +30592 * 26852 +21777 - 5950 +(7551 + 12464 - 19010 / 15304) +6601 * 17940 +(29799 - 6512 * 3390 + 31017) +24315 * 29194 +988 * 15082 +26516 - 619 +(16414 - 20756 * (15115 + 18695 - ((11794 + 13486 + 7838 * 19670) - 19208 / 11345))) +32181 - 8175 +19133 + 23457 +753 * 23041 +((20887 - 5147 * (23527 * 31610 * 24562 * 27600)) - 16509 - 25832) +10308 / 27964 +367 + 18495 +1169 - 14634 +16021 - 27469 +((22089 / 2162 * 21993 + 20837) + 8090 * 16134) +30990 - 188 +22152 - 28664 +(6809 * 22418 - (28453 * 12236 * 21633 - 24220)) +((26404 - 3213 + 4073 - 17257) * 31244 / 29148) +(22153 - 13314 - (10658 / 8982 - 28821 * 29028)) +23606 * 32618 +13762 + 22937 +31776 * 21156 +(10296 - 5159 - 27656 * 2169) +494 * 980 +24157 + 18783 +26486 + 22283 +16672 - 31509 +20577 + 14848 +(17217 * 5066 - 21677 * 25110) +(13793 + 13287 + 25534 * 1895) +22957 - 14944 +8069 - 30671 +(20499 + 12466 * 28860 + 25914) +2193 - 18680 +((2647 * 21430 * 3155 - 24858) - 23092 * 23593) +25816 * 8406 +5804 * 27865 +9352 * 28202 +32004 + 1165 +13519 - 26045 +20969 - 18155 +29700 - 15565 +23348 * 8929 +21032 + 5601 +18977 + 4389 +25918 + 3594 +(12335 + 30505 - (19721 + 2181 + 14136 * 30822)) +7168 - 27670 +2279 * 16394 +4281 - 8660 +5283 / 21770 +24633 - 11423 +8707 * 28061 +32578 + 16723 +(23291 / 6612 + 4080 + 11906) +810 - 25144 +20989 + 5174 +((2035 + 7388 - 5638 + 6349) - 5333 - 29880) +32115 * 6738 +5972 + 26943 +32719 * 10595 +11437 - 3958 +29283 - 22951 +6182 - 14675 +(32334 + 7026 * 3894 - 2585) +31481 * 21230 +14254 / 14656 +9662 - 27008 +26187 - 5136 +11637 + 23693 +21549 / 28773 +15060 / 14571 +18578 / 15993 +(16992 + 15117 * 8778 * 13557) +11138 + 24121 +(653 * 11119 - (29894 * 24808 + 6734 * 18327)) +9079 + 15999 +6827 - 23208 +29285 + 12137 +17232 / 29480 +22244 - 28727 +(11300 * 22073 - 15182 * 351) +23695 + 13273 +(26950 * 12611 - 23169 + 15295) +25645 + 9394 +30594 * 9554 +(11940 + 30242 * ((16512 - 9815 - 32317 + 29247) - 3306 - 28019)) +(((3335 * 19047 + (27064 * 4623 - ((32528 * 12319 + 27167 - 19103) - 21704 * 21742))) * (32215 - 18330 - (24060 * 20188 + 29434 - 7184))) + 21244 - 6959) +20691 - 25957 +7263 + 12565 +(32709 + 17885 - 27848 - 25290) +6434 + 24661 +24788 + 8931 +24355 + 30205 +(6638 - 26095 - 5886 + 9694) +27689 * 6426 +(21398 - 10047 / 22953 + 14128) +30507 + 3832 +29354 + 2267 +((22660 - 32177 * 11775 / 20972) - 24750 + 26907) +22312 + 7942 +27483 - 3832 +24122 * 22642 +31239 * 19811 +27196 - 25552 +(25934 * 7490 + (9521 * 14505 + 32387 - 28879)) +20759 - 2583 +32052 * 20638 +(24180 - 17875 + 27410 - 16845) +13883 + 24919 +(12117 + 28991 - 29341 - 11675) +(29384 / 15394 * 6430 - 5463) +7824 - 31703 +(15082 * 17123 * 29453 + 10883) +6199 + 23122 +11247 * 17149 +15409 * 16156 +4178 - 17422 +((2303 / 18052 + 10408 + 8136) + (205 - 4871 * 662 + 14083)) +29750 * 31373 +23223 - 22116 +10020 * 32763 +3388 + 916 +(29265 / 19163 / 11362 + 5895) +10231 * 24990 +27436 * 23339 +(30371 + 25170 - 18533 - 1443) +16167 + 24121 +(17522 - 27820 * 21726 - 13976) +(((7874 - 2975 + 5529 + 31113) / 31777 * 28973) - 19493 + 29618) +10793 * 28056 +(23301 + 8202 - 6904 + 30819) +15848 * 28321 +20009 - 10643 +12437 + 25567 +22455 * 7631 +22503 * 21568 +2276 * 8551 +674 * 29224 +5064 * 23617 +31215 + 17816 +6011 * 10170 +3054 - 19774 +8888 + 14020 +9280 * 4685 +20036 - 8269 +12597 - 19986 +(11978 / 1940 - 32734 - 21384) +28054 - 27066 +16789 * 31858 +4212 * 18784 +24308 * 12246 +21041 + 4978 +(28978 - 16911 + 13595 - 388) +4926 - 24423 +20388 + 19294 +14226 - 12436 +12890 - 362 +((20518 + 14544 * 32677 - 26800) + 23978 - 12355) +15804 - 14543 +15780 + 16796 +26890 * 18833 +12524 - 29973 +9374 + 16588 +18353 - 20294 +22181 + 16239 +5756 / 8203 +9021 / 11154 +3113 / 21474 +8971 - 18158 +17832 + 12155 +25645 / 12318 +25258 - 10597 +9549 - 23409 +24280 + 7773 +1364 * 28900 +12774 - 14010 +19552 + 4442 +12150 / 27637 +20941 / 15660 +10832 + 16940 +21913 * 12403 +32103 + 6232 +12858 + 4457 +((11407 - 18010 + 10198 + 22759) + (22061 - 22948 - (5885 * 7293 - 12271 - 18087))) +7864 * 21389 +(17437 + 16144 * 26562 * 25977) +24698 - 10584 +(28833 - 16694 * 30876 + 27247) +29822 - 28311 +26337 - 5931 +28531 - 25470 +14557 + 22182 +24594 / 31523 +((28144 * 22627 - 25189 * 10907) + (21445 - 30947 - (20266 + 4640 * 5052 - 21217))) +27168 + 16710 +(16638 + 16516 + 32125 * 17354) +((16130 * 23542 / 10384 - 12362) / (19281 * 27435 + 23282 + 25659)) +19191 * 12553 +22009 + 29857 +2379 * 6444 +6167 - 13700 +(30157 + 5982 - 17051 / 11324) +11332 * 2449 +22651 - 19299 +(14695 + 28288 + 27395 - 15041) +(14886 * 24974 + (15492 + 12079 + 29404 + 18893)) +(((16000 + 15301 + 27633 * 30998) + 32472 + 14273) + 6735 * 7631) +15943 - 21925 +8950 - 27370 +(572 * 13983 / 6324 * 7494) +2126 + 31063 +19922 - 5144 +12472 + 30599 +23121 / 32552 +5332 / 28437 +4098 * 1502 +29519 * 7377 +(18284 * 26058 - 21802 * 28113) +12409 - 30662 +(24584 * 21873 - 12238 - 19537) +21861 + 14716 +30409 / 20583 +2590 - 27484 +4639 + 19836 +29397 + 7973 +27066 * 20705 +(6006 - 4312 - 6326 + 23985) +19697 * 27958 +9230 + 28322 +21138 * 27431 +13829 / 23416 +940 / 27784 +(31327 - 12978 * 12013 - 23249) +965 + 7852 +(22205 + 30762 + 19243 - 21178) +(4139 * 4720 + 2049 / 16268) +178 * 6798 +(11296 * 6242 * 14488 * 9211) +26004 - 19784 +4325 + 24730 +(17342 + 2738 * 2529 * 17881) +(20114 - 6431 - 2589 * 24550) +(5647 - 357 + 27947 + 9666) +17660 * 6451 +((8752 * 12989 * 30728 * 23086) + 4659 / 24770) +(9077 + 6880 - (4433 * 16491 + (19060 - 14569 - (18603 + 21077 * 17198 - 27024)))) +16899 + 32459 +((2933 + 13218 - 7974 / 20630) + 19519 + 27640) +9281 + 27332 +30637 * 28063 +1314 - 25435 +18686 + 30426 +(24881 * 1841 - 26737 * 473) +5904 - 5308 +28962 - 1650 +31360 - 273 +13303 - 8848 +18420 + 16209 +19214 / 21715 +31522 - 20668 +31297 * 24212 +(2067 - 8305 * 14037 + 27015) +32499 * 3343 +28315 - 29457 +18353 * 8502 +15827 - 10231 +(19702 - 27239 * (10680 + 8048 * (((11472 * 11802 * 28953 + 26847) * 27682 - 27532) - 27944 * 26335))) +573 * 14469 +9226 - 6249 +9348 + 9758 +(23095 * 11725 + (16946 / 30566 * 5416 - 597)) +10223 * 5680 +2378 + 2122 +8096 * 13743 +27475 / 3069 +21644 - 14041 +1450 - 15041 +28107 + 26245 +10472 - 12269 +17846 - 32714 +11759 / 17623 +16830 * 21289 +7319 - 11432 +22544 * 11178 +22202 + 1739 +(30753 * 29493 + ((32611 * 16594 - 3159 * 8828) - (15030 - 29118 / 27839 + 325))) +(15638 + 29824 * 10714 / 5368) +31018 * 18991 +30314 * 14687 +6346 * 12633 +(31732 * 23038 * 10466 - 19854) +9060 + 7745 +((20446 + 25198 + 7264 - 25757) * 1742 + 26774) +21973 + 12772 +7954 * 28141 +26825 - 2230 +(27537 - 29191 * 3459 + 30487) +17038 + 27537 +11087 - 25541 +589 + 15404 +32693 * 16687 +((3312 + 23526 + 16278 / 15679) + 23331 + 11938) +15200 * 3375 +(22420 + 19811 + 16107 - 28825) +1662 * 20427 +19655 * 2499 +14979 / 7551 +5402 - 24897 +887 / 11251 +13387 + 15360 +(15534 + 21032 + (4017 - 2953 - 11902 - 6740)) +(29865 - 16794 * 14401 - 13992) +29141 + 8676 +(15104 + 19617 * 5425 - 23434) +(27634 + 9329 / 32525 * 25873) +29734 * 1851 +5896 * 24789 +30136 - 10399 +22592 * 28988 +6969 - 1615 +11182 * 19904 +22763 / 7863 +31865 + 13967 +3674 + 14968 +15266 - 8898 +27001 + 30836 +((27167 * 2154 - 25633 + 31660) + 17768 + 28114) +26956 * 21557 +6599 * 11068 +13077 * 22255 +31929 + 18910 +11821 - 22160 +251 + 20570 +4840 * 12825 +6769 + 21840 +7990 * 15262 +9684 * 4188 +17580 - 7100 +12388 + 22245 +30465 / 27493 +20582 - 28117 +13670 / 25971 +14368 - 11338 +3089 * 11309 +26335 * 23927 +19546 - 4176 +27719 + 5970 +18656 / 29795 +18493 * 22774 +30051 / 31892 +16779 + 2512 +(13224 + 18543 + 19090 / 18520) +(4166 - 31818 - 15315 * 18112) +2292 - 20864 +22809 + 15458 +10088 + 24427 +((24482 + 14156 + 20290 - 4174) + ((25677 - 1151 + 15521 - 26833) + 326 - 28817)) +3225 - 23936 +26663 + 7705 +2597 + 13843 +27494 * 377 +22052 - 3513 +11282 - 5891 +15949 * 29183 +(11210 + 16561 + 9672 + 2813) +4252 - 12995 +21332 - 15371 +27961 + 21546 +29521 * 27088 +13127 - 29118 +7499 * 6530 +(31615 * 13999 - ((19936 - 30765 + 23787 / 31516) - 30021 * 1772)) +(2226 * 27008 + 24617 - 11147) +4785 * 22309 +30367 * 5485 +11734 - 28052 +15195 - 22962 +18999 * 7505 +27987 - 17952 +9357 + 4770 +19212 * 23737 +((22152 / 17307 + 3027 - 16615) * 14784 * 7632) +14897 - 21255 +15077 * 5023 +13407 * 19394 +26486 - 8427 +(30527 + 6581 + 21539 - 8299) +16891 - 12218 +31917 * 18122 +14484 - 25512 +28686 + 20799 +((((26027 - 15138 + 12967 * 15829) / 14105 + 20414) * 4904 + 12006) * (15649 - 12737 - 5699 / 16045)) +(24451 + 25963 * 22438 - 32014) +7726 + 6000 +15933 * 3399 +(1982 - 21440 - 29934 * 1257) +32406 - 11870 +23033 + 8797 +18228 / 20821 +6195 + 31778 +((27441 * 17925 + 31965 - 20648) * (6691 - 30779 + (12731 + 8972 - 10895 + 9424))) +(21539 + 15069 / 17370 * 24328) +10260 + 20625 +1736 - 21781 +(14625 - 22744 - 6130 * 4763) +22014 * 23084 +26589 * 30893 +(19016 * 11062 - 8899 * 16574) +12663 + 8103 +30519 * 29236 +(26143 - 29247 / 24610 * 31343) +(19565 - 9995 + 31199 - 26462) +11140 - 17980 +(31410 * 27130 + (15026 * 30905 + 18968 * 17852)) +16578 * 31930 +7146 + 5657 +5298 * 12310 +4658 + 13862 +28249 * 16372 +1550 * 22910 +13323 / 26956 +5171 + 27044 +(30078 + 17988 - 15931 + 16284) +(27463 / 16352 - 22565 + 30128) +24997 * 12029 +(5464 - 22154 + 24139 / 17859) +19282 + 30428 +10839 * 6592 +25774 * 5310 +21242 * 25826 +8972 + 24510 +30137 + 3689 +3682 - 3552 +29116 + 18748 +3545 * 6895 +5541 * 31530 +1504 - 21099 +31075 - 14848 +26904 - 6272 +((1760 * 15711 * 30994 - 8418) - 5511 - 272) +26886 - 16868 +13924 / 14708 +12027 - 19180 +32512 - 22267 +27745 + 29168 +((23901 + 1379 + 19526 + 789) + 19900 * 17710) +31967 + 4932 +19164 + 27937 +21431 + 7930 +(21324 + 18471 * 19021 * 12244) +18794 * 27588 +(12277 - 26604 / (21108 * 20673 * 25681 + 27822)) +23718 * 6501 +13070 * 23785 +10886 * 18197 +27779 - 31547 +(16520 * 11507 - 6299 - 17333) +5677 - 12017 +(6055 - 1194 + 29215 - 830) +24002 / 9410 +32542 - 13307 +(11534 * 4563 - 21740 / 13262) +(20851 - 27056 + ((2416 + 21971 + (6306 * 284 - 28684 + 2450)) - 30479 - 972)) +(23822 + 17205 - (25256 - 5967 * (11336 + 27885 - 15466 * 14185))) +3933 * 30991 +10178 * 21526 +31186 - 9205 +27548 + 9677 +3436 + 1756 +23758 - 3285 +13881 + 16034 +3997 * 23684 +(13922 * 14113 - 211 - 15836) +(((15112 + 12076 + (17597 * 3852 + 8553 * 15874)) + 5150 - 15602) + 28133 - 8454) +5147 - 18340 +32138 - 12520 +23041 * 14341 +(23663 + 17823 - 7832 - 13976) +27448 * 10884 +11615 * 1512 +27168 + 31472 +26880 - 15378 +3390 + 12539 +1169 * 29173 +(19976 + 5900 - 29846 + 15346) +21249 / 10920 +5864 - 12869 +(28602 - 10378 * 7399 - 1362) +(16498 + 2608 + 28922 - 21467) +24296 * 2153 +32096 - 19115 +32525 * 15732 +28113 * 6712 +16459 + 11584 +12051 - 27252 +475 + 11253 +(12388 - 16037 * (23654 + 11234 * 26416 - 20084)) +(24502 * 13678 + 18241 + 15946) +6852 / 19642 +12474 - 23367 +27263 - 29380 +((20446 - 19690 * 21229 * 541) * (31142 + 13100 * (306 - 13184 + 15330 * 17056))) +30900 - 16180 +28468 * 20130 +(23451 - 16146 * 18383 - 15767) +22236 * 20528 +((((17795 - 25829 + 1357 / 8817) + 3272 - 27427) + 25611 + 19836) + 23338 - 4342) +5668 + 8795 +11422 * 17858 +26830 - 10515 +(28769 - 11048 + 14501 * 26626) +22226 + 22027 +((((30298 / 8553 / (10631 * 30747 - 15095 + 21446)) / 14566 - 28584) / (189 * 31735 * 529 - 17187)) + 5199 - 18454) +(18925 - 9244 * 6766 / 32495) +14696 * 21321 +(3225 - 1483 * 9458 - 6609) +26141 * 11875 +29100 + 20359 +7089 * 2640 +21064 + 20541 +23213 - 3235 +30710 - 27894 +23165 + 28860 +31100 - 2200 +15799 * 7425 +(((26588 - 15929 + 22752 - 1564) - 23742 - 473) - 6367 * 4474) +11947 - 22113 +(16173 + 26742 + (12188 - 14822 * 18694 + 24872)) +123 + 27504 +3831 / 29064 +5487 * 4529 +14807 / 22798 +29186 * 21686 +32756 * 4117 +18724 * 32531 +(29396 * 551 * 4721 * 24562) +16064 * 18761 +1347 - 9497 +(19258 * 23904 - 4824 + 31471) +13747 * 25147 +(7399 * 10630 + 19914 * 31941) +1315 + 31248 +(((6416 * 4845 * 13808 - 10817) + 17026 / 9643) + 25160 * 30828) +(8133 * 14413 - (7123 + 9707 * 22584 - 29645)) +16660 + 17951 +17437 * 5159 +4031 * 16284 +23732 + 6709 +9236 + 11381 +20063 * 8815 +((4997 + 21707 + 28459 + 12197) - 28261 - 3981) +21541 * 29139 +31484 - 32308 +24526 - 11726 +25191 * 22884 +17637 - 21185 +32667 - 28107 +((19722 - 485 / 21767 - 791) + 7063 * 9268) +18648 + 28537 +(25562 + 18264 * 21783 - 24209) +17931 * 890 +31177 - 30940 +6843 * 22801 +(10322 * 15714 * 13784 + 23120) +19901 + 30599 +19739 * 2084 +(29012 + 13285 - 13843 + 6561) +(30964 - 31021 + (31998 * 8487 * ((5400 - 22167 + 31345 + 30936) + (25043 + 24369 * 27212 * 15425)))) +3973 * 3711 +(20654 + 14738 + 1959 * 5355) +(1081 * 25151 - 30461 + 23648) +23439 * 6772 +18751 - 12595 +(31651 * 31463 * 9672 - 3153) +26116 - 22045 +5362 + 10754 +4438 + 21467 +7729 - 2499 +17115 + 23164 +(23029 + 22006 - 1970 * 21373) +9934 * 32647 +11999 - 776 +(19417 + 31845 * (24081 - 19558 * (13433 - 32361 + 5152 - 28141))) +17980 - 12291 +28876 - 8952 +28006 - 7181 +1608 - 27613 +19033 - 9187 +26820 / 30174 +2552 - 11510 +26296 + 3568 +4234 + 24582 +1734 + 17901 +24950 * 23347 +(28893 - 7487 - 2262 - 19859) +21762 * 15234 +(12345 - 8475 + 1727 - 23365) +(16272 + 17161 + 11083 + 28456) +13306 * 6073 +(7123 - 5977 + (25678 * 2249 * 7776 * 31071)) +12600 * 26190 +29877 - 23217 +(5562 - 19524 * 17600 * 14524) +2938 - 2869 +18802 * 25276 +26479 - 16574 +(20655 + 27598 + 1387 - 12468) +19358 + 30822 +2246 - 2489 +14389 - 19807 +210 + 10599 +(1075 - 6648 - (((233 + 15975 + 19169 + 16569) - 22463 - 9759) - 27953 - 29092)) +(27956 + 12102 + (((6473 + 30122 * 11370 + 23502) + 31404 + 10504) / (9537 * 26371 - 27375 + 30877))) +22724 + 12260 +28421 / 8052 +27616 * 16233 +20219 + 12621 +6557 + 21971 +4844 - 30599 +(2640 + 10862 + 27829 + 30855) +22798 + 16336 +(11403 + 13227 - 3988 * 28626) +25507 * 7165 +21136 - 27260 +22853 + 24529 +(1250 + 25215 - 10001 * 29377) +14805 + 16902 +30246 + 5722 +13070 * 19433 +27925 - 23450 +17790 * 31718 +7347 + 13675 +9536 + 24210 +3834 * 12519 +6835 * 11815 +19427 - 9880 +26595 - 13789 +21432 * 1123 +(25197 / 32103 + (6727 - 16596 * 18620 - 29548)) +9534 + 17941 +(11221 + 5377 / (27029 + 18010 * 18524 / 4349)) +23444 * 13372 +5276 + 13742 +8472 * 5200 +18903 / 11026 +11759 * 6997 +(26891 * 15441 / 20767 - 19987) +25447 - 23714 +(18161 - 13815 * 19027 * 17762) +13391 - 8766 +29912 + 13922 +2007 / 28994 +(1762 + 2811 * ((31725 * 22200 - 13095 * 661) - (18675 + 28417 * 31868 + 25233))) +(9844 * 20355 * 5703 - 9652) +(21663 * 30120 + (9274 - 30524 + 30537 - 19583)) +((31599 + 21625 * (3018 + 26991 * 7543 - 7380)) - 4287 + 13243) +24141 - 1407 +((24198 + 23997 * ((9390 + 31690 + 10568 + 31566) * 3150 + 18544)) + 20427 - 8099) +5421 + 26888 +(27712 - 18045 * (1933 - 13900 + 24537 / 15325)) +10408 - 18392 +(18142 + 17923 + 4119 * 9571) +27321 * 9855 +32149 * 283 +22855 - 15336 +(15649 * 12596 + 15751 - 2663) +17938 - 28252 +20802 + 26110 +(23106 * 3138 / 7823 + 17931) +(25143 - 10910 * 25015 + 3898) +11340 + 15285 +21938 - 18014 +27564 * 32567 +12435 * 2179 +15074 - 19789 +20961 + 20915 +2626 / 32426 +30155 * 11031 +11928 + 21951 +30314 + 20576 +3766 * 15687 +18370 * 26344 +21685 - 108 +18225 * 12461 +25905 + 12743 +5266 * 3568 +25746 + 26511 +(3095 + 28194 + ((((31470 + 16677 + 22016 * 14854) + ((30233 - 6727 * 31807 * 29801) + 13643 * 6793)) + (((5392 - 22608 * ((21356 / 30702 + (19311 - 153 * 3368 + 2863)) + (23702 * 4993 - 30348 + 20297))) * 9399 - 32250) - 5399 + 5290)) - ((28532 * 32310 + 14083 / 8106) + 24209 - 21524))) +(24931 - 4465 * 32352 - 89) +4847 - 123 +12875 + 17673 +14141 + 24360 +16739 / 1338 +27009 + 8582 +((31110 + 1316 * 17648 * 3100) * 8124 * 20450) +(15102 + 8873 - 32367 - 7362) +5966 - 12595 +14035 + 1578 +7786 - 21 +27136 - 14557 +(21338 - 24954 - 8447 - 15304) +32720 / 5432 +23753 * 21932 +24786 + 14068 +(9415 + 19435 * (12594 - 10242 - (8023 - 15428 * 18574 * 4079))) +9689 * 27226 +(26196 * 29530 + 17622 - 10813) +(31887 * 13569 - 27139 / 3341) +(7498 - 3608 - 12602 * 15172) +(21620 * 7993 + 12998 + 6105) +12913 + 5296 +10268 - 2893 +16107 - 19328 +10848 + 7796 +4477 - 1538 +12029 + 32519 +(24357 + 31017 - 28589 - 19455) +19316 * 28310 +6711 + 31968 +30892 - 12162 +19663 * 14230 +6725 / 6744 +22575 + 2549 +(31602 * 9196 - 18703 - 13024) +23199 * 797 +9479 / 24321 +24647 - 18111 +12385 + 11621 +(31571 * 16250 + (7571 + 26121 * 10314 + 1440)) +32312 * 7230 +(19346 - 26395 + (9616 - 17324 / 16859 - 8130)) +4704 + 1556 +16493 / 23454 +(17535 + 4309 - 31522 + 32518) +19421 * 32750 +23461 * 25668 +19462 * 23148 +16330 - 14495 +19646 * 15762 +2196 * 5687 +32105 - 26767 +10210 * 19325 +7346 - 3767 +(8198 - 20196 * 6924 * 23900) +((19565 * 24558 - 4804 - 1129) + 22199 - 15938) +20642 + 29579 +27422 - 22258 +((30558 * 5407 + 1625 / 24541) - 2971 + 5315) +9320 * 306 +11525 - 19783 +25255 / 17680 +30924 - 26430 +30615 + 26592 +3154 * 10636 +(3863 * 14021 + 29051 - 26605) +((29777 * 6269 + 27136 - 31194) * 11227 * 6332) +24590 * 17991 +27075 - 23551 +1146 * 20454 +25522 / 8115 +((10304 + 7172 - 13271 - 9617) + 32221 - 4461) +20122 - 3011 +31552 * 29944 +(28055 - 21264 - (30277 * 7387 + (16980 - 844 * 24371 - 31441))) +20914 - 16771 +12853 / 20321 +7917 - 15034 +16240 / 13146 +19960 + 21773 +(13901 - 17434 / (10039 - 1177 + 18332 * 3353)) +12922 + 19273 +1824 / 6898 +419 + 19868 +18647 + 30292 +31418 + 12551 +31340 - 19577 +28371 + 7191 +24706 + 17461 +15786 - 16675 +29522 + 21944 +14125 * 32411 +23977 * 29726 +20752 - 3183 +2870 + 4697 +21590 + 11810 +16393 - 8984 +8216 * 26338 +32129 * 31629 +10088 - 26153 +2068 * 21612 +(21394 * 10461 * 14035 - 12865) +18170 * 29680 +(26016 - 10803 + 24642 + 32721) +25601 + 7715 +((7824 / 23819 + 6766 * 16566) * 18645 - 28556) +3495 * 17723 +21454 - 15812 +14626 * 4761 +(((9833 * 5611 + (26781 * 4784 - 8086 * 10412)) + 23856 + 18732) + 18790 - 11720) +5361 - 23281 +14445 + 13452 +15294 + 27845 +(18828 * 7094 + ((27769 * 19366 * 10797 + 32545) * 11921 * 9329)) +15994 + 14241 +14859 - 1074 +7703 - 8572 +25381 / 23467 +17158 + 19939 +19208 + 2187 +30748 + 13879 +25329 - 21834 +23316 + 30097 +7815 * 18065 +10565 * 8035 +9688 + 10922 +(15003 - 32652 / (9667 * 3659 - 22089 - 17569)) +7108 + 10493 +6377 * 12729 +(25475 + 10605 * 17998 - 16550) +2575 + 19230 +29426 + 17746 +27591 / 27248 +5599 * 25049 +18022 - 30209 +21611 + 5454 +22260 * 22832 +8639 + 3036 +997 * 30855 +12027 + 18261 +1359 + 31648 +18765 + 16171 +10001 + 5384 +32035 * 2039 +19391 * 14324 +(24988 / 12069 / 20489 + 2802) +(17257 * 3763 - 17050 / 2064) +1050 * 15739 +(2699 * 22331 / (3066 - 3872 - 11468 + 18143)) +18189 * 24313 +28519 + 17722 +3528 - 23703 +7868 - 6652 +25660 - 27760 +15348 / 28960 +22593 - 21436 +22516 + 28241 +11708 * 968 +12948 + 31652 +28100 + 6568 +(15579 * 30477 + (25461 - 26551 - 18183 - 4743)) +2776 * 3903 +(5140 * 14669 * (831 * 15463 - 3595 * 7730)) +24935 - 6250 +2409 * 19892 +27012 - 15195 +1431 + 9995 +6707 + 23744 +15583 * 29806 +2501 + 8303 +(9838 * 16595 - 9435 - 14703) +14690 * 15957 +10879 + 21947 +(11250 * 31835 - 16482 - 8077) +(12189 - 14937 * 4381 * 26006) +21496 * 17685 +8558 + 30835 +16708 + 80 +1978 * 6898 +27232 - 16803 +(20355 * 24638 + 18813 / 9402) +7299 - 4418 +8056 / 2407 +7897 + 12744 +20409 - 157 +5242 * 16946 +3875 * 27754 +17107 - 30779 +(24918 * 6981 - 7878 * 26842) +26288 - 1213 +14468 + 30438 +(391 + 27942 * 11116 * 15029) +24458 - 27011 +22050 / 22395 +6615 - 29879 +(29407 * 13081 * 22230 / 1230) +((16042 - 6317 + (15084 * 22000 / (22962 / 21844 + (27819 * 26493 + 9859 + 19695)))) * 6537 * 25582) +(22609 * 17229 * (6145 * 16080 - ((12013 + 13319 * ((30727 - 5402 + 7448 - 7916) * 28541 - 1128)) * 23418 - 2451))) +(1500 + 4656 + 11658 + 14383) +17180 * 17831 +27874 + 10658 +12925 - 12670 +22522 + 28534 +31500 * 26811 +3929 - 15666 +31076 - 206 +7143 - 9212 +12167 + 6077 +(31960 - 11164 + 30436 - 7347) +23594 - 26609 +29159 * 3057 +(32424 * 2243 - 7951 + 156) +6047 + 31702 +22458 * 28436 +9605 + 1572 +21029 - 24151 +22629 - 22880 +(((26237 / 8431 - ((20932 - 27064 - (16411 * 8860 + 8159 - 19714)) / 13745 * 32586)) * 19975 + 12660) + 30035 * 13717) +28236 - 314 +23853 + 21962 +21080 + 7629 +12711 / 7851 +((14047 + 6464 + 25773 / 10565) + (6620 * 11540 * 24234 / 11371)) +10374 + 24332 +17244 * 15753 +(26094 + 8964 - 6531 + 10949) +22130 - 30363 +8740 - 9687 +2073 - 5728 +1514 + 4089 +21204 + 28852 +26299 + 14769 +19954 - 27946 +7465 - 13155 +21411 + 5165 +17207 - 2292 +22083 * 22802 +29886 * 10785 +27359 + 2630 +31786 + 28326 +(14356 - 18079 * 32250 - 17669) +(((((26736 * 2597 / (6808 - 11681 - 27502 - 18003)) - 13278 + 26383) - 10060 - 6378) + ((14409 + 21799 / 10745 + 31176) - 28216 * 7122)) + 15624 - 13436) +9118 / 16358 +27174 - 26878 +30887 + 30212 +26584 - 18734 +11590 + 17147 +24673 + 17937 +28137 * 5477 +6417 - 13292 +30137 - 4953 +19096 / 28906 +(8183 + 23336 - 27182 + 4921) +23601 * 5930 +19322 * 28037 +31602 - 28504 +(26593 - 7090 + 23669 - 21636) +21521 - 17152 +4811 + 13125 +(10365 - 5600 + 23223 + 8297) +5174 - 21030 +(10965 + 23007 - 66 * 30568) +22256 + 28931 +4399 / 7016 +28731 + 4172 +(6016 - 31643 - 4763 - 15825) +((5826 * 9615 / 3108 - 5931) * 27292 + 21500) +13139 - 10707 +22779 - 6464 +((6958 / 10043 - 10884 * 855) + 7265 - 24582) +12283 * 16080 +(3524 + 16269 * 5911 - 22509) +22877 - 6070 +12269 * 3107 +22542 - 19655 +24838 - 25674 +((1933 * 4003 + 23178 + 4387) * 7395 - 28917) +((16737 * 30191 - 3273 * 10851) + 26746 + 9799) +29677 + 7558 +31198 - 28303 +27304 * 16670 +20152 - 21768 +12336 + 1663 +(24283 * 9751 - 30841 * 6256) +23473 + 837 +20152 * 7219 +(27428 - 7727 - ((27765 - 4459 * (16612 * 22696 + 19978 + 18040)) - 28237 + 21402)) +(25987 + 11802 - 18203 * 20185) +19529 * 32452 +9809 * 15975 +2996 - 23152 +(28446 / 24209 * ((((16919 * 21174 + ((1531 - 20454 - 3282 / 23386) * 6949 - 20295)) * 21377 - 3165) * 9148 * 28729) + 21076 - 19052)) +2220 * 30610 +11079 + 7061 +2140 + 11927 +((28917 + 22165 * 8150 * 24242) - 22824 - 30713) +((1463 * 21554 - 4566 - 25802) - 28901 - 20772) +9296 - 11533 +10473 - 4117 +4262 + 2119 +3138 + 27454 +3138 * 23637 +(9704 + 31374 - 25380 / 27476) +(28177 - 9753 / 31070 - 21353) +13249 * 15179 +(31555 - 221 + 18700 * 16488) +27188 / 30005 +8356 / 26711 +100 + 7265 +8533 * 27420 +10524 * 2763 +4619 * 19120 +110 * 2594 +2809 + 2293 +28151 * 9608 +(14094 + 14210 + 10430 + 7736) +17170 + 12587 +4671 + 8663 +28764 * 5965 +1815 / 2988 +20103 + 21373 +23136 * 956 +26612 - 11446 +11405 - 22327 +32346 - 27370 +27688 * 29622 +32523 - 13029 +24557 - 25991 +(16217 * 29317 + 27796 * 31727) +30501 * 11510 +(21214 * 8318 + 3574 + 19566) +28118 + 24693 +26694 - 17874 +10488 - 990 +13339 * 5496 +(22690 + 31962 * 6389 + 29970) +19407 - 9112 +26715 * 4746 +21487 * 13351 +((23982 * 8419 / 8743 + 24463) * (3419 - 3955 * 22016 - 6069)) +4734 - 10228 +31008 * 1486 +8226 - 4478 +7252 + 31274 +((12453 * 13112 + 29645 * 3117) - 31294 * 24732) +((17394 - 2379 + 28585 - 26173) / 11001 + 13749) +25719 / 24473 +29393 - 11783 +16479 + 1590 +15374 - 15970 +8023 + 24385 +(19093 * 8335 / 13793 - 2607) +11216 / 21152 +((11334 * 15828 + 31018 + 15416) - (((29798 / 31448 - 17402 * 19939) + 15438 / 24607) - 363 * 16464)) +4779 + 651 +7965 - 6822 +24026 * 23606 +20686 + 2861 +(((31335 * 2967 - 13123 / 8921) * 31559 - 10399) / 26702 + 25460) +18805 + 27788 +4575 + 8195 +((412 - 20039 * 2988 * 23043) * 22090 - 31844) +30692 / 15284 +(18921 + 406 - (19384 - 22502 - (((24706 + 22405 - 19625 * 19421) * 1772 * 19948) / ((2030 - 22646 + (15391 * 5922 * (12574 - 5067 + 17455 / 2002))) + 20414 * 10558)))) +31369 * 19318 +12793 * 16901 +(29020 * 28302 + 32040 + 28535) +1002 - 30391 +(23719 - 8378 + (378 * 23081 - ((25467 * 6371 * 1335 / 26207) + 30283 / 1681))) +(4824 * 598 + 28333 * 4248) +28593 + 31922 +(14646 + 25444 * 30044 + 262) +19813 * 31743 +20013 - 1913 +((((12492 + 28067 + 28329 + 23163) + 18474 * 5129) + 11847 * 12990) + 25190 - 5940) +(27912 - 31087 - 205 - 25175) +((31595 * 22628 * 9067 + 12171) - 18015 + 9517) +12927 * 16485 +23418 * 8951 +((22863 * 30392 + 28940 - 6491) + 27472 + 3348) +32641 - 15402 +26119 + 18493 +29329 * 25054 +5924 + 1118 +((29005 + 30162 / 18301 - 27262) * ((7376 - 2408 - 5145 * 6071) * 21696 * 5136)) +8705 * 23321 +13745 - 21793 +6207 + 17372 +12021 + 18055 +4067 - 27668 +17207 - 1407 +12105 + 31284 +(31542 + 5416 + 19336 - 20232) +9453 * 25734 +1694 - 19690 +20753 - 11365 +(9100 - 23915 * 7454 + 12958) +15013 - 12973 +(3318 + 21461 + 24778 + 27133) +32083 * 12159 +((7675 - 32413 * 11933 + 16959) * ((28119 - 5579 - (107 + 22734 * 759 * 13944)) * 15638 - 19034)) +14298 - 13540 +(13081 * 12659 - 19683 * 12794) +(23573 * 6883 * (28628 * 29685 - 5362 + 14683)) +24471 * 13437 +9644 + 26170 +9787 - 7307 +(26245 + 15718 * (14359 + 13513 * 14244 + 1186)) +20434 - 25372 +19614 * 5917 +29193 - 19654 +22892 * 17428 +1893 + 27527 +21355 * 27186 +3536 - 6785 +26425 + 7262 +(29661 + 14574 + 5575 - 24359) +14998 + 16037 +25175 - 1570 +16225 * 3177 +28773 - 24909 +(24087 * 25693 / 3034 - 14000) +30796 + 28346 +5322 * 508 +(5210 * 5187 + 8698 - 15795) +24720 - 26718 +18376 - 15069 +30271 + 20710 +31448 * 13748 +(4859 / 25917 + (23905 - 22681 * 28369 + 935)) +22063 * 15847 +(799 + 20299 * 4608 * 32568) +(20457 * 12955 * 25944 - 392) +((15706 - 9129 + 18302 + 3707) * (3510 - 29206 * 29931 - 12202)) +(224 / 32712 - 19808 + 21005) +((10526 - 31788 / 5556 + 3574) + (14465 + 18789 * 17116 - 20126)) +9632 + 30886 +32620 * 30305 +((30135 * 22381 - (23005 * 24742 + (24957 + 545 * 21662 + 20552))) - 20193 - 15845) +10681 + 1854 +9247 - 28850 +(56 + 28326 * 18371 - 31165) +19107 - 7347 +24739 + 22299 +(6188 + 31361 / 17306 * 1758) +(21314 - 20702 * 15383 - 3413) +29991 - 7837 +(((((20317 + 30118 - (7192 * 19373 * (29560 - 28778 + 13552 * 23909))) / 8923 + 31177) - 28601 * 13897) + 16213 - 11825) + (15283 / 15375 * 8536 * 30236)) +(26832 - 18160 + 19972 - 28636) +18729 + 22066 +28851 * 17225 +1179 - 19606 +18813 + 7730 +14642 * 1884 +6876 / 10322 +8635 + 887 +((3528 + 15860 * (32220 + 13944 / 31581 * 21710)) + 14215 * 22118) +(((30309 * 17785 * 31839 + 24296) - 17213 - 955) - (1896 - 32255 + 12145 * 12475)) +30320 * 7430 +17334 - 609 +14843 * 7165 +17010 + 9905 +18632 + 19275 +9725 * 14339 +24310 - 20828 +18593 - 31397 +((6344 * 1659 * 25285 + 7900) - 24721 + 6331) +11171 * 17349 +16956 - 27808 +17199 - 12544 +12130 - 21021 +24643 + 5328 +(22263 - 621 + 25745 - 3386) +27770 - 23181 +((28869 * 3096 - 10279 / 10272) - 10312 - 18742) +1784 - 9973 +(4195 + 7487 / 3642 + 18621) +21034 * 11967 +(8014 * 10515 + 11625 + 16519) +(31618 + 12040 * ((26959 * 27971 / (12521 + 32694 + 27561 * 6225)) + 17498 - 17754)) +((16909 * 17134 + 1231 - 19008) - 2694 * 31934) +(7497 - 27082 + 14482 - 10651) +(1695 * 15522 + 28883 / 6318) +(7874 / 27208 / 29546 - 8453) +20679 + 1458 +(28473 - 29324 * 7327 * 18956) +4119 + 26546 +26448 - 13159 +((30749 - 13703 - 10735 + 8764) * 27375 + 30877) +32434 * 31184 +16391 - 3225 +7775 * 29656 +15650 - 30711 +24182 - 10429 +27060 * 3674 +26087 - 11856 +10355 - 2338 +12046 / 25153 +29263 / 6069 +6606 + 19791 +23462 - 6915 +(23067 * 9311 + 3259 * 23848) +(1415 + 2521 * 15875 + 26295) +778 * 18520 +5221 + 22310 +21900 - 17341 +27231 + 28546 +(17805 * 382 * 25975 - 67) +7423 + 14648 +((1159 - 7551 + (22043 - 16256 - 6799 + 420)) + 28869 / 12673) +26955 + 22353 +(5767 + 11634 - 18666 - 11817) +24664 * 5206 +(27001 + 8059 - 6483 + 12947) +10456 - 2080 +17962 * 11306 +22116 + 24380 +683 * 18975 +6795 * 31384 +6550 - 17449 +25650 + 15654 +8603 * 532 +476 * 11681 +7142 + 7129 +8756 + 30717 +(657 - 19376 * 14770 - 25907) +2601 * 31460 +21770 * 10820 +((21991 - 8926 / 12890 * 13051) - ((20544 - 20388 - 21582 * 32068) - 26651 * 15603)) +4081 * 29470 +1764 - 24180 +12484 + 27054 +19379 - 17514 +26915 * 11003 +15281 + 18414 +23141 * 8434 +30106 + 25301 +19012 + 25740 +13334 + 3305 +(((18117 * 1411 * 4140 * 10492) * 26414 - 7271) * 8704 + 25695) +4965 * 10812 +(17826 * 26164 * (10558 + 15556 - (18229 * 9899 * 28242 / 12791))) +10274 * 23773 +16011 - 9152 +5132 / 19616 +24427 * 9458 +(24383 * 1559 - 26228 * 28391) +((18728 - 1454 - 25943 + 3764) * 13878 + 16363) +25144 * 2379 +(28246 * 15744 + 19902 * 3972) +(((16458 - 30786 * 7120 - 16259) / (5365 - 12041 - ((16684 / 10020 / 27799 + 10165) + 11798 * 17449))) * 10003 * 5012) +((451 + 1105 - (8966 / 9429 + ((28209 - 26779 * 23259 * 19486) + (8826 * 28359 + (4155 - 4655 - 12794 * 3500))))) * 28983 + 22530) +(30745 * 12579 - (16244 * 17247 - 7409 + 26405)) +(3659 + 9430 * 26867 + 5686) +9799 + 23832 +((24314 + 5970 * 10718 * 16492) * 17436 * 21609) +(19166 + 13294 - (9586 / 15914 * 12095 * 29273)) +23248 * 28334 +25352 * 23 +(30919 * 11906 - 28960 - 29577) +10767 + 14682 +(15624 + 3839 - 13714 + 32062) +17777 * 1947 +19395 / 28623 +((23308 * 13674 + 690 * 23248) + (7670 + 6312 * (31316 + 5411 + 22534 * 1838))) +10577 * 13379 +28992 * 17926 +(8500 + 11129 + 26312 - 331) +16456 * 11967 +7684 - 27709 +(30146 - 8310 * 8938 + 691) +(((21775 - 26733 + 20389 + 9172) + 19656 / 1091) + (17437 * 8329 - 8170 + 7352)) +28354 + 20142 +15902 * 25841 +(3142 + 26471 * ((16561 * 2520 - 29137 / 17985) * (27281 - 22216 * 7884 + 31868))) +1597 * 31130 +25472 + 11190 +26002 - 22994 +25094 + 20957 +(5082 + 1004 * 21559 * 26500) +8669 * 23279 +24421 * 22760 +27148 + 18813 +10340 * 28197 +27240 * 22353 +1456 * 5362 +31420 * 23199 +27437 + 26979 +8778 + 27003 +10640 + 30979 +(29367 + 11882 + 11439 - 1330) +17752 + 12140 +17434 + 386 +19102 / 9653 +2493 + 13160 +22748 - 32487 +12293 / 234 +4711 - 26726 +1602 + 19409 +15107 + 5710 +5829 - 21134 +10620 * 25644 +22578 - 11378 +(22485 * 2515 - (10968 - 13293 * 22277 + 24883)) +12949 - 27767 +10806 * 23406 +1659 * 21120 +5331 * 10040 +24448 * 13764 +28282 * 25916 +2241 - 32226 +(((6968 + 15940 / (((13765 / 9672 + ((16947 + 30450 - 28028 / 27354) * (10498 / 6885 - (24026 * 5565 * 4123 + 21812)))) * (3260 - 26691 / 15465 * 11124)) - 4013 * 11114)) + 25081 + 19927) + 4386 - 30862) +(16868 - 20278 + 13366 + 15430) +25841 - 19678 +9444 - 7415 +29831 - 2660 +19299 + 4431 +16872 + 15432 +(31360 - 31902 / 3082 + 17928) +19593 * 14598 +30479 - 9563 +((12570 + 23497 + 14688 * 30249) - 18610 + 31495) +642 - 25321 +(96 + 17966 * 590 * 16090) +17445 / 27901 +25286 + 940 +((30316 + 10466 * 16796 + 9652) - 13687 - 10526) +(8983 - 27199 - (21236 + 20286 + (27474 - 2499 * ((7371 * 17443 + 12119 + 11741) + (27871 - 9300 - 24083 * 3369))))) +14944 + 5184 +10528 + 32628 +23017 - 13801 +16694 * 31638 +12577 + 6352 +2252 * 165 +17861 - 6137 +19685 - 7900 +(11997 * 31240 * 26235 + 9317) +13624 + 25295 +26381 + 28451 +30110 / 4519 +31687 - 2237 +((31557 * 14837 + 13089 * 24917) * (21322 + 30001 - 7907 / 29221)) +(25985 - 2256 / 2486 + 10464) +16475 - 2869 +24312 + 435 +15462 - 20061 +12219 / 17569 +13486 + 19792 +24201 + 10261 +23769 + 7854 +(7452 - 23264 + 26418 + 19476) +19219 - 11296 +1258 - 15901 +((10629 - 1420 / 31810 + 10658) * 2675 + 17546) +(8133 * 14669 / ((25539 * 28050 + 9874 + 11074) - 7451 * 10808)) +32048 * 5458 +26611 * 724 +19638 - 10507 +13857 + 18963 +98 * 21352 +(16490 - 17769 * 9630 * 18725) +21805 + 13706 +(420 * 12671 + 16298 / 30502) +1525 * 9206 +(6476 - 29740 - 23110 * 22267) +31376 - 28154 +18407 + 25853 +31099 + 11548 +5747 - 31882 +20416 + 15822 +17886 + 19281 +10699 * 18544 +23772 - 21256 +7414 + 20076 +((28420 * 14349 * 14744 - 26193) - 31380 * 17591) +(19575 - 7849 + (8439 + 24017 * ((18956 + 23151 / 28501 + 23748) - 2359 - 6710))) +(7415 + 27147 - (854 / 14340 * 2122 + 17248)) +(1409 - 19499 - 13724 + 6201) +14721 - 31120 +1381 - 13747 +26949 + 22353 +26219 - 7584 +15724 * 3630 +6544 + 32198 +28644 - 9756 +(23484 * 14832 - 13711 * 3920) +27651 + 301 +18212 * 24736 +(17309 - 20471 * 32545 * 13179) +(949 / 17484 + 19980 * 7899) +((31957 + 14130 * 32135 * 23221) - 25070 - 5016) +17213 + 2574 +16945 - 29 +4089 * 2610 +32388 * 28128 +11996 * 29807 +(4163 * 16221 + 16544 - 8597) +29602 * 6924 +6668 - 29684 +(19663 + 29125 - (5721 * 24926 + 26365 + 9020)) +24839 / 11469 +31777 + 10653 +(4119 + 10063 + 21868 - 21896) +1475 + 24024 +26299 + 16790 +19250 - 25104 +((20674 / 8838 * ((18188 - 16765 - ((13202 - 26299 + 128 * 31091) * 1025 + 20954)) + 15058 + 8362)) / 26676 * 6458) +(14348 + 787 - 28300 - 14278) +9243 / 24331 +(9157 * 20781 * (10319 + 6075 + 7545 * 23419)) +4310 - 18223 +28716 * 28860 +27461 - 26583 +26678 - 5128 +24480 + 7483 +((15153 / 30186 - (230 + 4267 + 12788 / 7626)) - 5916 / 12608) +28794 * 2226 +(31895 * 3860 * 19813 + 24939) +2194 * 22752 +28699 + 7814 +1073 - 20442 +20712 + 27288 +(10434 * 11466 - 4299 + 2534) +654 + 26467 +952 + 7333 +(10661 / 9115 / 3240 - 12138) +((18342 - 30838 / 24434 - 14342) - 12962 * 16015) +11493 * 29310 +32107 - 26410 +11494 * 26659 +14388 + 19128 +17800 - 2347 +30548 + 31103 +((20167 / 3712 / (2726 * 26399 - (19154 + 3679 * 24263 / 14023))) - 27390 * 9452) +901 * 30668 +16475 - 13306 +10166 / 8163 +(6472 + 29264 * ((11529 - 8040 - 21639 / 15777) - ((12811 - 8051 - ((28478 + 28644 - 629 - 31012) - 31766 - 27936)) + (9396 * 20150 + ((26547 + 5296 - 8185 + 2114) + 14732 * 11835))))) +30907 - 29818 +11509 * 28706 +17275 * 17072 +19150 - 31489 +30898 - 29081 +11052 + 6476 +(7359 / 14113 + (19338 + 1308 - 13518 * 8658)) +1691 - 7282 +31167 - 25520 +10885 * 27481 +3557 + 20315 +28159 * 2412 +19063 + 19240 +19343 + 983 +(1254 * 22621 + 312 + 1530) +22430 + 3982 +11479 - 7556 +(32308 * 29967 * 29112 * 25121) +5644 * 12216 +10171 * 22656 +6710 / 14833 +15012 + 27257 +29481 + 11835 +18961 + 16993 +15869 * 19015 +21761 + 14232 +(32155 - 27811 - 6628 - 17171) +29419 * 15065 +22646 - 27997 +((15569 - 30981 + 19502 * 16452) - 13981 * 30475) +(3820 * 9818 + 30528 / 6862) +507 * 14714 +301 - 3125 +(9192 - 28077 / 5753 + 14883) +9107 + 29286 +(29533 * 2520 * (15110 - 23291 - 5094 + 32339)) +11282 - 27401 +((20763 / 4603 + (470 + 7936 - 12832 / 20090)) / ((1746 + 10521 + 17643 - 28046) + 2415 * 6223)) +(11392 * 24347 * 7917 * 21862) +23930 - 32466 +17528 * 30140 +20673 - 18883 +11840 - 10917 +19466 * 22793 +(12434 * 18026 - (14552 * 1526 - 25264 * 29338)) +8463 + 27441 +28789 + 29223 +6679 * 20734 +8046 - 21133 +8034 - 3961 +8241 + 10380 +(27003 - 15546 * 14869 * 12665) +4681 + 19077 +28009 * 13461 +5127 - 5775 +3945 * 23354 +(30738 * 6835 * (31292 * 26573 + 30683 - 279)) +((6051 - 8985 + 3717 * 26986) * (((6362 - 17739 * 2187 / 29587) + 6187 * 23838) + 20995 + 27334)) +3005 + 13184 +29178 + 32624 +16063 - 1060 +4718 - 15654 +2186 / 12121 +24740 / 6668 +29354 * 6187 +19859 * 821 +12808 + 25984 +24952 * 4557 +(19272 * 5879 * 15374 + 6374) +29481 - 145 +24589 - 2303 +((10568 * 4565 * 30356 * 27307) + 12305 / 3857) +20226 * 24270 +(27919 - 7475 / 10427 / 8296) +20728 + 3852 +19922 - 23200 +30748 / 20664 +(19030 * 9051 - 28176 - 16418) +27638 + 17249 +1111 - 9451 +2598 * 17830 +4152 + 20579 +6369 + 29380 +21312 + 1368 +14086 + 22694 +(21920 - 21386 * (7250 + 31483 * 3430 * 26512)) +17767 * 21559 +16907 - 24152 +14044 / 18761 +6335 - 27377 +(2175 - 3378 - 1714 * 26433) +1576 * 31208 +12362 - 27119 +18401 + 16921 +14645 + 22923 +22103 + 19645 +13784 * 7430 +7007 * 22359 +29789 * 27912 +12407 + 13578 +9286 + 22834 +13134 / 12786 +(7248 - 5246 - 792 * 20898) +7760 - 30676 +21011 - 31664 +22943 + 10168 +1486 * 7951 +11643 / 11091 +21513 + 25562 +20273 * 16441 +4836 + 10998 +3582 * 7824 +10448 + 22982 +26827 - 19220 +18398 - 25041 +7316 * 29874 +27936 - 22616 +(1958 * 13819 + (9302 * 28509 - 13312 + 16228)) +27412 * 11614 +5597 + 959 +13150 - 23870 +1277 + 8291 +2303 + 25069 +(18680 - 24368 - (29730 + 6786 * (8570 * 17237 + 29333 + 18212))) +5217 - 139 +13690 + 18317 +21799 - 11484 +(17014 / 3272 + (28235 + 11272 + 2708 * 20611)) +6438 - 4321 +303 / 17318 +32341 + 24362 +18387 + 24588 +1466 + 28814 +32126 + 924 +26371 - 16311 +19543 - 32675 +28826 + 24069 +(27480 * 4469 + (13062 / 21911 - ((9546 + 9954 - 30156 * 30128) * 27283 + 12576))) +24631 + 949 +15365 - 31888 +31157 / 12192 +(17606 - 6602 + 4630 * 28043) +(29114 * 11982 * 4503 - 23309) +29264 + 31840 +18138 + 19246 +((19531 * 21247 + 22510 - 8983) - (((8433 + 2010 - 4294 / 3139) - 24712 - 13972) - 2606 * 28610)) +29441 * 24908 +13588 * 30551 +12753 * 24190 +8542 - 6603 +20566 - 13613 +17490 + 22391 +14284 + 11593 +25225 * 23271 +10840 - 21491 +25235 + 16363 +28858 / 6855 +8526 - 29102 +(886 + 14043 - 5786 * 13416) +7570 / 23444 +((((27694 + 23542 - 22623 - 3309) - ((3666 + 28118 + (4265 * 1215 + 5367 + 18757)) * (29082 / 29997 / 23366 * 3018))) + 10149 + 20145) - 9124 / 10963) +6800 - 6580 +26706 * 7063 +12975 - 12359 +10181 - 12571 +28124 - 19924 +((10114 - 10594 * 16828 + 20745) - 7307 / 3253) +31097 * 32234 +29299 / 17317 +3896 - 24953 +31906 + 22053 +(28899 + 2591 / 32231 * 17344) +(((19737 * 23614 * 1271 * 21775) * 6302 + 6938) * 18905 / 23407) +((1722 - 11216 * 8434 + 913) + 9292 / 14170) +20868 + 12104 +19806 * 17198 +27819 - 3796 +5458 / 3292 +24552 + 8935 +9678 * 26796 +(8853 - 3610 - 23469 - 22006) +5834 * 24413 +17249 / 20877 +28835 - 523 +(14113 - 11227 - 12001 + 20303) +((20364 - 8080 / 10742 * 31414) - 21222 + 4215) +(15489 - 5506 + 11997 + 15861) +20756 - 19345 +20269 * 10760 +(3423 * 26394 - 7175 - 28596) +2020 + 1606 +1296 + 1812 +19718 * 13615 +21264 * 11034 +27228 * 15378 +9983 + 6091 +29759 + 15988 +14288 * 8170 +14039 * 12120 +2139 + 31887 +(8879 + 10340 - ((11488 - 11475 + (23661 * 30263 + (16541 - 14147 - 24599 * 9103))) * 31530 - 1808)) +((14692 - 6581 + 31987 * 26353) - 13808 + 22358) +6692 - 24302 +9396 * 30493 +32595 - 31609 +47 + 29119 +27801 * 24146 +16929 * 13949 +7326 + 9971 +(4672 - 26250 - 28201 - 427) +7649 * 14423 +27360 / 12996 +19389 - 16997 +18967 * 5906 +21166 * 1354 +(18722 * 27995 - (8981 * 21270 - 16939 - 2075)) +32140 / 22859 +(17248 * 7851 * (605 + 17912 / 18754 / 17467)) +(20124 + 16349 + (998 + 21602 * (10972 - 31704 / 233 - 26912))) +10257 / 14727 +(10329 - 17388 - ((8198 - 21357 * 30612 - 22610) - 29711 * 2021)) +((28389 - 24909 - 24577 * 21535) * 25658 - 6109) +29957 + 23549 +19395 - 21693 +(1675 * 26240 + 17775 * 1968) +21821 - 17297 +5780 - 4865 +12893 - 80 +1869 - 12700 +13548 - 10173 +12770 + 23503 +(11760 + 10543 - 6858 - 14761) +2089 - 17842 +((((28326 - 31955 * 21695 * 30875) + (27762 + 10836 - 18120 - 23509)) * 25190 * 10294) + 32304 - 2193) +26767 * 32149 +9402 * 14637 +(12302 / 9161 / 15986 + 5565) +(30630 * 14520 * 2064 - 27945) +12821 + 12081 +22699 + 8588 +26444 * 20372 +31177 + 12871 +20690 - 23533 +2986 + 31508 +(20961 - 15701 + 21899 - 22175) +19262 * 15253 +18880 + 6552 +23292 * 1204 +(30563 / 10787 + 22322 * 10255) +7743 + 23951 +(3912 - 20497 * (4649 + 9725 + 32649 * 18284)) +10007 - 1950 +29560 + 9061 +25229 * 29227 +15199 * 15778 +13654 * 3837 +2661 * 4839 +17439 / 23557 +13645 * 32743 +18646 / 20653 +24336 - 31663 +26350 * 6734 +(24474 + 8962 * 23054 + 13274) +31217 * 10752 +6864 + 14869 +1085 + 22310 +18853 + 7162 +8042 + 28759 +(25409 - 20081 - (25538 - 27339 * 11755 - 14087)) +(20281 - 4800 * 18405 * 12614) +((18683 * 12110 - 15105 * 29185) - 17220 + 21594) +17967 * 3044 +((6133 - 2275 + 15796 * 28985) * 2236 + 19154) +31153 * 8918 +23653 * 8533 +26434 * 10882 +27963 + 8761 +((23715 - 27749 * 29352 + 26145) + ((32070 - 31852 + 15198 + 4217) + 18168 / 9888)) +22110 + 12056 +29585 * 23144 +(28690 - 2949 + 7141 + 1176) +27137 - 20286 +10745 * 4381 +29107 * 12184 +7676 * 3572 +32372 * 13194 +6731 * 8271 +20105 / 1868 +16868 + 1213 +12808 - 16733 +29671 - 9366 +29675 * 23759 +21235 - 31090 +29156 - 12306 +22187 + 26334 +((26191 + 14759 + (5964 - 14987 * ((28682 - 9893 - (30882 * 15284 + 32475 - 509)) + 8836 - 20939))) + 26311 - 19775) +(28590 * 22981 - 26455 / 13744) +(6861 * 29581 / 22532 / 6574) +22932 / 759 +28889 / 30275 +1821 - 26573 +(32651 * 6164 + 30218 + 24614) +30752 - 6590 +28916 - 30340 +(9671 / 2473 / 25362 + 29606) +23764 - 21677 +20556 - 8301 +19378 - 23373 +23289 - 22584 +21366 - 25097 +((11230 + 19833 - 17625 - 21889) - 22439 + 1704) +20657 * 29783 +((((28797 + 6770 * (6862 + 12026 * 6887 / 29429)) * 18871 + 17901) + 31448 - 23776) * (32593 + 26704 / ((7659 * 8238 - 9079 - 25033) + (14776 * 7188 - 22459 * 208)))) +16781 + 32633 +31861 + 12634 +25176 - 8906 +(8154 - 2409 * (16302 + 32229 * 6440 + 24118)) +6145 / 230 +11809 * 22791 +1761 * 4491 +21660 + 1003 +(26418 * 1604 * (981 * 17775 / 30124 / 31855)) +13275 + 16789 +(17958 * 26820 * 4799 / 25298) +((15632 - 13457 * 4298 + 10797) - 21637 + 3339) +1574 + 19350 +20650 * 15698 +10933 + 16966 +7837 * 7024 +14371 + 11715 +(((22617 * 27223 * 3843 - 9384) + (5071 * 3478 * (5990 - 7455 * 18305 - 11122))) * 19315 / 7874) +11047 * 12270 +164 * 31209 +10466 - 301 +(25284 * 27644 * 18899 + 25854) +1369 * 9793 +4825 - 12117 +690 - 27448 +4451 * 5088 +2031 + 32106 +17668 - 24623 +12612 * 13785 +11851 * 31716 +24887 - 3386 +((25460 - 275 + 24120 - 3186) - 26689 + 5165) +24506 - 5294 +30876 - 30178 +(728 * 27402 * 15146 + 10486) +(15298 - 23416 * 11083 - 12210) +17175 * 26511 +14524 - 15687 +(22046 * 31154 * (27460 - 3535 * 28425 + 976)) +(13044 * 4786 / 30111 - 13778) +4246 + 32302 +1325 + 4858 +4890 + 31967 +14079 + 22021 +31654 + 32250 +15471 * 5617 +(13430 - 17775 / 17663 * 31346) +((27831 + 18959 + 17985 + 26342) + 2151 * 13448) +(7916 * 12368 * 5701 / 26768) +12401 - 31231 +18917 * 11883 +((9231 * 1149 + 592 - 707) + 30492 + 21119) +19881 + 9663 +24844 - 9295 +(32711 * 31695 * (((27724 * 7027 + 25295 - 6887) * 15071 - 7043) * 5109 * 27485)) +(9461 + 12089 + 11218 + 16107) +15149 * 1570 +5094 + 13597 +(9108 + 11141 - (709 + 10051 * 19145 + 28298)) +26554 * 17657 +(17632 - 7406 * 12524 - 9270) +24399 * 26720 +32223 - 2812 +13837 - 2346 +7154 - 12392 +2634 + 9348 +18203 * 6941 +7663 - 29180 +10716 + 21002 +(28205 * 31609 * 26537 + 28491) +2278 + 23919 +4689 * 24935 +25086 + 25352 +((((10485 + 6180 / (20625 + 3545 * ((24710 / 7831 + 13900 / 16576) + 11915 - 17187))) - 8484 * 26485) + 32344 * 28075) * 30471 + 10679) +(29348 + 12531 - 30476 * 4426) +32656 * 7487 +28720 * 8402 +7365 + 20082 +(10088 - 11569 + 15221 / 8515) +16542 * 13629 +25099 + 20136 +27530 / 12816 +12858 / 28787 +(6272 * 4510 - 27741 * 14207) +(29669 + 26180 * 1368 / 11812) +27596 - 25692 +24564 + 8612 +12424 + 7564 +(31009 - 19682 + 13611 * 17109) +22769 + 3504 +6444 * 21985 +((28172 * 15562 + 29252 + 1251) * 28134 + 19630) +(1447 - 15070 * 16790 - 2052) +((585 + 3019 + 27050 * 554) - 23141 - 12586) +20316 / 14365 +(2964 * 5775 - 6010 * 23168) +(21263 - 4014 + 26322 + 32373) +772 * 17277 +4409 + 15862 +18709 * 2958 +7122 * 30344 +20571 / 21297 +9456 + 3828 +(29966 - 27958 * 7875 * 23362) +19584 * 10156 +(7044 * 19774 - 28082 - 17822) +1871 * 27756 +24768 - 29565 +5217 * 12578 +(4825 - 27975 - 8368 * 25418) +26145 - 32481 +5259 - 31764 +5694 * 16076 +30831 + 27138 +14145 + 5557 +24074 * 31126 +31464 * 30560 +18731 * 21477 +23081 * 27037 +8939 + 1705 +((13558 + 26473 - (10519 - 18168 - (4955 - 8331 * (12649 - 15377 / 5556 + 22403)))) * ((31645 - 24697 + 14729 - 14353) - 18639 - 18126)) +(1087 * 8481 * (17546 + 20275 + 20045 + 31142)) +2180 * 30565 +13558 - 23151 +4389 - 24102 +23035 * 7845 +((4459 * 3955 + 17777 * 18717) + (20721 - 198 - 15804 * 6230)) +2682 * 24136 +30867 + 10283 +((22788 + 9600 * 6565 / 24859) - (28898 * 5913 + 7075 * 4175)) +16940 + 7653 +13261 / 16553 +9962 * 32100 +((4848 * 19954 * 21000 * 26124) + 15819 - 24401) +7027 / 21821 +11409 + 13256 +(11458 - 20906 / 3673 * 9387) +2659 + 30780 +9279 - 27865 +(27052 - 9321 * (22319 * 12415 + 14915 * 26512)) +(24176 - 2299 * 29339 * 23041) +17265 * 10196 +(12386 + 3797 * 1751 * 27853) +((31603 / 1393 * 2939 - 5396) * 20296 / 27434) +21436 + 19004 +14426 + 2007 +8181 + 5495 +20144 + 23122 +26171 - 31047 +28 * 18172 +((20565 - 11186 * 1987 + 23000) + 4760 + 25326) +1353 - 9940 +(2102 - 12068 * (20187 - 11536 - (9382 / 13229 * 21309 * 12868))) +(26272 * 24610 * 4702 * 16967) +20457 / 27376 +(26833 + 32461 * 13453 / 26435) +25827 + 16585 +(24697 - 12060 - 25944 * 24516) +(10581 * 21344 + (30327 * 22220 * 31276 * 20806)) +(21000 * 20529 + 1230 + 26084) +32247 + 15155 +25848 * 29205 +((11780 - 32145 * 7491 * 6543) - 15503 - 27598) +(8685 * 12332 + (26383 - 7784 + 32468 + 26841)) +10253 - 16076 +6956 / 31885 +27537 - 22194 +5271 * 8906 +28967 + 13275 +29111 - 20853 +(27081 - 21050 - (11417 + 2605 + 15443 * 13542)) +12771 + 30973 +15518 / 24409 +2102 + 19244 +16367 - 6350 +3359 * 30826 +26622 + 28466 +(9283 * 12356 + (14838 / 25331 + 27423 * 30358)) +20490 - 22109 +29504 + 1853 +((22513 - 4108 * 20743 * 8537) + 18745 + 28897) +(24581 + 15578 + 18914 + 16522) +(17487 - 10371 - 12630 - 21103) +17333 * 10019 +(((1409 + 5588 + 27574 * 24479) * 1575 * 22000) * 16951 - 10454) +(27962 * 27261 * 17385 + 1165) +((31434 * 29866 + 26009 - 31499) * 17790 + 4154) +1021 + 6037 +19477 + 13695 +17260 + 26809 +30059 * 1927 +20555 + 13997 +27617 * 26423 +20263 + 31842 +21515 + 4788 +12422 + 11348 +2874 * 11949 +(7453 * 19491 / 490 + 30134) +4523 - 14327 +25329 + 8888 +19200 * 5921 +1153 - 11841 +12985 * 11526 +17459 * 5382 +(27323 + 19072 - 27263 + 28419) +16125 - 14663 +22702 - 7723 +30993 * 21405 +17077 * 29722 +18169 - 8404 +7421 + 19695 +(14874 + 30293 * 18843 - 19895) +7750 - 19089 +16083 - 14265 +24536 / 577 +9395 / 960 +3897 - 11008 +(7267 + 18179 - 5600 * 24174) +3825 - 11850 +4461 + 23227 +23818 + 11239 +((21687 * 14939 - ((28565 - 14657 - (25808 + 28872 + 7429 * 21855)) - 26436 - 29873)) + 4545 - 28058) +(10753 + 3342 * 16959 + 2299) +10856 * 21092 +29762 + 12783 +23189 * 15866 +(17098 * 20288 + (16435 * 31323 + 19744 + 5364)) +17238 - 30910 +21801 - 107 +(16082 - 25543 * 31318 - 13231) +26931 - 13408 +18243 * 20678 +15528 - 23619 +((14887 - 13069 + (16198 + 31685 * 25365 - 4221)) - 21877 * 25028) +24186 - 6409 +31929 + 22241 +6604 * 31829 +26340 * 112 +15589 - 31443 +3433 * 10654 +14629 - 31469 +18083 + 5126 +25059 + 976 +17649 - 25462 +3282 * 12566 +11819 * 30291 +(18103 * 26119 - ((59 - 13549 - 17191 * 24171) / (17202 * 2979 - 31977 - 3155))) +24057 - 29853 +7514 - 728 +((16533 + 26259 - (16758 / 5869 - 20940 + 3565)) - (16909 + 31628 + 29869 + 13261)) +4947 - 11016 +10838 + 24939 +3348 - 8853 +5179 * 22363 +(2488 - 26586 + 801 * 19035) +3164 - 29154 +27259 + 17300 +29686 - 17799 +10898 + 18178 +(13651 + 7462 + 22145 * 32173) +24275 / 10446 +6736 + 5493 +17869 + 8470 +(25837 + 1822 - (((22359 - 5988 - 14227 - 14739) / 798 * 14201) - (32480 + 17234 + ((25441 * 18271 - (12724 + 5157 * 17287 - 5068)) + 20784 - 32516)))) +13728 / 25100 +17073 - 18192 +7174 - 12665 +30780 - 31272 +((11773 * 20 - 16217 + 1124) - 14333 + 14051) +1085 / 28194 +14492 + 16841 +(32277 + 30776 * 27413 / 23832) +1158 - 14208 +22512 - 142 +24420 * 9806 +20004 - 30828 +15243 + 300 +3745 * 26915 +20837 - 12967 +30672 + 6033 +11480 - 20425 +17051 - 2189 +7836 - 24595 +17367 / 19177 +25940 + 9950 +19517 + 26583 +7365 - 1359 +5719 * 24704 +25954 - 5064 +9691 + 22036 +11427 / 11663 +(25859 + 15932 + ((26542 + 904 + 1762 - 23755) - 30351 * 30433)) +(48 * 31093 - 17486 * 763) +(22438 - 29392 * 14805 - 9546) +14850 - 22969 +25806 - 31903 +(3822 - 21913 + 1188 - 7852) +15999 - 19826 +30998 + 15146 +18379 - 31982 +26323 - 29407 +11977 + 26389 +23507 * 17263 +28147 + 6456 +1889 - 6282 +31924 - 17801 +(1479 + 29008 - 16172 - 30922) +18060 - 26296 +11249 - 6176 +30577 - 32622 +(5516 + 13167 - 5971 - 21934) +21077 + 15695 +26032 - 27459 +25634 + 28334 +(6812 * 4433 - 25600 * 3960) +24664 * 23321 +21050 + 30769 +(23468 + 22129 * 22621 * 17779) +(8967 * 27673 - 21311 * 30778) +14734 - 25320 +10942 + 16201 +4334 + 756 +(12585 + 2106 * (1186 * 7727 - 30373 - 32714)) +9781 - 31152 +4594 * 5946 +7469 - 17299 +((((18330 - 22208 - 8444 + 1367) * 30370 + 25375) - 8153 * 17833) * (21643 - 25614 * 25103 / 30350)) +31269 + 13233 +30351 * 22747 +14430 + 9252 +11938 - 27612 +29789 - 26565 +(31164 - 23309 + 11441 - 3745) +9962 + 24341 +8250 - 32346 +(31464 + 3533 - (21747 - 18912 * (26310 - 14729 + 30406 + 20546))) +5799 - 3276 +27506 * 27502 +22865 * 16579 +9279 + 2086 +26070 + 13668 +(644 - 4169 + 26753 - 29398) +12889 - 23126 +((8828 * 29595 - 6005 + 15188) - 14952 + 16584) +20573 * 31166 +31941 - 31132 +28735 - 25756 +25770 * 13511 +31605 - 1138 +24255 - 14684 +28613 * 30260 +21413 / 32051 +26599 - 1053 +8843 - 26049 +12030 - 27525 +((13265 / 13756 - ((4018 * 679 - 27597 - 29818) - 12073 * 7139)) - 29240 - 29540) +(29953 - 11664 - (7663 / 22114 + 13584 + 18017)) +31869 / 15478 +29199 + 15597 +((26100 + 30209 - 4816 - 10824) + (2860 - 15628 * 16316 + 26889)) +552 + 14418 +(31592 * 29423 - ((6529 - 26846 * (8394 - 16450 - 19590 / 30504)) - 31542 * 16201)) +13883 + 23634 +(2707 + 952 / (((14278 - 26477 / (29341 + 13220 + (6183 + 6888 / (5560 - 2242 + 19352 * 6609)))) + 2183 * 20334) + 15913 * 14708)) +1388 / 8508 +12491 - 20069 +(20859 - 19891 - 19286 - 12591) +22919 + 15942 +22167 * 32436 +8185 / 2068 +21609 * 3848 +(11547 * 11353 * (8264 * 806 - 30151 - 19592)) +6377 + 5846 +(9127 - 14182 + (20747 * 28257 / 19903 / 1255)) +27763 * 6590 +5189 - 26314 +10300 + 497 +27014 - 11059 +8704 / 10742 +15046 - 27711 +(22584 + 346 - 26941 - 18374) +((14390 - 16057 - 14955 + 3848) * 17648 - 24327) +879 + 8428 +(19466 / 2031 * 27381 + 32042) +29786 * 16564 +4793 - 12885 +27007 * 27881 +15157 - 31793 +5800 - 8656 +2795 + 15601 +18386 - 14202 +30513 - 17330 +1454 * 4188 +21405 * 24523 +22182 + 10789 +9432 * 28537 +12278 + 30242 +9504 - 29630 +25039 * 25544 +(14233 * 28284 - 6793 * 6548) +29728 - 14094 +1775 - 21653 +(9965 + 388 + 15664 * 29131) +25243 / 21695 +8560 + 9961 +19713 * 13637 +7937 * 28674 +15041 - 1244 +20617 + 11876 +(25909 + 21449 - 2077 - 20862) +(12666 - 18557 * 24987 - 25522) +21135 - 15856 +9108 - 30659 +18898 - 10278 +11105 + 27960 +(16066 / 31896 - 5285 - 8636) +26435 - 7906 +(13358 + 10737 * 265 * 22810) +23019 + 23008 +(10464 + 24931 * 3638 + 29669) +14781 + 1007 +(17241 - 31535 - 23476 - 12024) +18542 + 5062 +(18749 - 22940 - (860 * 20825 + (27154 / 4314 * 17087 * 28472))) +((9798 * 9613 + 26568 / 32100) * 20149 + 18523) +15498 - 522 +22797 + 23287 +2526 * 11344 +(10583 - 9072 * 7377 * 6782) +19069 + 28561 +2458 - 6416 +15612 * 16436 +(32449 - 21310 / 23024 * 23054) +22959 / 2442 +537 / 21364 +(24984 / 19011 - 27482 + 26435) +8853 - 765 +24473 - 12460 +5676 * 5424 +15100 * 11164 +24637 - 18527 +25216 + 8315 +180 + 27385 +5086 * 24417 +14788 * 17815 +(22715 * 14515 / 16178 + 30855) +(19679 - 1266 + 32288 * 17120) +22052 - 7846 +25755 - 26246 +24802 + 30999 +2303 - 8157 +13586 * 16051 +28381 - 17686 +24608 - 31160 +24541 + 20407 +14257 * 9085 +(29606 * 6463 * 24200 + 20857) +17459 + 18787 +(24282 + 805 * 22411 / 17434) +((9735 + 26162 / (31765 - 30037 - 22002 * 2125)) - (13593 + 10587 / 3559 - 17661)) +(2648 - 23849 + (6799 - 4897 * ((17041 - 10996 + ((28802 - 707 + 6932 + 18854) * 3487 * 10660)) + 22325 / 26799))) +18780 + 2591 +31695 - 23278 +3610 * 26698 +29292 * 10019 +13815 * 29073 +8697 * 4932 +5947 + 5807 +26321 / 9710 +6548 * 180 +(16521 - 20407 + 15545 * 4351) +5466 + 10682 +629 - 31038 +21571 / 25240 +21223 + 24091 +18707 + 7028 +(7080 * 25565 - 11301 + 15548) +19728 - 13220 +16887 * 791 +6348 / 1870 +10095 * 729 +(469 + 23795 * 20652 - 361) +12418 + 28803 +20281 + 28523 +(15065 - 11418 - 22132 * 27369) +5843 * 17575 +15255 - 21205 +22461 + 5927 +22770 - 30299 +8383 * 32533 +9671 + 2875 +28675 - 24655 +4568 - 25317 +31198 - 17678 +2721 * 23470 +14396 + 27435 +26572 + 4568 +25760 / 7095 +2060 - 16918 +11023 + 12681 +5616 * 24501 +(21671 + 14882 - 7463 * 12836) +(9412 - 16318 + 20035 - 26122) +((22988 * 22780 - 7592 - 29739) - 2521 * 4100) +9277 - 17575 +4567 + 10819 +8152 * 29914 +31733 * 8755 +(((24869 - 21637 + 12223 - 12581) * 22002 - 32294) * 22450 * 3502) +2652 - 17636 +24394 * 31361 +(30840 * 28041 / (448 * 10751 + 26612 + 21801)) +19830 + 17454 +3258 + 11506 +3207 - 21727 +19298 + 22600 +15983 * 21844 +31496 * 12686 +22501 * 26213 +29849 + 4030 +3015 * 2663 +(30771 * 11442 - ((32027 * 11927 - 16522 / 27166) + 18837 * 31859)) +775 / 30740 +26697 - 25381 +14105 + 2302 +(((26984 - 21182 - 14434 * 30988) - 28842 - 21604) - (4593 * 27172 - 28606 + 1907)) +(25743 + 14786 + 9337 - 4641) +10081 * 28939 +28186 * 31105 +25221 - 18156 +30337 * 30436 +(13821 + 5249 + (16315 - 32144 - 14205 * 23497)) +8498 * 7378 +23488 - 558 +(11299 - 1224 - 13016 + 966) +1510 - 15115 +20944 * 13256 +20241 / 16261 +7842 * 27834 +(29783 + 21903 / 4831 - 68) +20497 * 2279 +31106 + 2683 +24262 - 11289 +26190 * 2379 +21386 * 4140 +22688 - 21553 +2043 / 22500 +26955 * 28704 +7165 - 13782 +19736 + 26016 +30521 / 20088 +(28953 + 4526 - 13704 - 25828) +30600 * 19403 +3365 * 24670 +30241 + 29155 +2379 + 11829 +30403 - 28478 +8291 + 31961 +31234 - 1121 +21625 - 16257 +3341 * 9552 +2259 * 22426 +26778 / 27809 +11971 + 3431 +14058 * 2102 +12586 - 15507 +23289 * 16967 +812 * 27146 +20158 / 28108 +135 - 5955 +609 / 14500 +23960 - 25963 +(18754 - 13819 * (14238 - 32699 - 29701 / 27798)) +((30950 * 25111 * 21477 - 26124) - 30244 * 32688) +31157 - 15842 +(2088 * 32751 - 6801 + 4291) +2994 * 10617 +(4271 + 7548 * (11644 + 13557 + 1520 + 5755)) +(20256 + 19026 - 11932 * 31137) +11281 - 6829 +(1288 - 32676 + (((682 + 13797 / (((9755 * 3977 + 16874 + 14547) * 18301 * 24533) * (12484 * 4386 + 16553 + 10558))) / 8389 * 25889) - 13545 / 737)) +31199 - 29270 +18841 + 18019 +(7289 + 32446 + 14719 + 10215) +5380 - 23595 +((((13023 - 12846 - 3310 * 32339) + 1800 + 9448) * 11083 / 31166) + (27501 - 4049 + 29607 / 6045)) +14103 - 28866 +(20837 + 22026 * 13226 - 10545) +31575 - 5667 +12809 + 25222 +15007 - 4546 +31272 - 14796 +4328 * 27282 +28844 - 22403 +(31891 * 24582 - 3279 + 24521) +13099 + 25536 +(22542 * 28516 + 8386 - 9309) +((4216 + 26925 * 23386 - 6296) + (21106 * 18495 + 16764 * 32726)) +878 + 8853 +14769 * 28587 +30729 * 13517 +22340 - 20755 +((13971 / 28705 * (1513 / 20904 - 5270 + 903)) + 238 / 30148) +((27500 + 22644 * 27871 * 408) / 27573 - 32540) +28950 + 7918 +8707 + 17491 +7902 - 23168 +32576 - 7558 +16646 * 12782 +15287 + 16633 +29185 - 7760 +7631 * 15633 +12546 / 324 +6203 * 20260 +26366 + 8511 +20532 - 21871 +13566 * 18832 +30587 * 24425 +32754 * 11321 +(11164 * 19662 - 30669 / 14521) +30611 + 27720 +22760 + 10955 +18704 - 24948 +15293 * 27587 +30033 * 31693 +27619 * 25028 +8713 - 24092 +30897 - 19958 +25569 * 16748 +(7707 * 21945 / 9829 + 23657) +19918 + 11058 +4232 + 10830 +(8014 - 17668 + 20722 + 17589) +(13807 + 12823 * (18130 + 30401 / 4910 / 24162)) +29504 - 8071 +(26433 + 22607 - 25514 + 22710) +5613 * 17446 +22952 - 18033 +(6444 * 31785 - (27226 * 3797 + 7213 + 17198)) +12 * 15800 +6552 - 12021 +4239 - 22295 +(3820 * 10623 / (32412 * 12492 + 30074 * 489)) +((5490 + 12911 * 1969 + 31840) + 10746 * 27144) +14401 + 20743 +18008 / 835 +25836 * 25090 +22873 * 989 +((17752 + 24276 * 26764 + 5463) + (23023 * 27233 + 29154 * 24683)) +(20463 - 20447 * (15198 * 1631 - (((23301 * 13257 - (17497 * 9774 + 8440 + 1118)) + ((20572 + 3626 - (5735 - 11797 + (31765 + 20365 * 30911 - 12636))) + 22898 * 25273)) - 30714 + 32319))) +583 - 12748 +(9136 / 20879 - 17002 + 18015) +30392 - 10835 +28254 * 25024 +(25616 - 23880 + 12563 * 31148) +17597 * 7632 +31787 * 24780 +23748 * 24989 +13428 * 18018 +(8364 - 8700 / 6622 / 14668) +(23420 * 4384 * 5561 - 27418) +12905 * 776 +14410 - 2676 +437 - 12409 +21335 - 24353 +(27675 - 16769 * 3207 / 19063) +29476 - 13989 +7553 - 12336 +(5906 + 14440 + (29286 + 17204 + 10943 - 9667)) +25178 * 6736 +4774 / 4295 +(17470 - 10592 - 25828 + 27695) +(((16897 * 8820 * 17813 - 13434) + ((4057 + 4165 * (9704 + 11072 * 8644 - 7768)) - 27334 + 14691)) / 27575 * 13872) +14195 * 20162 +15327 * 6379 +10636 * 27163 +2068 + 6946 +32235 - 9076 +30536 - 29433 +(20704 * 17699 - 28337 - 4848) +19650 + 13221 +26327 - 16121 +11113 * 11362 +5629 * 28948 +17077 / 11163 +12916 - 13052 +10353 + 25362 +7811 - 5746 +10148 + 30879 +4519 * 21367 +17793 * 9326 +9078 / 26518 +(15554 + 15243 + 4324 - 19991) +11562 * 9070 +(14670 - 23725 - (29199 + 24799 + (3609 * 29558 - 8864 * 6291))) +(20002 * 24914 - 13146 - 26143) +12427 * 26338 +30506 / 25415 +(7413 - 13543 - 20353 - 13514) +20385 * 20300 +16529 + 17787 +16779 + 32512 +(21948 * 5650 + 16218 - 25161) +9993 + 22989 +2508 - 17297 +2591 / 14348 +(17331 + 15281 * (7791 - 5450 + 20217 + 20218)) +29241 / 6514 +14424 * 10457 +30362 + 27486 +19623 / 20611 +17782 - 31698 +32160 * 10909 +7011 - 21892 +27581 + 404 +30803 * 6103 +(18449 + 17181 - 14206 - 17746) +11760 + 3196 +(13076 / 30022 / ((20698 - 6997 * 24223 * 5302) + ((3485 * 4467 - 31955 - 1987) + (24229 + 21959 - ((4038 * 9830 * 2590 + 23127) * 18254 - 11121))))) +31040 + 4944 +28309 - 3278 +10718 * 13150 +24706 - 32693 +7216 * 11566 +10831 + 12934 +17202 * 24522 +((26530 + 31192 + (((25573 + 5644 * 31403 + 17557) * (30846 - 29199 - 13337 + 19456)) * 32533 - 29897)) + 11195 - 11110) +21816 / 22217 +24651 - 10109 +((18438 - 20362 * 9216 - 11874) * 8560 + 1701) +15742 + 13178 +15069 * 1087 +5799 - 23424 +32433 * 5000 +(6930 - 12368 * 15382 + 24600) +(29696 + 17870 + 12671 * 3170) +441 + 27578 +6221 + 13336 +22012 + 19009 +32577 + 31562 +8105 * 18525 +32356 - 17830 +((14930 + 6738 * 17839 + 15565) + 26752 * 25478) +18350 * 1169 +(25952 - 13628 + (26728 / 39 - 8446 * 283)) +(28365 - 15683 - (14590 * 26293 + 30102 + 21006)) +10163 - 12141 +12519 + 24470 +27506 * 30502 +6116 * 25716 +3324 / 32360 +20332 * 29301 +(30385 - 32472 + 18644 + 25265) +32179 - 18583 +14258 * 16786 +30546 + 2401 +(116 * 1901 - 10520 + 15618) +19281 + 23366 +9331 - 32291 +31478 + 1822 +20336 + 6136 +29612 + 27961 +6979 * 20550 +(14359 - 6205 + (24018 - 16705 - 3564 * 12835)) +6618 * 26313 +17331 * 21650 +(15432 + 5320 - 29652 * 24376) +(16516 * 6431 * ((17141 + 4248 * 29117 * 32511) + (14407 - 30249 - 20612 + 11326))) +(5097 * 4055 + 18866 * 7346) +30146 + 18954 +10352 - 1668 +22013 / 26819 +19607 - 24085 +(16781 - 21496 * 11694 + 9614) +18213 + 14284 +20245 + 23058 +8145 - 28054 +13881 * 13372 +23675 + 20445 +((((22974 * 555 + 30174 * 21536) * ((21198 - 858 + 555 * 21395) * (29890 - 14994 * 5878 + 7012))) - 25467 - 25821) + 2914 + 29862) +((2666 * 8536 - 6478 / 17974) - 32511 + 3811) +14332 + 29441 +(11450 * 4942 - 31558 * 24500) +(28576 + 12133 + (19203 * 13267 * 11535 * 4333)) +(10805 + 5507 - 28213 + 18390) +16520 * 30575 +28521 - 20764 +12263 * 19331 +(28188 + 18837 - 30136 + 23951) +(5020 - 28220 - 11153 * 6966) +24959 - 9681 +22658 + 15916 +28618 * 17831 +18471 + 5211 +2176 + 4687 +22487 + 6147 +(6630 * 27617 - (11885 - 1745 + 19864 - 5332)) +15737 + 14339 +21705 * 29569 +10254 - 16263 +10791 * 29181 +6605 * 11539 +29607 - 2554 +20523 / 26006 +(5892 - 4658 - 5897 - 4316) +(31580 + 32425 * 14331 - 1041) +(4136 * 5957 + 6270 - 1809) +3164 * 16597 +25211 + 14104 +24756 * 21808 +12604 - 21528 +517 / 21787 +16762 + 5572 +23013 + 7275 +(6087 * 8463 * (31838 * 31434 + 15711 / 31254)) +((16776 + 1207 + 17876 - 29552) * (((27540 - 30415 * 28780 + 12219) * 32300 - 20094) * (23478 + 13141 - 25140 * 31615))) +3635 * 23378 +(32071 - 25097 + (12736 + 13148 - 16802 * 22776)) +14702 - 10118 +27642 - 17817 +(9124 - 16891 * 15140 + 1865) +28251 * 7723 +11964 - 29553 +8820 * 19152 +31660 - 18255 +((15095 * 22390 + 16801 - 7329) - 8495 + 1193) +4062 / 13705 +20333 - 5250 +(16613 + 8296 - 714 / 15888) +29935 * 21720 +((16421 - 28021 - 25193 - 19653) - 28382 * 17940) +25529 * 15395 +(18091 - 20139 - 4821 - 21687) +6613 + 15403 +2233 + 22095 +((((1167 - 5081 - (16735 * 31684 * (26514 - 18891 / 14536 + 13715))) * 1795 - 8795) + (6758 * 14572 + 17009 * 8522)) - 23392 - 25770) +10146 + 521 +2073 / 29022 +(((6559 / 21260 + 18824 * 12123) * 3635 - 10006) + (29207 - 10185 - 19096 + 21194)) +3802 * 12972 +29527 - 17441 +16882 / 5601 +16375 * 8253 +12745 / 25384 +9346 * 32418 +5352 + 6322 +25569 * 28067 +((5759 / 15082 + 27130 * 11545) * 14387 + 26266) +(3498 * 25115 - 27218 + 17626) +27839 - 30703 +2704 * 32483 +3683 / 27408 +8463 * 4270 +3903 * 2098 +(1942 - 20022 + 24893 / 31150) +477 * 5648 +16010 - 9404 +28376 * 13414 +26074 / 23530 +(20380 * 13907 - ((13912 * 11690 + 26456 - 25159) * 9300 + 9535)) +684 / 30699 +(27264 + 25342 - (18892 + 17671 + (3629 - 24476 * 18330 + 19819))) +9118 + 14970 +4424 * 22086 +20741 - 8544 +3130 * 17231 +20111 - 5349 +(12928 - 3600 + 31938 + 7788) +22582 + 14319 +(8588 * 18540 * 28757 * 8984) +16100 * 1289 +13669 * 11091 +((26178 * 1125 + 1006 * 32533) / 29458 - 28767) +12619 * 14195 +(28874 + 23467 + 32572 - 19435) +2892 * 18684 +25303 * 2212 +(18995 * 12472 / 542 + 9670) +12359 + 25417 +15246 * 22997 +29682 * 12629 +1303 + 4072 +11870 - 5284 +28237 * 13786 +22500 + 27276 +(18872 / 31647 - 19787 - 30593) +2306 + 779 +8463 + 7997 +12353 * 21876 +(18046 + 3499 * 2529 + 13674) +(27010 * 16487 - ((30924 + 11853 - (27585 * 10473 - 30976 * 1033)) + 25006 - 7182)) +1946 - 4422 +2396 + 3512 +71 - 21188 +18003 - 18720 +7305 + 11633 +13663 + 25966 +(10469 * 28015 + 1786 - 7702) +10907 + 2452 +(((20432 + 4808 - (21111 + 8350 - 17528 + 4040)) / 6526 - 17483) - 18413 * 8256) +(22717 - 19510 - 30997 + 23883) +(144 - 15444 * 29355 - 19417) +10143 + 21473 +((5494 + 17800 * 19479 - 2820) - 1109 + 7069) +28942 - 21417 +9579 * 1807 +4719 - 1449 +1685 + 15326 +10960 * 25087 +31314 * 13519 +7366 - 28858 +(30092 / 15607 - (25865 + 21105 - 524 * 28188)) +17198 * 11841 +(27351 + 11843 - (4861 + 27662 + 20937 * 24739)) +4497 * 22618 +((495 - 7738 * 25872 - 11809) * 29307 - 27173) +14440 + 22880 +27875 - 932 +13177 - 14780 +13666 + 650 +11267 - 6931 +(19804 + 23609 / 20922 - 4060) +(((32616 * 9711 * 28237 + 21402) - 26688 - 28643) * 11525 - 17511) +26626 - 8666 +6775 + 22561 +21427 * 9143 +12788 / 3813 +25744 + 24527 +21143 - 4179 +1612 + 17826 +15635 - 22565 +9731 / 31353 +16634 * 32264 +24831 + 9337 +32013 * 29704 +21126 - 18931 +390 + 3717 +1568 - 14635 +29992 * 911 +18070 + 25446 +3164 * 20123 +24620 * 3322 +17746 * 26431 +4140 * 6500 +18406 + 12681 +11191 + 5992 +4551 * 24328 +26896 * 10741 +7848 + 28082 +14993 + 29955 +(18492 - 28407 + (14240 * 13830 * (22475 - 415 - 25492 - 32173))) +19188 * 29307 +5948 + 29740 +26490 - 8505 +13620 * 2172 +1607 + 27588 +(6245 + 21526 / 25783 * 11317) +20550 - 11836 +11963 * 17043 +1103 + 32377 +7080 / 4295 +10739 - 17398 +27216 + 25731 +(17379 - 8209 / (23865 - 3167 * 17105 - 211)) +25390 - 4710 +(8424 + 15975 * 321 - 11334) +19786 + 3399 +2180 * 9915 +11108 - 15598 +(18965 + 8225 - 21991 + 30065) +32230 - 8350 +26288 * 9427 +27076 * 29642 +19340 + 11114 +5274 - 23874 +17927 * 12907 +(21060 - 7066 - 9750 - 23664) +(6657 + 9530 + 32238 * 18339) +31262 + 24986 +32423 - 2563 +748 - 18717 +16302 * 10019 +12278 - 26873 +(13421 + 16844 + 11806 + 15102) +205 - 22922 +6225 / 4179 +5423 + 13589 +492 / 9463 +12929 / 10372 +(18425 + 10892 * 10020 * 29514) +21735 - 2599 +28511 - 18120 +17766 - 28763 +(12792 + 28620 - 19641 * 15381) +9267 + 17628 +22250 * 16761 +(9543 * 8901 + 21592 - 28635) +16408 + 9497 +(29220 + 10530 - 21513 + 30211) +31232 + 15540 +22043 + 9085 +11170 - 8062 +11035 * 21293 +17547 * 5347 +9996 * 13676 +(30322 + 16479 - 26915 * 16772) +(7139 * 23908 - 29023 + 14790) +25937 + 13954 +28902 * 23564 +13822 / 27396 +11836 - 206 +27763 * 21095 +(2406 - 18917 - (16282 - 31205 + 23749 - 31002)) +12291 + 30696 +32199 - 28711 +(4822 * 27927 * 13223 + 9037) +1949 + 3494 +23589 - 4907 +28335 - 1111 +1870 - 31664 +5269 * 28792 +1860 * 20045 +11207 * 12497 +18178 + 548 +(12903 + 25385 * 27768 + 13564) +(25354 - 12393 * 18133 * 28250) +12798 / 20436 +32623 - 23890 +(14114 + 23852 + 2562 - 6642) +17076 + 808 +27563 - 25337 +21038 * 30804 +24530 + 4146 +638 * 6720 +28891 + 21301 +17194 * 4388 +24746 - 16266 +23059 - 12464 +(3279 + 6097 * 19152 - 18780) +29693 - 16416 +((29279 + 16963 * ((11921 * 15595 + 13829 * 21380) - 30690 + 14059)) + 20796 + 25338) +31441 + 23969 +11296 / 18857 +26540 - 11450 +1130 * 11238 +15411 * 3349 +(32142 - 19454 / 24090 * 21243) +14453 * 26733 +23978 - 22996 +26578 * 23891 +21991 - 13420 +6530 / 20570 +3620 + 1859 +(11443 + 28510 + (17142 + 12227 * 27298 - 18184)) +((15877 - 16113 - 24167 / 32767) - ((29742 - 7709 - 19549 * 10279) - 11913 * 728)) +8155 - 13879 +12708 - 14959 +32757 - 24698 +598 - 9143 +(19297 - 31295 * 17515 - 30072) +9206 * 19686 +20087 - 30309 +5954 * 5196 +30717 + 5733 +28932 * 21922 +23491 * 15740 +23167 - 19226 +15854 / 5319 +24814 - 959 +(24708 * 29032 + 31117 / 19064) +3062 - 1695 +32188 * 16247 +((27128 / 25905 - 9974 - 31520) - (7750 - 9972 - 16239 - 1774)) +1273 - 22611 +3182 * 10396 +15723 * 24758 +10443 / 29127 +25313 + 30761 +27085 - 16878 +535 / 1976 +(25364 - 13303 - (25102 + 30133 * 10852 - 21952)) +25478 - 16042 +2514 + 25021 +(12282 - 20884 - 174 - 5774) +26478 + 20598 +20583 * 28969 +11144 + 10788 +639 / 19730 +16383 / 8745 +1252 - 5350 +(18417 - 7865 + 22965 * 4155) +(10191 - 16612 + ((12743 * 26739 + 4581 + 32460) * (30055 - 22085 * (15433 + 14802 - 11154 + 6808)))) +((8680 - 26898 * 2652 + 1591) - ((14710 * 8820 - (1610 * 18016 + (((6967 + 1337 * 6341 + 19717) + (24943 - 3670 + ((24761 - 13652 * (31494 / 12335 * 357 - 29976)) * 20650 + 10585))) / 9259 + 18602))) + 12435 - 16858)) +(2018 + 20158 * ((2274 + 23956 - 22248 + 6634) + (7303 - 24048 + 18622 + 2136))) +16717 * 30150 +22879 - 18703 +30543 + 2451 +28502 / 21308 +155 * 14661 +3755 + 5167 +(30192 - 1538 + 10882 * 15504) +2415 - 6671 +32545 * 20224 +4931 - 21475 +(28918 * 4094 * (10184 * 9927 + 24686 * 6988)) +27763 * 9489 +24005 + 23044 +15541 * 28791 +21999 * 16907 +29470 / 17232 +3852 - 10040 +24509 + 15993 +7496 * 22700 +27486 * 12822 +18926 - 13279 +3522 + 26373 +31297 * 742 +28109 + 29821 +(20535 + 12053 - 11816 * 18757) +19954 + 22189 +((27775 * 18689 + (14932 * 29659 + 2153 + 17141)) * 6319 + 17733) +14736 - 29872 +19927 * 28917 +31256 - 4976 +2647 + 31060 +21089 - 13850 +6728 - 13656 +15795 - 3542 +30792 / 18620 +6670 + 20008 +(10522 * 26455 * 32604 * 23427) +13700 * 2822 +2753 * 27317 +1061 + 28763 +21935 * 17259 +21488 - 20551 +15995 * 3943 +7243 + 24392 +8553 - 25111 +12729 + 23403 +(21362 * 11718 + 32474 - 14896) +19170 / 21745 +(17478 / 19002 + 11340 + 3812) +19953 + 7518 +29896 - 8118 +((((10119 - 17679 + 22374 - 20992) + (22611 + 8214 - 13039 - 10414)) * 13554 + 30071) / 22258 - 9386) +20489 + 3794 +22991 * 16764 +(16811 * 27469 + (24563 + 153 + (5204 * 5124 + (11378 - 5844 - 1496 - 31577)))) +(26412 + 32322 - (26657 + 22210 * 14622 - 18888)) +(((23575 / 12785 * 4251 + 16524) * 10474 - 1019) - ((29784 - 30021 + 11301 - 27311) * 14658 + 2569)) +1668 - 999 +((542 - 20403 - 17808 + 3103) + 20956 - 14713) +12323 + 16229 +1199 + 14260 +16613 * 22374 +28447 + 19000 +21398 - 17831 +(7869 * 26837 + 32630 * 2991) +22191 + 11734 +25261 - 11579 +13018 * 2401 +(32120 * 12895 - 4122 + 4421) +(4147 * 28975 + 3520 * 8273) +14828 * 27357 +4222 * 10994 +2356 - 23344 +((10630 - 3729 - 5885 + 27767) * ((13204 / 26277 * ((23753 * 10239 - (15350 + 10316 + 4757 / 17618)) * 12917 * 5572)) / 15226 - 9718)) +1657 - 11758 +(18057 * 31758 / 21650 + 8030) +12138 * 27530 +1734 - 28797 +23722 + 24678 +17740 + 25580 +12389 * 30264 +(18440 - 25152 - 21519 + 7574) +10090 - 32300 +(5054 * 11466 + 15392 * 10505) +(24366 * 11091 * 27973 - 4626) +15298 - 4980 +(24111 - 16847 - 10115 * 18015) +2832 / 20363 +(15775 - 7606 * 16071 - 17267) +14705 + 28085 +19439 * 29426 +(15291 + 31135 + 29796 - 32174) +10956 / 19322 +6479 - 29830 +28204 * 15954 +21288 - 19172 +(22692 + 10509 * ((3115 * 19858 * 30687 * 28219) * 5647 * 27148)) +((5487 - 22423 * (21792 * 3435 - 4136 - 16485)) - 29872 * 8883) +(9844 / 23899 + 13630 - 24697) +29263 + 19264 +17806 + 30817 +(5679 + 21731 - (17000 * 10251 * 8412 / 29299)) +22522 * 6783 +5625 / 13446 +17947 * 10528 +22876 * 21370 +32719 - 2791 +28776 - 5840 +19832 + 31566 +(23260 - 3532 * (32432 - 26557 + 8906 + 24516)) +(24177 - 6135 + 31782 + 69) +(11764 * 2934 - 5790 + 4782) +(7341 + 18440 + 28567 - 8883) +20579 - 12081 +29764 * 7342 +11221 - 12103 +4487 - 9976 +24378 * 2025 +20192 + 30005 +15666 + 29529 +28889 + 2063 +(((24673 / 28548 - (12667 + 26264 * 6527 * 18106)) * 29361 * 9137) * 13268 + 10245) +23805 * 5247 +(11740 / 29139 * 18991 + 18815) +(8431 + 5673 * 17692 - 18586) +(3761 * 1261 * 26776 - 63) +(29743 + 11050 - 21297 * 14105) +13451 - 10401 +22042 - 16876 +5736 * 18843 +17799 * 16808 +(19032 + 6895 + 21437 * 4550) +(27938 + 28926 - 21853 * 24937) +22539 + 13886 +(24910 + 23997 - (32004 / 25883 + 23161 + 10710)) +326 * 20659 +(14231 * 9586 * ((23081 - 6613 + (19692 + 9911 * 18497 / 24983)) - (30512 - 16343 + 27630 - 19610))) +24001 * 6044 +8755 + 1183 +11001 * 16090 +1774 - 2799 +27772 / 8241 +5125 - 10904 +11220 * 21177 +12781 * 15756 +32329 - 8758 +8917 + 12756 +22423 - 2741 +28980 / 25816 +21605 - 27191 +23160 + 21339 +9029 + 20235 +(20262 - 9468 - 10150 - 2054) +(12434 * 30453 - (25980 + 27433 + 28854 + 29526)) +6097 / 420 +(1343 - 23944 * (11366 - 13764 * (11709 + 18592 - 4215 - 30914))) +9570 / 24394 +(12426 + 21335 * 32005 * 25135) +(23272 - 14418 - 6638 - 14119) +(((27191 - 11859 + (19124 * 16241 + (16811 - 31214 + 2797 * 1528))) - 25020 * 24408) - 17664 - 12381) +(26974 * 25135 - 11526 * 25109) +32704 - 24266 +11734 / 31918 +17561 + 32715 +23853 * 10760 +32061 + 28791 +28661 - 27581 +5476 * 30749 +3636 - 27336 +3587 + 26447 +12917 + 24666 +29736 + 9570 +(26148 - 5136 - 2150 - 331) +(9527 + 7272 + ((31915 / 17636 - 32648 + 6911) * 32081 + 23049)) +25486 + 4655 +4762 + 15875 +12945 * 7931 +864 - 1460 +14867 / 13764 +2381 - 6207 +5455 - 27041 +14653 - 30504 +9502 * 29920 +(10066 + 5965 + (21942 - 16159 - (18751 - 29044 * 12554 + 19652))) +4177 + 12839 +8412 + 32619 +18354 * 16635 +(28020 + 2001 + 27763 - 21251) +15124 * 14983 +2115 - 7889 +(26741 * 25836 * 15582 * 22576) +20779 + 14570 +(8939 + 2488 - (18933 - 28938 / 15648 * 17231)) +((20890 * 3558 + 14607 - 23335) * 713 + 1423) +(11933 * 9738 + (17534 * 18355 + 21865 * 3314)) +6215 * 4876 +31376 / 30013 +25653 - 4592 +12010 - 27525 +2964 / 285 +25453 + 10034 +28844 + 29083 +5045 - 6395 +((29469 + 3201 * 3854 + 5013) + 26508 * 8944) +11541 * 31205 +(10558 + 719 - (18327 / 30052 * (4608 - 4296 + (((9086 + 10271 - 29283 * 292) - 24176 * 1401) * ((2692 - 20457 + 14893 + 10130) + 19397 + 9715))))) +26107 / 576 +21546 * 1375 +(11776 - 24784 - 24739 - 5917) +9488 * 18129 +21347 + 19355 +13493 - 2470 +27715 * 21470 +26298 - 19039 +27304 * 10231 +(10323 * 18257 / 797 * 7565) +204 - 11325 +30718 + 3188 +(27549 - 21469 + 21434 + 10415) +650 * 29627 +19232 + 29522 +((17784 - 12656 + 27360 + 11923) + 25228 * 18452) +(19237 + 6230 * 13142 + 15611) +15890 - 366 +526 * 31083 +((23802 + 1325 - 17777 + 8246) - 9821 - 31198) +((2169 + 23778 * (5486 + 1441 + 6949 + 15852)) - 4141 - 14628) +(31806 / 25792 * (27809 + 16555 - (11833 * 31866 + 11240 - 24250))) +7722 - 19037 +22697 * 28029 +16448 - 24612 +13909 * 26181 +1389 * 32006 +(25846 / 15988 + 8080 - 22909) +32687 / 17746 +1403 * 4911 +14363 + 31901 +31589 - 23296 +9472 + 1937 +19698 + 11323 +1690 * 27210 +1090 + 20334 +7975 - 20231 +(22356 * 26584 + (1150 + 22764 - 897 - 4882)) +25093 - 8222 +14492 / 28279 +2726 * 29554 +(8595 - 8112 + 28017 + 11563) +(11321 * 9884 + 15152 * 23784) +23467 * 22136 +12164 * 5036 +25635 * 9648 +((1512 * 19244 * 25144 + 11705) - (871 * 3188 + (11701 * 31040 * (7777 * 25849 * 31501 - 1406)))) +22186 - 14565 +23096 - 14890 +17822 - 8542 +789 - 25042 +6256 * 20016 +21712 / 22437 +31287 * 16696 +17602 - 7126 +6326 * 902 +24701 + 340 +738 + 14159 +23764 - 5837 +18122 * 10302 +((17781 * 32598 - (29914 - 23961 - 24587 * 18826)) + 24372 * 24834) +26897 * 31438 +7893 + 11854 +((2980 - 6912 - 14897 * 22686) * 31757 * 30225) +(1117 / 8172 * 13764 - 11610) +10303 + 9586 +(9137 - 24022 + 25144 + 28224) +5122 / 7202 +25779 + 16235 +26896 - 5527 +(27285 + 6777 * 24167 - 7989) +15222 - 9977 +12336 - 7188 +31401 * 31912 +28828 / 23102 +452 * 374 +(21139 + 17300 * 5074 * 13751) +14913 + 22631 +17952 + 19346 +(12514 + 1150 + (12560 * 5466 + 11344 - 16158)) +20221 + 14478 +26578 * 12016 +25072 + 24642 +23800 * 566 +7736 + 32264 +27369 + 11783 +28105 * 3824 +6588 - 16052 +18044 * 16557 +(12219 + 18652 - (((19259 + 4627 - 11602 + 20627) + ((19661 + 1832 / ((27983 * 32087 * 9694 - 18978) / 27049 + 19641)) * 16442 + 4994)) + (17016 * 13951 + 25768 + 29743))) +20600 + 25636 +31552 + 3077 +((6163 - 20201 * 24106 - 12655) * ((18450 + 26138 + 10115 - 1464) - 19510 - 26362)) +4412 - 30213 +((17227 - 17807 + 22543 - 27437) - 23016 * 2989) +26621 * 26852 +371 - 16538 +795 * 10396 +(18042 - 1858 * 24124 - 24137) +(22523 + 14720 + 13269 * 21777) +22548 / 29433 +18066 + 12886 +12238 + 20658 +10802 - 2670 +26610 + 23854 +5648 - 6292 +31529 + 31209 +31841 + 31828 +(28980 + 26946 / 9703 + 16608) +(20439 + 18761 + (32378 * 27606 - 19412 * 29195)) +(((553 * 29577 - 28441 * 8514) + (8818 * 14642 + (672 / 13728 + ((18671 - 10902 / 28692 - 6478) * (((5227 + 12358 - (9752 - 1221 * 5641 / 17901)) * (1825 * 18742 * 21808 * 6093)) * ((1655 - 22931 * 27302 + 15353) + 8880 + 5023)))))) * 15647 * 19935) +3241 - 28480 +13717 + 6142 +21012 * 22238 +4631 - 657 +18258 + 27812 +32083 - 21332 +27658 + 20311 +3768 + 8511 +2430 - 32436 +15917 * 19055 +9852 + 11444 +1133 * 19747 +12266 * 11563 +32134 * 29955 +(18098 - 17559 + 16553 - 18344) +13134 + 31110 +28938 * 14504 +22663 + 28118 +1910 - 31065 +28538 + 157 +(27256 * 15918 + (32580 + 12363 * 12324 - 26704)) +13821 * 18584 +(15302 + 9060 * 25933 + 26344) +21417 / 5419 +21124 / 2531 +3292 * 18582 +(7831 * 11321 + 4220 * 14488) +6185 + 23998 +16550 - 21046 +24075 + 4316 +7373 + 7222 +23007 - 6463 +24437 - 27051 +31546 / 2873 +12525 - 4809 +17137 / 13756 +9102 * 23142 +24577 - 22784 +5615 - 14617 +11193 * 31675 +31841 * 29367 +28658 - 5786 +6523 / 20032 +26440 + 14818 +24772 + 18681 +9280 + 6750 +13782 * 19678 +7889 - 30160 +20519 / 18071 +12878 + 14438 +((373 + 28280 * 11350 * 1849) - 31988 - 28059) +23864 + 18053 +30958 - 3155 +(24267 + 3050 / 17459 - 14068) +((24667 * 8978 * ((3554 - 8952 + 3036 * 19385) - 16433 - 19299)) + 3386 - 27799) +(28352 * 8617 - 25031 * 2230) +25688 + 7137 +27171 + 642 +20278 * 29277 +(15343 + 2435 * 12988 * 11056) +29338 * 23786 +13697 * 30066 +25598 * 4341 +4362 + 23573 +(8173 - 17219 + 17018 * 17456) +2677 - 20011 +15107 - 15688 +(15088 * 3734 * (21284 + 19222 + 18121 * 14681)) +14174 - 10855 +2269 * 2262 +11216 * 7878 +30382 / 36 +19299 + 8091 +(23376 * 765 + 8087 - 7061) +((9997 - 4852 / ((16567 - 20597 * ((31975 - 17712 + 1566 * 26399) + (18633 * 6882 + 15306 - 29221))) + (((20765 - 4269 * 32191 * 9962) - 1073 * 13472) + 4904 - 21127))) + 32221 - 22452) +10588 - 13941 +17727 - 4422 +17428 + 13638 +(6428 - 30801 - 15115 + 31318) +(6306 * 30588 - (7092 * 15673 + 17421 + 21619)) +23174 - 7565 +23406 - 14676 +(19625 / 6755 - 2722 + 3781) +((29844 / 11213 / 16476 - 18088) * ((31000 - 1942 * 23773 * 31166) * (25584 - 2532 + 21062 + 5967))) +12134 - 24561 +18503 * 27878 +((12854 + 16053 * (206 * 12116 * (13987 - 21569 + (24917 * 6237 + 4573 - 28111)))) * 3842 / 27986) +(26812 * 31956 * 3519 - 16890) +27201 - 17604 +16046 * 5903 +(9095 * 6826 * 15307 + 14890) +9116 + 29034 +14800 + 31971 +(6330 / 25552 + 12005 - 2230) +7573 - 24124 +30559 * 16882 +2038 * 13311 +17407 + 20730 +29731 * 11646 +((8675 * 18879 + 14189 - 27917) - 6467 / 18611) +16057 * 8996 +15068 - 11269 +11492 * 13442 +19720 * 20966 +((21396 - 8778 * ((23454 * 25942 - 24559 + 28934) * 11465 - 6896)) * 21207 + 6359) +((23948 + 5431 - 25504 - 7425) - 5185 * 11013) +27521 - 28454 +(((19639 * 19089 / (27360 + 18647 * 21168 * 23484)) - 21682 * 16728) - 7987 - 29948) +(8872 - 32753 + ((32701 + 20055 + 29318 / 20053) + 25859 + 15932)) +11685 + 356 +6437 / 30187 +5410 + 14979 +31035 / 12563 +(6650 - 2562 - 3438 * 24854) +((29605 + 2437 * (1215 - 12631 - 12167 * 17635)) + 17494 + 32495) +17689 - 16364 +23881 + 419 +((12882 - 31231 - 5295 + 26109) * 4258 + 18550) +7623 - 13531 +1048 + 4338 +16107 * 17252 +18853 - 32757 +3171 * 2620 +12329 * 9627 +10604 * 6443 +11858 - 30723 +25884 * 3567 +11397 * 32403 +(27531 * 27367 + 30067 + 10997) +9595 * 7828 +527 - 15920 +18014 - 2939 +22391 * 13728 +29631 * 6948 +23125 + 11646 +10587 / 28580 +24566 * 3994 +(29083 - 1667 + 2277 * 11955) +11989 - 29147 +6459 * 30570 +11777 - 9823 +(13190 * 18302 - (1220 / 20138 + 2282 - 24346)) +19393 - 5040 +10822 + 29963 +22087 / 20681 +1980 * 32529 +22985 * 30865 +22328 - 20073 +5297 + 10461 +1341 / 24803 +13942 * 13610 +31250 + 16758 +6574 - 27056 +29851 + 23168 +(16125 - 27177 * 21383 * 2338) +8148 + 1931 +9401 + 18584 +(17236 + 30462 - 15794 + 11856) +31786 * 16421 +14271 - 28458 +7268 * 9830 +22568 - 17044 +28328 + 4421 +(14476 + 20128 - 26929 + 12794) +21978 - 30924 +20819 + 23244 +5174 + 16879 +(631 * 20731 + 6982 + 4330) +30994 - 12853 +480 / 9056 +14399 * 5600 +(20236 - 23480 - (939 * 28870 / 10446 + 6404)) +3180 / 8952 +6512 * 4948 +859 + 8123 +25197 * 24119 +(17006 - 1606 * ((21598 * 21858 - 1464 + 22247) + 20697 * 20135)) +6967 * 20542 +((31088 - 28020 * 12129 - 9398) * 320 - 24595) +(3357 - 8737 * ((((9558 - 6509 - 22491 * 25078) + 12917 + 18464) * 10869 + 22774) - (29019 - 3971 + 26308 - 11160))) +13041 - 14359 +(19360 + 28186 / 13422 - 9000) +9902 - 10889 +1850 + 22459 +13196 - 18371 +20565 - 17762 +20633 * 27033 +32589 + 3931 +2055 - 21878 +22543 * 67 +23235 + 6278 +26335 - 14115 +7079 + 28908 +14982 + 10854 +(29434 / 4885 - 30433 - 31846) +25388 / 6797 +((15794 + 22032 + 32059 / 24674) - 21004 - 4716) +20347 - 9841 +19980 + 699 +(26926 + 19750 - 27236 + 32740) +16644 - 12378 +(23939 + 29688 * (28725 * 32456 - 27567 - 25861)) +11481 + 10262 +((1068 + 14312 * 1295 * 12840) + (5842 * 31799 - 3317 * 12105)) +(28005 * 10443 + 16280 - 6764) +5610 * 7645 +15050 * 28142 +5111 * 9672 +19285 - 17910 +15031 * 14555 +(23837 + 11725 * (11888 * 9233 + 14710 - 27675)) +1823 + 20306 +2943 + 27734 +18874 / 17699 +(8998 * 27206 * (4526 * 16186 / 13620 * 4215)) +32551 * 4561 +14626 / 14275 +3591 * 5999 +(12639 - 28682 + 4709 + 27648) +10152 + 10052 +(((14967 * 23007 * 31878 * 3704) * (520 - 16910 * 17880 - 19191)) + 12883 * 28359) +14410 + 27131 +(18718 + 5935 - ((16793 / 16173 * 12709 * 10293) + 8656 - 1152)) +9033 + 7144 +9625 + 29952 +(19608 * 25135 - ((24686 * 20775 - 22487 + 20910) * (362 - 25593 + (28778 * 18019 - 27302 - 20187)))) +((14712 + 16419 + (10405 + 18076 + 31956 + 6342)) + (29532 * 14048 - 13911 - 18587)) +6002 - 8770 +32568 * 17444 +(31919 * 17487 * 20327 + 14521) +10180 - 31072 +2062 + 10968 +(26312 + 29276 + 11231 - 23195) +24587 * 29393 +10746 * 18347 +(28014 * 12227 * 32170 + 8077) +(24421 * 12026 - 6388 - 17007) +8521 - 8255 +(11605 * 8767 - (12898 - 23756 - (23598 + 20905 / 25459 - 21366))) +2054 - 31081 +12336 * 15831 +(24662 + 26558 - 24236 - 21011) +23214 + 9582 +25165 - 9054 +12488 + 8602 +10981 + 30030 +14626 / 25396 +6612 + 5079 +(11578 * 14906 * 27925 * 18075) +3820 + 28181 +5750 * 24904 +19993 * 25118 +(23409 + 16449 - 216 * 28890) +29580 + 6279 +21730 - 29688 +32476 + 31848 +6621 - 26652 +((19776 - 26844 - (11487 * 7289 - (18905 / 30071 + (22836 + 15836 - 26097 - 2898)))) - 13458 * 15255) +5757 * 6071 +28506 - 28948 +32142 + 12219 +((1766 + 21980 * 12305 / 23629) + 18068 + 11648) +26765 * 28874 +25887 + 5082 +25282 + 17325 +(24204 - 25145 * ((20679 + 28768 * (12483 - 2899 - 8834 * 9352)) - 23163 + 689)) +((8784 - 25236 * 7963 + 32455) * 27045 + 6865) +24645 - 4221 +28072 / 24766 +7195 / 14845 +(14746 + 8800 + (30867 - 18993 / 20821 * 43)) +4128 * 18921 +23310 - 1681 +8894 * 32214 +24164 - 19864 +25766 * 13943 +1991 * 1156 +21677 - 783 +(((29881 - 18297 * (8872 - 27487 + 14387 * 882)) + 28638 + 22162) + 17951 + 20414) +4147 + 8425 +(1288 * 26705 * 2747 + 11863) +28015 * 3314 +13069 + 1835 +(27044 - 21634 - 20356 - 23136) +10797 * 10547 +(25106 + 24860 * ((28561 - 4471 - 26206 * 3753) * 16559 - 19165)) +(32121 - 30428 * 27131 * 507) +23877 * 19430 +11579 / 10371 +2409 - 21069 +16772 - 18580 +13242 + 5168 +8860 * 12153 +26167 * 17469 +19494 / 11494 +(7055 - 24223 + 7690 + 31644) +20507 / 19662 +6676 * 12520 +30987 * 18228 +16427 * 6297 +10509 * 3626 +(31540 * 4843 * (785 - 12198 - (19393 / 24215 / 15872 - 31463))) +27108 + 13909 +18714 * 17855 +30502 / 26541 +14612 + 9392 +18269 + 20368 +3991 - 18143 +(23948 * 13328 - 27314 - 16019) +(21405 + 31989 + 1420 * 18106) +19557 - 1059 +6827 - 27377 +32146 + 22353 +6346 / 25247 +13336 + 30665 +8752 * 11669 +21222 * 23351 +15001 * 26592 +18466 - 2078 +(31600 - 26651 / 19868 * 11423) +25273 * 21807 +10792 * 16989 +785 + 22307 +7471 / 29123 +5988 - 18982 +(16956 + 24498 * ((20224 + 9034 - 28797 + 26937) * 16773 * 81)) +28885 * 19932 +11261 + 1342 +3963 + 8423 +(27270 + 26776 * (27624 + 18107 + 5115 * 5113)) +(3727 * 31319 / 19743 - 26953) +(885 - 12201 + 10346 - 15408) +13552 * 25814 +30169 - 8726 +23015 + 30613 +((9294 + 485 + (23158 * 11788 * 10646 - 6952)) - 23571 - 30297) +23641 * 14168 +19928 * 13100 +2260 / 27951 +28510 + 3326 +(7275 / 2717 / (12659 + 18620 + 8616 / 32026)) +31480 + 3310 +16914 + 12211 +12234 - 10442 +2721 - 9611 +28430 / 384 +((6723 + 12930 + 4468 * 19234) / 31647 * 30977) +(30183 / 5416 * 21560 * 3941) +29671 + 18767 +(23402 * 6802 + 16331 + 6838) +(23298 * 3693 - 16376 + 22235) +(7771 - 12341 + 9662 * 13256) +28195 + 16413 +((28386 + 20675 * 29544 + 16138) * 31651 - 24109) +(((5853 * 32317 - 924 + 25760) - (((11689 + 3560 - 12092 * 14013) + (14436 - 32144 * ((16222 * 25365 * 24173 - 23447) * 26584 - 13322))) - 28916 * 2308)) * 25176 / 30540) +19103 + 8340 +32600 * 20808 +((21884 + 20717 * 7302 * 15741) + 13230 - 27099) +(((23896 + 20773 - 27604 / 25677) - 12609 * 5026) + 17096 - 21776) +6301 / 19775 +7908 * 22285 +17207 - 22041 +27481 + 27544 +23947 - 23184 +28496 - 1691 +(28669 - 6338 - 30754 * 15934) +32224 - 1739 +4946 + 6843 +13174 - 19286 +28123 - 23559 +(4297 * 32601 - ((19208 / 18979 - 21657 + 19262) * 18655 - 3189)) +390 * 3568 +7962 * 15990 +18945 / 15935 +12326 - 26928 +328 * 21017 +18614 + 19625 +293 + 16406 +(10226 - 13647 + (22687 * 31551 * 22437 - 21291)) +(5568 * 21940 + (5758 + 1518 - (16957 + 16965 / 22499 * 20426))) +705 / 12794 +3161 * 31710 +25565 - 30830 +24609 * 22684 +18987 + 29249 +11927 + 9969 +8914 * 16915 +15265 + 11577 +14217 * 9240 +8913 - 18264 +(32364 + 29733 * 9770 - 26319) +7385 + 9385 +4271 / 17820 +8277 - 4223 +19392 - 12615 +22828 * 1945 +10200 - 13998 +(23416 + 8799 - 9441 + 19200) +(32431 * 3944 * (25164 * 4603 - (27925 * 20727 / 10249 - 12544))) +22507 - 25436 +27933 - 11150 +((6117 + 23038 - (15167 - 2211 + 11885 * 12149)) + 19605 + 913) +4206 * 7127 +9524 + 27185 +(17462 - 21942 * ((16683 - 32588 * 10835 - 22440) + ((28652 + 24839 * 18124 - 14079) - 17885 * 19420))) +11444 + 16246 +27995 * 27799 +9491 * 28998 +24391 / 15447 +(32630 * 13928 * 11473 * 10193) +13697 + 24981 +(26268 + 6629 + 2797 * 30556) +10349 + 12303 +((761 + 12016 - 18162 * 17023) * 26129 - 26811) +10798 * 10895 +29751 + 28867 +(24025 + 12668 + 23317 + 14866) +11892 - 18968 +(24820 - 28732 + 25168 - 26216) +29369 / 29624 +25623 + 7406 +27954 - 4004 +27740 + 32426 +(19807 * 20551 + 3890 - 30833) +(19325 - 21987 + ((20843 * 289 - 4384 + 30477) + 24901 * 8728)) +22720 - 11550 +2226 * 9897 +30199 + 25544 +31742 - 4830 +22868 - 13117 +10798 + 957 +6872 * 19404 +24188 - 29571 +(655 - 20917 * 30022 - 30116) +27463 - 13185 +26470 * 10572 +31327 + 460 +808 + 21513 +63 + 18662 +(9864 - 5055 - 22611 * 9983) +22338 - 3940 +(17354 - 23808 * (16180 + 20567 - 2100 * 27644)) +10507 * 22745 +29498 * 10103 +16518 / 1412 +(((32655 * 2911 - 20887 - 5147) + 30305 - 17171) - (28885 + 23566 * 16731 + 15852)) +4707 - 13208 +11985 - 3163 +((23858 - 24507 * 998 - 7483) - 12154 + 24684) +28644 / 20932 +4290 - 29005 +29462 / 6661 +16082 - 5344 +7542 + 32185 +26737 - 20574 +18134 - 3164 +(25619 - 29724 + (32614 + 32372 + (126 + 20983 - 24828 + 31041))) +8964 - 16663 +24064 * 26695 +18343 * 13130 +1478 * 27246 +15399 * 1763 +8240 - 20527 +23294 - 13712 +11310 + 30023 +21031 * 6332 +(21904 * 8191 + 25087 - 8250) +(23623 * 31611 * 2123 + 5702) +16875 + 7913 +6652 - 22991 +22537 + 27511 +20312 + 6148 +29960 * 20456 +31690 * 8986 +1518 * 3644 +27551 * 909 +7682 * 13438 +13635 + 29769 +(24921 - 11310 + 13003 * 2511) +19435 + 9482 +(1515 + 5641 - ((26413 + 20206 + 1639 + 5418) - 10444 * 12932)) +24621 / 14218 +26672 * 14156 +26864 - 29819 +27882 + 12185 +4966 + 23527 +(15056 + 10515 - 31620 - 7783) +26519 * 4821 +9371 * 14491 +(2164 / 15315 + 5062 + 4695) +19185 / 28529 +28685 + 16636 +24511 + 23929 +(19287 + 7555 * 26860 / 11778) +8815 + 23953 +25175 + 31357 +(31052 + 6436 - 9704 + 11453) +24808 - 24091 +23579 - 21817 +32267 * 24224 +107 + 31378 +14589 - 14454 +(15780 * 26885 + 29875 / 9564) +14190 - 31765 +19777 - 31103 +2019 + 22463 +22571 - 7507 +28739 - 21221 +4570 / 9926 +4919 + 16850 +(6852 * 32091 - ((9632 - 28810 * 22008 + 1354) / 25399 + 10359)) +(22934 - 25904 * 20589 * 1065) +19445 * 13427 +(14936 - 26521 - 31278 - 25423) +13245 * 2376 +(11621 + 27654 * (5643 * 3459 - 4671 - 20409)) +(((18544 + 6394 - (19127 * 7564 - 6448 - 7475)) + ((27871 / 24822 * 19963 - 10302) - (25150 + 26510 - 12118 * 32228))) * 4671 / 26291) +28450 - 28269 +12385 + 13247 +27163 + 7665 +5999 * 9396 +5619 - 29088 +12943 + 4966 +30048 * 15925 +(16197 - 7670 + 16175 - 15174) +6031 + 28579 +(25098 + 18312 * 30312 - 20148) +(16201 * 16312 - 23432 / 29710) +14977 * 21432 +19793 - 4637 +(30932 * 15778 - 21018 - 30290) +19993 / 2740 +25258 - 18842 +27957 - 23481 +515 + 32415 +12420 + 25511 +24596 * 12057 +10146 - 23928 +21437 + 20358 +23974 - 14613 +24755 - 18799 +10131 / 20204 +10273 + 6201 +(24237 * 17167 - 14044 * 15893) +28639 - 21159 +19379 - 4768 +27265 - 19118 +11888 - 22740 +6735 + 7690 +6735 / 29890 +24297 + 13178 +8218 + 17419 +17265 - 17066 +12222 + 10869 +22491 - 7745 +8965 - 21923 +((3768 + 9791 / 7051 + 30006) * 6943 * 3066) +20798 - 32624 +27934 * 31010 +1856 + 25480 +17167 + 801 +32655 * 11059 +28601 + 9110 +20884 + 8476 +32021 * 21143 +5833 * 7543 +18896 + 18610 +(16595 + 29689 - 19513 - 19746) +14619 - 32489 +25820 * 10385 +(1748 - 5968 * 1378 - 25672) +(31177 - 29971 + 26306 + 3529) +28051 - 19443 +31256 / 8462 +(30310 / 508 - 19098 - 2579) +8247 + 31482 +13198 + 27077 +18440 * 5862 +6395 - 29480 +10787 * 28651 +31268 * 2826 +19887 + 5374 +21920 / 17442 +2355 + 1935 +28791 * 18044 +6461 * 20623 +11093 / 18405 +(3206 * 22965 - (((31084 - 5626 * 26203 - 9826) + 31013 * 26107) - 20516 * 2697)) +26272 + 13529 +16980 + 17687 +7382 * 3791 +26628 + 9239 +(((11159 - 31373 + (29300 * 21415 * 18896 * 22903)) + 19844 - 18513) - 21405 * 29601) +7581 + 1644 +(29501 * 24855 + 703 * 1397) +18586 - 7619 +(20301 + 9492 - 7915 / 2168) +((20968 + 610 + 14526 / 2495) - 22903 * 262) +29395 + 12136 +16531 - 919 +((27810 + 25178 - 21956 - 24237) + (((12098 - 2416 * (((30224 / 6596 - 28178 - 3264) - (21928 - 15947 - (7615 + 12354 + (18380 - 18071 + 8166 * 29251)))) + 28619 - 10021)) * 7607 + 18388) - 11228 + 16041)) +(9168 + 3709 + 25682 + 9524) +26252 + 10957 +(13617 * 615 - (2922 / 19664 * 18571 + 7155)) +2186 + 8479 +9230 - 31500 +13114 + 1348 +13318 * 17626 +2100 - 23077 +(26543 * 18225 * ((16795 * 6132 + 8185 + 2) + (4494 * 2984 * (21447 * 26174 * ((7247 / 3073 + 3521 + 22861) - 30315 * 26721))))) +8028 + 21227 +(11820 - 1439 + (4166 + 1071 + 10058 / 1286)) +6518 - 23026 +(24359 + 26525 - 15841 * 17915) +(15412 - 14106 + (26139 + 4347 / 27213 - 25462)) +(21551 - 11040 + 25021 - 7611) +9104 - 2729 +29163 - 31407 +15257 - 9799 +16153 - 10085 +6504 - 4706 +21839 - 30449 +((15795 * 20962 - (((24465 * 9012 * 31354 - 13760) / 25978 + 143) * (23067 * 31533 * 28419 * 18761))) * 19155 * 3922) +972 + 23820 +4998 + 29989 +((5040 + 26438 - (6984 + 20719 + 6768 * 14004)) - 26062 * 1754) +10654 * 6214 +22396 - 17243 +2304 - 31995 +5217 * 4693 +17745 - 7939 +32384 + 16755 +((30493 + 13885 / 68 * 241) - 30210 + 26927) +31968 * 23352 +17974 / 8585 +15820 * 11938 +23217 + 10883 +31262 - 10830 +18997 + 23490 +8762 + 25804 +22091 - 3216 +(19354 - 21030 * (6276 + 24149 - 24703 * 7512)) +11749 - 5911 +29129 + 9920 +5562 * 26205 +21839 + 20498 +14091 * 19876 +(18307 - 24919 - 4872 - 27496) +25345 + 31132 +6450 - 22678 +((2298 - 17453 * 32115 + 29005) * ((32453 / 30316 / 29338 * 11458) / 8924 / 6568)) +24163 - 23458 +(6803 - 15046 + ((1251 * 29670 + ((12004 - 24329 * 30149 - 27477) - 5203 / 6827)) * 29050 / 29612)) +30814 - 22804 +15997 + 20921 +((10215 * 12173 * 12683 + 18053) * 15153 - 21925) +(19849 + 16657 / 4107 * 23506) +9464 - 27959 +8769 * 9721 +29530 * 30592 +7058 * 2774 +(21732 + 16882 + 31848 - 3664) +(9426 + 28780 + ((30901 - 31496 * (((24089 * 13940 * (30808 / 26114 + ((22764 - 5632 - (16587 + 16305 * 14110 * 8342)) * 12261 * 29741))) + 8281 / 25688) * 11141 + 855)) - (((20633 / 8420 - 12806 + 18086) + 13095 - 6832) + 9606 - 8020))) +8537 * 14963 +5925 + 11942 +30456 - 15458 +10066 + 290 +14291 + 7713 +(12784 / 25755 * 26230 * 20698) +((((27971 * 6038 - 10275 * 8360) + 10648 * 22275) - 32260 * 30447) - 4384 * 32736) +(8284 + 21231 * 1579 + 2234) +22832 / 30765 +15528 + 1842 +7518 - 5787 +((18723 * 14778 * 27129 + 18490) / 1770 * 4874) +24589 - 9716 +16398 - 17591 +(3753 - 18602 * 20616 / 6715) +29522 + 9382 +540 + 7491 +((18380 + 9790 - (5587 + 21619 - ((964 * 13608 + 31783 - 12102) + (1263 - 1393 + (26764 * 16721 * 31213 * 12948))))) * 1510 * 16016) +9151 * 6424 +((7401 + 1627 / 2100 * 28590) - 27609 * 7522) +24143 / 22321 +(1292 * 17264 - ((1436 - 27340 + 27890 + 25540) * 21043 / 3976)) +16410 / 26029 +22719 - 11234 +5889 + 32635 +28227 / 32071 +17413 + 7432 +14419 / 22928 +28452 - 29123 +7897 + 24605 +4713 - 3366 +((21350 + 7796 - 7143 - 13520) + 6975 - 30302) +(10902 / 8767 + (10369 - 349 + 2639 - 30417)) +5201 * 17167 +2474 * 7251 +23119 + 14322 +20311 - 23481 +18212 + 20575 +6358 * 11825 +7237 + 217 +9876 + 16842 +8074 + 11925 +(7169 + 20134 * 27313 - 23356) +12595 / 1231 +(1846 - 13856 * 5123 - 26734) +20468 * 17144 +15158 + 11116 +11190 * 18019 +23812 * 26069 +22480 - 23740 +19123 * 23945 +((27204 - 14753 / 20045 + 4518) + 14401 + 21751) +18980 + 22251 +23235 / 28146 +(17745 * 245 + 3154 * 24749) +15018 - 16473 +22086 / 32071 +((2526 - 32472 * 415 - 8877) - 5088 - 5117) +24025 * 22475 +23531 / 13172 +(20410 * 30201 + (25093 + 28833 * ((11953 - 22911 * 29925 + 10440) + 30247 * 28616))) +23853 - 687 +14463 + 3290 +79 - 8596 +21301 + 1214 +21162 * 5568 +(7990 - 32488 + 29957 - 4716) +31919 + 27552 +14644 * 1766 +27248 + 30090 +(((1848 - 12538 - 20359 / 1407) * (15836 + 20373 * 18518 - 29873)) + 19759 * 23962) +32306 * 4293 +2344 - 9269 +31221 * 19159 +5003 / 16840 +38 + 24364 +(542 + 19116 - 28807 - 258) +15672 * 17467 +12628 * 21320 +4518 * 28431 +19538 - 22359 +3784 / 2226 +11606 - 20830 +14928 + 10109 +29085 - 8903 +((30803 - 7055 / 4977 * 13158) + ((5518 * 4299 * (7767 * 13071 * 20274 * 25693)) - 3987 - 18239)) +6213 + 2379 +(9852 - 12821 - 29639 / 10690) +(30953 / 22846 * 16576 - 28069) +2652 * 26736 +239 + 10386 +((31352 * 19308 + 5679 + 26519) * 31922 + 29473) +5874 * 4723 +30136 + 27520 +11833 + 22533 +5876 + 21221 +(32058 - 5412 * (22691 + 26573 * 25499 * 5883)) +8245 * 1431 +11353 + 6432 +(3856 * 25094 + (16790 + 1647 / 7269 - 1358)) +(22056 - 3670 - 26952 * 6587) +5616 * 22849 +(5669 + 30135 + (30726 * 18125 + (13090 * 18604 + 30614 - 4063))) +10942 * 10103 +(1089 * 31795 * 49 + 23897) +3652 - 22799 +8343 - 19708 +30288 - 3808 +27851 + 25969 +4705 + 17639 +((24780 * 28860 - (14070 / 4028 + (11529 - 20404 / 5319 + 31155))) + 3890 - 15269) +(7814 * 25644 * 12593 - 5035) +13462 * 22510 +15746 - 14642 +((27375 * 15191 + 14957 - 29344) - (22670 + 32634 * 18527 - 25824)) +((27561 + 9980 * 5868 / 27231) * 27258 * 31266) +20452 * 888 +((16575 + 14690 * (424 * 8751 - 28240 - 31053)) - ((27018 - 26416 + 26967 + 22302) - 8319 + 12847)) +20820 - 29391 +10394 + 30269 +1178 - 11182 +12704 + 18285 +1372 - 27897 +(6776 - 31398 * 8953 - 22031) +16861 + 23032 +6994 + 16361 +25632 * 28591 +(2200 * 2722 / 22052 * 6759) +31650 + 12190 +29558 - 15684 +17883 * 21524 +31778 + 31831 +((15743 - 1966 * 19651 * 4390) + 3480 + 21607) +(29524 + 18067 - 23425 * 29141) +17000 / 3279 +31691 + 2905 +(17474 + 27821 * 8503 - 4976) +24778 * 6462 +(3192 / 19193 - (12847 + 27854 + 25988 + 23810)) +7908 * 20073 +(22686 * 1749 + 11781 * 24374) +28711 - 25100 +21025 + 21029 +(12256 - 9756 / 19242 / 16279) +29196 + 10562 +8058 * 3271 +15766 - 28959 +20851 * 18324 +10334 * 3509 +((12711 - 24298 + 32097 + 4384) * 25228 * 14530) +27655 - 728 +9404 / 17516 +29010 * 10687 +18233 * 13263 +(17547 + 183 * 8773 - 20975) +(((6129 * 4291 - (13890 + 19303 - ((1695 / 4711 * (4626 - 12815 - (10151 - 25584 * 28424 + 7619))) * 24027 * 13032))) * (25762 + 24543 + 20290 - 14454)) - (3096 * 31483 - (14503 * 13545 - 28158 + 2325))) +(30894 + 26070 * 14482 + 30209) +((32713 + 31419 - 13066 * 16110) * 28692 * 31280) +26573 + 1497 +9870 - 19655 +12402 - 4070 +16417 + 11245 +(2563 * 15228 - 6187 - 3935) +13030 - 27510 +18029 - 2721 +7358 * 10223 +30734 + 25122 +(15121 - 14817 * 27690 * 2755) +(425 * 6546 + 28969 * 3204) +10158 + 28402 +(5269 + 4799 * 28625 * 12364) +12274 / 15673 +32118 + 17820 +1157 - 4312 +15108 + 18351 +24654 * 12969 +20393 / 17919 +((3242 + 31877 * 1204 * 14157) / 689 + 14049) +8526 + 16962 +8865 * 26925 +6481 * 21329 +(16345 * 4300 + 26989 - 5389) +(4227 - 24975 + 27673 + 27048) +8731 / 1569 +(29581 * 7185 + 4967 - 14183) +(19035 * 11376 * 25650 - 27362) +26120 * 17590 +23190 * 8288 +6748 + 25476 +17462 + 4083 +5419 * 28754 +5104 - 22859 +20827 - 24720 +24532 * 26851 +18619 - 12700 +(27893 + 20838 + 9461 * 24285) +((15315 * 31327 + 7911 * 9527) + 8187 - 11449) +7083 - 10502 +10681 + 8935 +8280 * 3808 +((((16863 + 27735 / 30171 + 4506) + 17301 + 18242) / 29417 * 7435) * 30043 - 23694) +6684 * 4792 +23868 - 10632 +25770 - 6978 +(1405 / 6378 - 29667 + 18989) +6284 + 24374 +(29812 + 16554 * (30814 - 19206 - 4743 / 18332)) +((((19354 * 11505 * (8577 + 14816 + (7143 - 6584 + 24063 / 10752))) + 6263 - 6540) + 4887 + 20684) * 21568 - 12941) +((16794 * 32201 - 23475 * 25616) - 10617 * 13693) +21355 * 29425 +((9435 + 519 + 17341 - 6446) - 25339 - 1253) +(29157 / 6861 * (7275 * 24372 - 12773 - 23409)) +13856 + 2894 +830 + 5144 +24065 * 30393 +11143 - 24884 +(7321 * 24646 * (15850 + 27001 + 16214 * 23574)) +19144 + 7204 +(((1107 + 16653 - 13569 / 19925) / 29842 - 2044) - 14547 - 22209) +1768 + 1576 +31679 - 21292 +25161 + 17997 +28815 - 7219 +12547 - 5600 +11072 / 8531 +22468 * 20852 +13055 * 4735 +6012 * 5283 +(4168 - 26647 - 14664 * 2174) +32676 * 6368 +7730 - 29621 +32419 * 4476 +(22659 + 2280 * (23878 * 17958 - 1541 / 12864)) +32182 + 7797 +(8554 * 17444 * 30129 + 14787) +3595 * 19786 +(21871 * 31258 - (((19818 + 1769 + ((32596 + 5301 - 12162 + 26741) + (26644 - 10670 + 11187 - 4182))) * (16901 / 27112 - 30219 + 31777)) * 16899 - 30321)) +27490 + 10657 +8230 * 11110 +16291 - 9964 +3948 + 1447 +13157 - 24629 +8371 - 26642 +4663 * 16733 +30925 - 6403 +14355 + 8715 +23277 * 18534 +30930 + 4679 +5437 - 20848 +(2641 + 6541 * 18269 - 26975) +6082 + 2076 +10304 - 1728 +19541 + 234 +20584 * 28930 +(12747 * 1025 * 14052 * 7530) +10808 - 20765 +(23410 + 31278 * (6151 + 23959 * 26040 / 789)) +839 - 10529 +((22738 * 15483 + 3508 * 28459) * 21130 * 25284) +15242 * 192 +1439 - 347 +31508 + 11602 +6879 - 661 +29217 + 17476 +15599 / 22069 +711 + 20516 +5697 * 17888 +(1675 * 32286 * 22080 + 32115) +11484 - 16744 +31856 + 28604 +(12205 - 21746 / 5894 + 12540) +32042 / 20295 +26609 - 16321 +(((18162 - 838 - 15882 - 10551) - 15012 - 20053) + 25598 * 11037) +21720 + 23580 +11713 / 23722 +(31464 * 25786 * 14210 - 18085) +26047 * 4258 +20190 / 6834 +17447 + 20966 +((11030 * 23391 * 3533 + 14540) * (25669 - 15489 * (22516 + 4743 * 28166 - 25024))) +23963 * 30135 +10612 * 31449 +6150 + 32057 +2914 / 25547 +27478 - 25424 +(19169 + 25028 - 32260 + 270) +745 * 27333 +24678 + 10346 +((12682 * 16387 - 11870 * 3608) + ((27880 * 12637 + 11400 + 26869) / (1887 + 24083 + 4466 * 20953))) +27235 * 13145 +14200 + 8077 +15033 + 6194 +19754 + 14600 +(7181 * 7854 - 5936 + 16306) +22402 - 14827 +(((3927 + 11590 - 8137 * 5018) - 19796 + 17038) * 26249 - 19127) +9236 * 30564 +8962 - 17842 +(25184 * 3907 - (754 * 26736 * 10160 * 1948)) +2692 * 18452 +16458 * 8953 +937 - 4724 +(8933 + 22455 - (21119 / 30569 * 14486 + 9655)) +28206 - 3124 +30319 - 23749 +21544 + 10077 +26011 * 31310 +(32481 * 3653 - (20669 + 21608 * (15788 - 31679 - 23095 * 25719))) +16137 + 31142 +(24534 + 25564 + 4348 - 11399) +27733 - 20666 +((17706 - 8462 - 2154 / 773) / (14023 + 3839 / 23599 + 29914)) +(((32068 * 6530 * (10662 - 4929 + 23901 - 29789)) + 26896 + 13938) * 14460 * 195) +(25692 * 6920 - 11854 * 74) +31288 - 20679 +((10928 * 19837 - 10673 - 9599) + 7006 - 16228) +32217 - 23538 +(((16672 * 13580 * 21059 - 25524) - 5523 - 18872) - (28461 * 1855 * 16321 + 2295)) +804 + 16976 +(11668 - 5124 * 15554 * 13194) +13103 - 7809 +(13290 + 31988 + 31577 * 22103) +((15831 + 22345 + 6933 + 264) - (28584 / 320 * 18365 + 23013)) +3821 + 26895 +69 + 15359 +(21114 + 27118 - 28291 - 19130) +10556 / 1524 +21500 - 26037 +30375 + 2844 +7575 - 9319 +31947 - 28300 +28103 + 5649 +31592 + 32699 +30972 - 6013 +11461 * 8427 +1932 - 31703 +4863 / 19425 +601 * 18041 +5246 * 30397 +(31426 * 31448 + 15311 / 10477) +(8183 * 30544 - (19875 * 23180 + 10710 - 9147)) +8834 + 28555 +7948 + 24576 +3358 + 23487 +12404 * 22610 +(((8825 + 13388 + 395 - 25798) + 11711 + 25660) - (1775 - 6143 * 21836 * 14981)) +428 * 26495 +17347 + 25017 +27512 / 11050 +9191 - 22694 +5614 / 27267 +(25029 * 18103 * 20467 - 27145) +(20440 * 32001 * (16935 * 14784 / (16052 * 30626 / 16525 + 10812))) +26752 + 11644 +1889 - 14943 +22591 * 18951 +22058 - 16661 +(24577 + 29923 * 3029 * 6622) +((17972 + 27470 * 2875 - 460) + 14535 - 15853) +356 - 18890 +(21158 + 25035 - ((2215 * 27435 * 7443 / 10246) - ((3987 - 21694 / 25645 + 30589) + 15151 * 10960))) +99 / 6719 +15351 + 4431 +29735 + 22625 +32675 + 22515 +8679 + 7777 +2730 * 17775 +16887 - 19104 +11387 * 2864 +10043 - 12198 +8068 - 27922 +(10136 + 4720 - (16086 * 909 + 28298 / 30179)) +15917 * 21240 +(10455 + 29089 - 19516 + 31669) +(16572 * 28565 + (((23073 + 21611 / (18502 + 20952 - 23532 + 28063)) + 32680 * 32344) * 10505 - 772)) +21105 + 3800 +22629 * 19659 +19293 - 13626 +30487 - 5626 +20661 + 13378 +(28158 - 24942 * 29570 - 31643) +1814 - 8 +16593 / 20086 +11469 - 9571 +3246 + 14844 +18732 - 12718 +14383 + 24873 +25754 / 5261 +10297 + 22617 +(24591 + 3931 + 19366 - 7874) +30996 * 20215 +(15347 - 32110 + 12569 + 21327) +18445 * 23727 +4958 * 10158 +18607 * 25928 +25366 / 10028 +18269 * 8323 +18747 + 19518 +1606 + 6505 +4279 + 14173 +13013 * 7654 +27080 - 21411 +(19886 - 14460 - 23393 * 5545) +(19236 + 25874 - 21928 * 2632) +19087 * 5073 +(14132 * 1049 * 18234 - 15449) +(31884 * 24377 * 6460 * 19350) +2954 - 21515 +(6858 + 24098 - (13405 - 8017 * 14968 + 9772)) +(2911 + 23514 - 9042 - 24136) +3982 + 10932 +14268 + 31855 +24033 * 11846 +(16499 * 11847 * ((5539 * 16480 - 26779 - 15661) - 8366 * 2789)) +31816 * 6503 +4676 - 8147 +143 * 24806 +20735 - 17906 +16786 + 375 +15878 - 12417 +14242 + 32685 +(24547 * 29167 + 2194 + 17474) +27875 * 21436 +((((162 * 1960 * (455 + 11746 - 2214 * 13593)) / (17487 * 1493 * 18390 - 4855)) * 12097 - 16900) * (23798 + 510 * 14787 - 25430)) +12604 / 16307 +(8624 + 24016 - (13854 - 24287 + 27829 - 14227)) +24269 / 32514 +2557 - 31111 +27678 - 6083 +11717 + 18887 +15965 + 8867 +31376 * 8796 +27743 * 23458 +(1015 - 30300 * (4306 - 2577 - 8937 + 8741)) +1125 - 26712 +1174 * 22081 +9242 * 17920 +16388 * 31680 +21784 - 21136 +9957 - 15382 +3593 * 14041 +12678 - 18873 +16505 - 10024 +5698 + 18535 +20700 * 15478 +920 + 22790 +14420 * 22237 +12107 + 11403 +21430 + 18800 +9325 * 26309 +28183 - 9752 +2190 - 23382 +19523 + 30851 +(1866 * 30951 * 22303 - 22382) +4247 - 11078 +(1232 + 18515 * 14479 - 8299) +22211 - 8316 +(32739 - 22947 * 10005 * 22745) +11737 * 28653 +28447 + 5023 +26872 + 2941 +(2557 * 4812 * (1770 + 19933 + 12293 + 29681)) +18638 * 19195 +5778 + 26716 +22230 + 11734 +16598 * 20108 +30286 + 5282 +(9611 * 513 * ((6740 + 8634 * (1160 + 20406 - (16563 - 4527 - ((22580 - 22453 + 21106 + 14703) + (12785 + 19763 + (12076 / 20018 + (30199 + 27597 + 20704 * 13503))))))) * 1775 - 25395)) +(27529 * 8457 * 28225 / 15827) +7312 - 28790 +6769 + 19131 +25419 + 13371 +549 * 20627 +(26644 * 17126 - 15593 + 32131) +15990 * 22498 +684 + 16460 +21995 * 6991 +(371 / 27120 - 26878 + 28581) +(13326 + 413 + 1267 - 4944) +(21246 + 357 - ((4103 * 25541 * 25203 + 21251) + 27004 - 4146)) +11728 * 17214 +319 / 23998 +23070 * 31579 +(19019 * 24801 * 2500 - 11740) +26366 - 3790 +12660 - 1130 +((12949 + 11645 + (28767 - 1231 * 24617 - 21006)) - 32293 / 21386) +9065 - 9413 +1096 / 22857 +14056 * 4700 +9295 - 20557 +26142 + 31003 +15717 - 20870 +20968 + 13570 +17599 + 429 +15369 * 26088 +5073 * 19965 +1404 - 25746 +24539 * 6430 +13613 * 32756 +(24833 + 5346 - 32426 + 3856) +26123 + 23416 +(18947 - 5855 + 29256 - 599) +20479 - 18081 +4522 + 8800 +25809 + 2455 +16632 - 30619 +7086 + 2919 +2278 - 32214 +(13405 * 12703 + 26928 - 26140) +(27791 + 14772 + 1559 + 19830) +4848 * 23253 +1410 / 30666 +17527 * 26253 +30564 + 15118 +(8626 + 26518 - (18621 - 10223 * (12282 + 2580 / 23848 + 6328))) +451 - 32620 +30144 - 9321 +31899 / 26329 +(3148 * 19923 + 21332 - 3348) +4349 - 28003 +4115 - 5918 +31332 + 25321 +(3614 + 19108 + 28342 * 7012) +3320 * 17351 +1600 / 27797 +3626 / 26898 +17434 - 16161 +26913 * 8768 +(13246 + 23579 + (14320 / 7835 + 12803 + 14534)) +1921 + 27693 +((11980 + 18504 - ((12170 - 6015 + 546 + 23630) + 8277 + 15787)) + 537 * 16176) +15577 * 19102 +9521 - 24035 +10448 - 11871 +15551 * 18719 +18830 + 10365 +31958 * 24568 +1953 * 4579 +15845 + 126 +(12185 * 17065 + 1148 / 1353) +10363 - 15098 +19806 * 20355 +18118 + 10129 +24610 * 13515 +585 / 22975 +24678 + 14399 +2676 - 11766 +17590 * 25847 +16552 + 23988 +1489 + 17882 +((32331 + 8096 - 23529 + 17376) - 4941 - 18657) +(23936 - 29849 - 25876 - 14261) +(23682 / 19848 * 21009 + 27390) +(16312 + 22647 * 2837 / 10853) +(31554 - 15017 + 28408 + 26487) +5633 - 23968 +8697 * 5156 +29884 - 21709 +6306 / 21734 +9842 / 5311 +(3504 * 28257 - 24467 * 20984) +5189 + 17326 +14650 * 11841 +16049 - 27470 +17670 / 27730 +22293 * 5440 +12949 / 24589 +5928 + 11145 +25882 * 17551 +22155 + 13029 +(26106 + 3886 - (964 + 26010 + 13640 + 20566)) +479 * 4581 +9170 * 13270 +6998 + 25590 +12725 + 15856 +28197 / 25657 +20003 + 8546 +(10525 + 13975 * 8750 * 1259) +32762 * 10973 +29543 * 27443 +30557 - 18099 +31613 - 6479 +8671 * 14413 +21660 - 18620 +(10741 * 32753 + 12407 * 15271) +1808 * 4944 +((((17815 * 5424 + 6339 * 17561) + (23648 * 27030 - 23994 + 7522)) * (19640 * 29602 * 19338 + 28110)) / (13639 * 15310 + (((10044 - 26598 * 31429 - 12702) / (2905 + 14404 + (32010 - 15700 * ((1434 - 4330 - 25490 + 30941) * 25784 + 31521)))) + 15002 * 18612))) +845 + 4511 +8418 + 7190 +(1462 + 18119 * ((27495 * 8053 * 18619 - 19702) - 30816 * 30512)) +15425 * 11069 +14672 + 9297 +18694 * 15572 +(27574 + 23244 + 12920 - 27463) +((7821 + 14450 + 1966 * 1702) - 9051 * 12134) +6466 * 32471 +14955 / 20482 +4403 + 5734 +19572 + 12739 +(7234 + 753 + ((5211 * 17650 - 26103 / 23620) + 16947 + 26584)) +11218 * 26778 +28718 + 24611 +32072 + 25471 +7321 + 24895 +31151 * 5230 +9728 + 32705 +(27060 - 22095 * 25833 / 18513) +72 * 18398 +(22612 + 31474 / 10890 - 2778) +3960 - 23054 +15532 * 27020 +(28459 * 19811 * 1875 - 4724) +28622 * 26161 +22610 - 28122 +4721 * 13650 +(1611 * 8912 + 2554 + 7450) +(29367 * 13573 / 18312 * 10214) +7226 / 6604 +31594 / 17842 +31654 * 5871 +23098 + 6783 +(6511 - 26998 - 11358 - 26368) +25266 - 29476 +(4246 - 32407 + (3191 - 6130 * 15358 - 18945)) +(21562 * 32350 + 14385 - 10469) +23614 - 8858 +21863 + 19633 +1960 - 21762 +24551 + 6281 +(3319 * 9323 * 29906 + 8295) +28387 * 17494 +7447 * 9018 +24071 / 31548 +30002 - 14179 +27682 + 12359 +(13250 / 17077 * 3154 + 9841) +((21800 - 15814 * 2308 + 2567) - 29029 * 9685) +9649 - 5411 +12794 * 26783 +5063 * 4992 +9997 - 15846 +(20168 - 19135 - (30506 - 1557 * 16338 / 7436)) +23081 / 31752 +18710 * 19972 +1943 * 6622 +(27706 + 32093 / 25191 * 860) +(7501 + 16437 + 22782 + 9783) +21957 + 4235 +8155 * 4230 +14532 + 6873 +29128 * 508 +23594 - 16833 +19143 * 25952 +22326 * 5410 +(21390 + 28590 + 15463 + 1980) +(22148 * 19580 + 16470 + 5472) +16367 + 32587 +30825 * 31518 +4653 * 15404 +1665 + 18884 +((7553 - 25945 * 24794 * 9560) - 10867 + 19033) +8124 + 4694 +5410 - 15231 +13256 - 18270 +28816 * 16836 +((2604 - 8525 / 15660 * 14706) - 24548 + 2765) +(16023 * 32152 - (13435 * 16442 - 22803 * 18221)) +15681 - 17451 +((26056 * 25464 * 25966 - 11355) + 23806 * 29907) +258 * 3058 +(12762 * 15721 + 7662 / 16046) +19310 - 9578 +28894 - 7966 +10666 - 28212 +29825 - 12204 +30977 * 25481 +32554 * 31556 +(12826 * 19398 * 18365 + 31910) +(12284 * 14786 - (14982 * 11893 * 21642 + 12870)) +9299 * 27339 +(13420 - 29005 * 19490 - 9303) +(4644 * 31793 * 6413 - 17907) +14670 * 24136 +((29727 + 7901 + 28016 * 10083) - 25172 + 12790) +28164 * 21916 +3799 + 11537 +11087 / 7551 +820 + 22406 +3270 * 19436 +11911 - 7793 +5904 * 11688 +((14029 - 4408 - ((23663 + 28600 - 2910 * 1946) + (9511 / 20360 * (17883 + 16836 + ((25164 * 20533 * 11515 * 12910) + 15285 * 16445))))) - 32722 * 30270) +8877 * 21833 +5423 * 12930 +1482 + 316 +14638 - 25053 +((32164 - 20176 * 28846 - 9521) * 28731 * 19495) +18662 - 32332 +310 + 28200 +28860 - 20560 +785 - 16302 +4399 - 23367 +15782 - 2437 +14490 + 19959 +8733 - 5414 +27085 * 2534 +26896 * 4153 +1013 - 7165 +31986 + 4232 +2202 - 14670 +(29781 * 18772 + 24657 * 30945) +8137 - 30237 +((19328 * 24350 + 2453 + 32731) - ((11773 + 19892 * 21520 * 26241) * (13235 + 15667 * 10644 * 29715))) +32291 + 28149 +(22255 + 30373 * (11324 - 7055 * ((11144 * 17175 * 570 + 28744) + 23891 / 25957))) +(5892 / 29391 * 10007 + 18322) +25905 * 19878 +979 - 5540 +5606 / 25415 +(13598 - 32666 - ((31755 - 18511 * 18780 * 29550) * (6800 / 14787 + (26226 + 18452 - 25383 - 22384)))) +2 + 10050 +28382 + 14858 +(22103 + 17967 * 21049 * 20343) +(29311 * 13001 - 13755 + 18428) +2379 + 20706 +(8088 - 14834 + 15234 / 31154) +27828 - 14796 +2673 + 28663 +(14098 * 32534 - 12483 + 5543) +6980 / 30696 +32277 * 2507 +(5886 / 27069 * ((6104 + 4595 * (16477 - 31544 + 23102 + 13633)) - 2245 * 9567)) +3121 * 22968 +(8601 + 11039 - 16101 + 20338) +11422 * 11466 +10952 + 23546 +28261 + 22602 +24025 - 13804 +(1641 - 7995 * 6614 * 27925) +(5184 * 26375 - 30261 - 21217) +29840 - 26742 +(28356 * 26308 + 21674 / 12970) +30449 + 22475 +15529 / 679 +(20718 * 9374 + 18567 - 14614) +3064 * 32255 +4343 - 17578 +21173 - 17992 +13887 / 6013 +23499 / 2575 +23061 * 13099 +(28913 - 12063 + 26862 + 21110) +10608 * 28195 +((12729 + 6616 + 12609 + 31069) - 11341 + 8060) +((((28104 + 6980 + 31214 * 11857) - 12713 * 19180) - 23607 / 16807) * (31597 * 23370 + (24784 - 12348 - 29338 * 11458))) +25122 - 9327 +6951 + 12438 +29818 - 24337 +29893 - 25105 +23875 / 18326 +25649 - 22515 +30430 * 24701 +32657 - 25552 +26901 * 27453 +20349 + 10682 +27060 - 27204 +3129 / 28953 +(30007 + 11214 - 184 - 3526) +(7395 - 9941 + 1341 + 22474) +828 + 29184 +23465 - 11052 +30308 * 11970 +1008 * 25179 +21962 + 13697 +782 + 5523 +12089 * 31086 +(16794 + 13093 / (27137 + 17953 + (8775 - 27587 / 6336 - 27446))) +8475 + 29002 +(32674 + 216 - 30863 * 27533) +((26880 + 9354 * ((26035 + 15267 - 18886 * 3439) - ((21083 - 1739 + 3622 - 23119) * (32451 + 28553 - (21738 + 23123 * 6079 - 1244))))) - ((((32746 / 29220 * 9970 * 11759) * 27029 + 28388) * 21810 * 20514) / 24669 - 1040)) +11870 * 26217 +13334 - 20701 +((6893 - 30978 - (19386 - 31918 * 9900 / 18262)) - 25315 + 2156) +13176 + 25481 +27387 * 15235 +28557 - 28717 +13415 * 6249 +20053 - 24866 +30481 * 25883 +(14379 - 24746 + 16326 * 18279) +27274 + 11153 +12988 - 21108 +6609 - 32429 +23957 - 20458 +(30574 - 20708 + ((31524 - 9161 * 10447 * 18984) - 11878 / 5905)) +(18839 + 29833 - ((13443 + 30922 / 19358 * 17874) - (13650 / 32237 * 2812 * 23850))) +(14296 - 27148 * 26926 / 14955) +24124 * 29251 +20744 * 21237 +9919 + 3056 +3756 + 21734 +28017 * 10961 +338 - 12491 +4933 - 22706 +24431 - 5937 +12189 - 22596 +7041 / 23218 +((27057 * 22826 * 20057 * 23779) * 6578 + 11786) +12892 - 5214 +12105 - 23132 +17534 - 16077 +28595 + 2114 +(29579 + 14738 / 25140 * 9673) +2605 - 11173 +(2086 - 3477 - 29358 - 13983) +826 / 1303 +14583 / 1216 +18396 - 23042 +(23010 - 5718 - 9067 + 21983) +(((31254 * 1926 - (((5545 + 6323 - ((21525 / 14325 * (476 + 16796 - (1595 * 21980 + ((8246 * 27595 * 22626 - 9264) - 22989 * 1735)))) + 8501 * 25167)) * 29956 + 14177) - 26209 + 29264)) / 4963 * 10423) - (11053 * 11815 - 15868 * 32439)) +(((32466 * 32197 * 27226 * 1321) - 8670 + 21149) / 31187 + 17609) +15058 + 5871 +(24830 + 21967 + 19596 + 14986) +(22627 * 2994 * 10605 * 20804) +(674 - 11150 * 16406 * 19472) +2301 + 30337 +29417 * 9679 +16097 / 6087 +11847 + 25838 +8283 - 5349 +1796 - 13970 +9363 / 23896 +9867 * 25120 +10433 + 7737 +10187 + 26055 +25488 + 21384 +5298 * 29180 +13722 + 21147 +21174 + 30826 +27979 - 10426 +(7573 + 27264 - 6567 * 11409) +20730 * 5904 +18880 + 22353 +(12385 - 22939 * (19345 + 31724 * 21665 - 4163)) +19061 + 13089 +2367 + 4478 +27298 * 24145 +((8260 + 28445 + 3912 * 12923) + 31838 * 11376) +13320 + 14222 +11638 - 18914 +27394 + 26318 +3290 * 20184 +8646 * 14334 +14729 + 23173 +((30710 * 6938 / 22314 + 4193) - 1709 - 10582) +3439 + 28405 +18663 * 21022 +274 * 4746 +14441 + 12255 +((21 - 19291 - 6158 - 16422) + 30026 / 24826) +31103 + 7174 +16046 - 773 +(14442 + 7181 + 12396 + 16768) +25174 + 49 +12519 * 28668 +(10059 / 14647 / 4649 + 26135) +6702 - 11587 +3832 + 15343 +(30534 / 27145 + 10504 + 28835) +((23529 - 6581 - 18812 - 27964) * 3787 - 15349) +19199 - 9427 +11388 * 646 +5685 - 17735 +((((405 - 4558 - 4723 * 3308) + (137 + 27479 - 10551 + 12730)) - 30578 / 16736) - 18627 + 7915) +(((31634 - 27099 + 16795 - 15594) - (((29865 - 16794 - 10980 + 25331) * (28708 * 3500 - 6218 * 2216)) / 28505 + 2574)) + (6537 * 14511 + 6352 - 16501)) +(17130 * 24061 * 19935 - 4765) +23833 - 12510 +18779 * 14460 +25739 + 23005 +10446 - 16363 +7140 * 2554 +11428 * 26292 +13621 + 23970 +(((20125 - 6549 + 18733 + 24256) - 2211 + 12607) + 1956 * 8788) +22622 * 19618 +16757 + 25052 +28460 * 5339 +(16890 - 7222 * 2234 * 19289) +26909 - 28379 +15376 * 371 +(13554 * 31978 * (5116 - 1804 - 13957 + 30806)) +10372 + 27826 +24916 * 32641 +31950 - 16168 +20986 * 5757 +22725 / 5267 +(32001 - 28789 - ((8831 * 24331 + (12825 * 28010 - 29434 - 28460)) / 19867 * 27423)) +5887 + 22774 +15905 * 19931 +27387 - 19671 +((12390 + 6102 - (27758 + 18343 - (30497 - 7028 * 14118 * 11616))) - 1151 + 10852) +22899 + 22272 +(12631 + 24353 * 20921 + 6972) +4696 - 9291 +(12766 - 28591 + 14725 + 12195) +5479 + 6703 +(5974 * 10706 - (17862 / 1263 * 25836 - 30279)) +13838 * 7020 +29242 - 8217 +4504 * 13688 +(23947 + 32687 / 32373 * 29531) +4379 + 16992 +9626 - 16061 +18397 + 29015 +25250 + 22344 +(20082 + 11084 * 21194 - 27475) +(26122 - 9292 + 11815 - 25336) +(24922 * 23571 * (18034 - 3396 + 25130 * 2648)) +1459 + 388 +(8056 * 25655 * ((26944 - 26557 + 15275 + 15678) * ((15327 / 5453 + 11383 - 28008) * (1524 - 29471 - 32183 * 7517)))) +(1098 - 9028 * 1783 + 12347) +16847 + 11212 +27124 / 15890 +6761 - 4965 +18835 * 24555 +2104 + 23951 +24691 * 12761 +8799 * 24638 +30087 - 19789 +((4765 - 23682 - 6688 * 23267) + (11076 - 2200 + 10649 - 30311)) +(6258 - 2 * 21380 - 31372) +4881 - 14898 +32358 * 13537 +24208 * 26212 +(((7034 * 13998 + 24817 * 24473) * 29995 * 14400) - 8613 + 26599) +6636 - 9448 +24045 + 26439 +29179 * 22970 +16176 + 12119 +(12712 * 7373 - 11589 * 31125) +(26531 + 12555 * 6642 - 3814) +(25636 * 32696 - 3392 * 23341) +22418 * 14155 +(21168 * 26240 * 28712 + 10693) +23982 * 15097 +2426 * 3685 +((2678 - 25423 * 6496 / 9681) * 13801 * 12890) +(525 - 7201 * 20431 - 23064) +701 - 30404 +(21119 * 18222 + ((26958 - 8406 + 20179 - 5987) + 30011 + 16176)) +((18880 + 29905 * 15158 + 14775) + 3182 - 10178) +(((11874 - 26592 + 11923 / 30259) - 4184 + 23839) + 896 - 29344) +((27454 + 27360 * 12622 + 9166) - 29076 + 24631) +15943 + 22322 +32533 + 4429 +25695 * 17773 +19578 * 24490 +29538 - 9646 +24106 * 27955 +27369 + 10268 +15211 - 5358 +3332 - 9002 +11155 + 4742 +(24307 + 15207 + 10163 * 31245) +27575 + 5364 +1537 * 9246 +29387 - 18321 +336 + 11892 +(2886 + 10846 - 20659 - 20144) +21799 - 12154 +7203 + 11512 +27161 + 24879 +18249 + 4797 +30442 - 29679 +11709 - 29978 +((31046 + 9122 - (9958 + 12850 + 2044 - 24807)) - 19839 + 28656) +(23062 + 31459 * 25846 * 5888) +11049 * 18534 +5862 - 32563 +(11257 * 23311 / 19637 + 19470) +9707 - 1055 +(7212 - 28243 + 16001 - 15412) +1023 + 20475 +12016 * 4684 +(22673 - 20094 + 4545 * 9520) +(26236 + 30837 / 2864 * 1763) +2543 - 17822 +255 * 1954 +2605 / 17000 +27766 - 3366 +15350 + 31194 +8703 + 18864 +(9852 * 5321 + 6162 - 28622) +22264 + 32580 +13394 * 16552 +20004 + 3861 +13996 / 17177 +((23789 + 25329 / 1140 + 19355) + 23494 - 15302) +7797 / 14487 +2471 * 13684 +(2406 * 17487 + (((32421 * 25078 - (6344 * 14358 * 264 * 32211)) + 11261 / 22379) * (26758 * 10784 + 17341 - 6446))) +22773 + 30665 +858 - 9486 +(((23469 + 8303 * (((16264 * 1590 - 26536 + 8201) / (29728 * 30578 / (168 * 1966 - 29378 + 11821))) - 32622 * 8077)) * (((1308 + 3819 - 11897 * 8964) - (18630 + 6987 - 21478 - 21036)) * 10368 + 12707)) * 31097 + 17125) +(16546 + 28594 * 5166 + 32245) +8745 * 23949 +18259 * 3663 +11117 - 30888 +32575 * 30029 +((24374 / 15905 - 27813 * 3295) * 8267 - 28310) +26454 + 1567 +(1273 * 2002 / (18992 + 14128 * 28485 - 4017)) +12364 * 11880 +(27255 + 30670 * (25721 * 29075 * 21461 - 30082)) +(10629 + 2424 * 26338 + 12158) +19220 + 11316 +20875 + 24463 +(13569 - 12445 - 12812 * 7982) +4044 + 16538 +(3856 - 4741 * 23027 - 2416) +(18731 - 2577 + 20736 / 3878) +30359 - 5182 +6688 - 17844 +27311 - 22916 +(13847 + 9605 * (5758 + 28947 + ((300 / 31878 + (16104 - 13711 - 16459 - 28169)) + 23790 * 11411))) +(3504 * 9073 + 15201 * 12199) +11431 - 16947 +(9303 * 14776 - (3856 - 6538 - (13095 - 28818 / ((21055 * 27527 - (9277 + 29514 + 19140 - 27338)) - 10969 - 5591)))) +7514 * 25114 +14552 - 5289 +8067 * 27719 +312 + 23218 +29722 + 20431 +2715 - 2931 +20200 - 2245 +((((16888 - 4263 * 27355 + 15261) + 454 * 5358) + 27541 * 29061) - 5187 / 18487) +24449 * 3022 +(22796 * 29831 * 26742 / 20584) +11593 - 11150 +3135 + 25904 +544 * 1121 +28049 - 20752 +4669 - 19685 +(25144 * 5763 * (14698 - 19622 * 29994 * 18042)) +12499 - 15214 +9255 + 23882 +22471 - 6106 +22698 * 1715 +30087 * 415 +21006 * 22418 +1830 * 16556 +(4497 + 5252 * 13340 / 22688) +((24885 - 19399 - ((20135 * 2275 - 31577 * 8431) + 31297 - 16208)) - 5058 + 17374) +19582 - 5282 +30059 * 134 +((28934 - 28607 - 30172 + 6589) * 8590 * 3370) +((19270 + 8587 + (14499 / 1672 * 21492 - 18016)) - 31883 / 8446) +(1840 - 27840 + (23139 + 26065 - 17223 - 23088)) +(27780 * 13325 - 14294 + 23130) +(11426 * 31630 - (30451 * 18131 * ((358 + 5637 - (2629 / 19010 + (605 - 14422 * 10434 - 1305))) - 26437 - 27759))) +(6166 - 25334 * 28468 / 32524) +5613 * 6947 +10071 * 2405 +14151 + 9186 +13196 * 27060 +22451 * 28081 +((11259 + 1435 + 21907 * 2418) - (1716 + 26643 * 11452 + 6254)) +12680 - 19976 +((20599 - 9698 + 31985 / 4852) + 2098 - 3358) +((23657 / 8736 - (7232 - 31958 / 6445 + 2058)) + 6783 - 15329) +(13068 * 23697 + 11033 + 19662) +1475 * 3511 +(27817 + 26531 - 16738 * 5032) +22176 - 18505 +32443 / 14026 +(15137 - 29468 * 32756 * 19295) +13952 - 12184 +24793 - 18072 +7534 * 9949 +22088 + 5085 +((395 - 25798 * 654 + 11928) * 1511 * 2064) +6342 + 25495 +((1357 * 31453 * 23862 - 10371) - (6570 + 9205 * 21384 + 25769)) +31325 + 6091 +6958 + 7891 +10972 - 18505 +((12830 * 24502 * 5657 + 14117) - (5869 - 16382 - (18269 + 23960 * 26144 * 29532))) +4698 - 13500 +1745 * 32077 +(9086 * 23037 * 32278 * 6468) +6074 + 21648 +23359 + 21429 +5847 * 28971 +31858 * 663 +19483 - 30553 +(974 - 59 / 31892 + 7331) +3988 * 27910 +17465 - 25627 +8289 - 8336 +4445 - 7818 +10995 - 22994 +9970 - 11074 +7073 * 11028 +28011 * 31816 +4577 - 15229 +28217 * 12243 +9739 + 30750 +2985 / 29630 +26128 - 17954 +24183 - 32740 +15425 * 26070 +15719 - 9380 +32607 - 24075 +20496 - 8678 +(19962 * 14786 - 28988 + 18514) +5842 * 29945 +13377 - 12607 +13255 - 5346 +23644 - 30339 +11576 - 26896 +21168 + 9599 +((15099 + 10230 + 12611 * 25484) + 25397 - 14604) +(6863 + 32014 * (12305 / 23629 + (30247 + 21319 * 14477 * 13592))) +(11470 - 4917 - 30861 * 32745) +4309 * 31733 +(3847 + 12425 * (26272 - 1140 + 14531 * 27374)) +17344 / 17562 +(6953 * 29424 * 1294 * 23124) +766 * 5114 +26586 - 11277 +31972 * 4422 +872 + 19147 +1718 - 27239 +4623 + 6734 +29100 * 9406 +(23064 + 26051 - 13912 * 1116) +1834 - 25919 +16914 + 25517 +18487 + 22865 +3166 * 6601 +9872 * 20389 +29524 - 22899 +8819 - 20468 +24005 + 17676 +30969 + 17382 +29 - 19786 +22590 * 15793 +1903 + 13642 +9457 + 17751 +(16042 - 4792 + 19096 * 17982) +18226 + 9445 +9149 * 2727 +4560 - 2109 +7412 * 2181 +31579 + 20111 +(1014 + 20714 * 18373 - 13421) +(25450 * 26963 + (((5840 / 31841 * 27705 * 32729) * 15062 + 23543) - (8693 * 1167 / ((8035 * 6142 / (9697 * 26235 * 25286 / 2681)) * 1617 + 14413)))) +2256 * 22858 +(4483 + 23955 / 26532 * 18656) +(31391 - 31067 / 31697 * 594) +6119 * 24342 +27205 - 6984 +18598 * 16236 +(831 - 9276 / 32624 - 28337) +11939 * 5706 +25280 - 5176 +(25202 * 29466 - (12006 * 25619 + ((28339 - 22047 + 3552 * 12200) + 24894 + 28111))) +8906 - 30152 +14169 / 25827 +(24616 + 9388 + (2411 - 23203 + (30096 * 30872 - 22872 + 7))) +2192 * 1783 +7614 * 1295 +20133 - 27877 +14254 - 7374 +(9634 * 17548 * 20601 - 19436) +24881 - 9360 +(26040 + 18638 * 26570 + 29811) +28022 * 26380 +(27662 + 18000 / 16986 - 6270) +(24709 + 12098 + ((25719 * 13378 + (8999 + 21951 * (9432 + 24624 - 11128 + 30383))) * 2759 / 7740)) +6848 + 17924 +32089 - 22056 +(15612 + 24917 * 27558 - 31724) +(3158 + 31382 * 18370 - 28495) +28259 - 337 +13968 / 6235 +4631 * 22711 +(18877 * 5471 * 14796 - 15927) +1898 * 28226 +707 * 16068 +((((8833 * 27581 / (26477 + 10794 - (8288 * 9274 - (4867 * 30611 / 32047 + 23619)))) + (19188 * 1041 * 22391 + 30474)) / ((6120 - 15323 / (5168 - 25424 * (31967 + 6247 + 15527 * 4928))) + 22331 * 28394)) * (15536 + 16032 + 16333 * 1239)) +17542 - 28534 +19193 * 29744 +16426 + 2694 +32554 + 31785 +((1189 - 20138 + (25249 + 15031 / 11463 - 485)) * (4879 - 3954 - 751 + 5887)) +31244 * 10218 +1623 * 7920 +7386 - 7258 +(16333 + 27837 + 1254 / 20356) +(((2522 - 28272 * (10163 - 21253 * 14666 / 24696)) - 26745 - 17891) * 2988 + 19152) +12982 - 27127 +(11637 - 24656 - 915 - 7971) +1240 * 20968 +32091 * 13190 +((21807 * 26762 - 24776 + 25818) * ((5953 + 18272 * (12197 / 13948 * (25357 + 31210 - (1877 / 32059 + 1063 + 2384)))) - 12198 * 289)) +28899 + 13666 +16751 - 18827 +(13102 * 5377 - 16298 + 11671) +16441 - 1332 +1235 * 53 +696 * 24888 +16673 / 5207 +10541 - 8448 +32666 + 6754 +(17020 + 19898 - 31634 + 19911) +28157 - 23495 +6535 - 31204 +8475 * 17680 +2940 - 25221 +5817 + 16579 +(9332 - 21800 - (27986 - 21326 * 29058 * 8937)) +((((1661 - 17260 - 23553 * 7423) + 12152 * 2690) + (4096 - 9656 + 29657 * 249)) - 23200 * 26401) +5278 - 12527 +5968 * 28572 +27517 - 321 +15864 + 20943 +8122 * 31932 +(26201 - 22080 * 9861 + 439) +119 * 4103 +31424 * 32419 +28645 + 25475 +(24844 + 12639 + (1525 * 20567 + 30361 * 10717)) +2855 * 7210 +16560 - 22092 +(29712 - 19399 / 25051 - 10626) +5589 + 4966 +14942 * 24844 +(15727 - 7325 - 20797 - 26383) +19791 + 4453 +27680 * 9708 +14167 * 5121 +32235 - 6619 +12173 + 9700 +(9313 + 19905 + 7204 + 17001) +27134 * 18884 +8027 * 26171 +(8311 - 26766 / 10898 + 12398) +1998 * 15471 +14825 - 17626 +14454 * 21617 +13704 - 6100 +(((24428 + 12541 - 738 / 20978) - 21639 - 22120) * 22948 - 21529) +5961 - 19555 +(19253 / 5915 * (10644 + 22787 * 26754 - 18861)) +(28457 + 12120 + 26129 - 178) +1894 + 30266 +27866 * 828 +2732 + 15857 +(((31787 + 22566 + 31657 * 31952) / (12733 * 6332 * 842 * 6228)) * 11583 - 22902) +(20130 + 24634 - (9292 * 1719 - 17222 + 2248)) +1941 * 17206 +912 * 20190 +24649 + 3847 +9722 * 7140 +23683 + 8365 +9478 - 3515 +689 + 9582 +18773 * 14671 +18572 / 24552 +18119 + 18444 +28296 + 23531 +(26361 - 22440 + 17167 * 25481) +(27060 * 363 + 21671 + 7109) +11944 - 7164 +12528 * 27598 +5434 + 11503 +10868 - 8124 +2645 * 7799 +1722 * 10976 +(23606 * 11216 + (13129 + 19262 + (18840 - 29932 + (3649 + 19369 + 27754 * 7019)))) +(7703 - 30560 * 23942 + 6599) +(24728 - 4501 - 27056 + 14484) +8015 * 2531 +((29888 + 32070 * 32324 - 6578) - (31544 * 22868 + 23258 / 15733)) +6883 + 24013 +19772 * 28410 +1148 - 30509 +19104 - 16729 +6282 - 29807 +18365 * 10533 +8150 + 23345 +(351 - 16906 * 30151 * 26064) +823 + 19266 +(30837 + 20414 * 28920 * 27923) +24276 / 11838 +17566 * 30265 +10157 * 7455 +(26604 - 6251 + 747 / 30219) +18038 / 4783 +(19643 * 15447 - (8425 * 3013 * 11769 - 3604)) +31271 * 18561 +27759 - 599 +28478 * 6783 +14332 * 21031 +(((3788 - 3544 - 28133 * 28674) * 32595 - 2530) + 16712 * 27223) +(11178 + 6920 + 2541 * 14032) +20498 - 7024 +12980 - 25451 +14191 + 27507 +14151 + 15512 +5797 - 4791 +10325 + 25538 +18786 + 2580 +31102 * 18414 +10843 + 23554 +25071 * 31730 +(13372 + 6795 - ((32704 + 3222 + 9248 + 30136) - 25007 + 8086)) +(3678 + 20638 * 1011 * 5583) +17899 - 8228 +(13418 - 1362 - 5235 + 14148) +2411 * 31001 +18784 / 24548 +31394 * 1263 +29999 + 9166 +(6132 - 4073 - 2028 - 4790) +7997 * 2312 +4317 + 15358 +26122 * 25170 +(25780 / 7018 * (25111 - 27553 - 8747 / 12692)) +5064 / 16176 +16808 - 19610 +28307 - 31636 +26777 - 13444 +223 - 6826 +3197 - 8883 +16463 * 25142 +5421 * 11069 +21039 - 21571 +15109 + 22095 +5439 + 8019 +25901 / 26123 +19845 - 7844 +17041 + 9487 +28640 / 28419 +14351 + 20068 +16752 + 17102 +((24357 + 31017 + ((4456 * 30118 / 16777 - 2424) * 3978 - 24662)) + 11204 + 2217) +1066 + 15496 +30671 * 24549 +12922 - 2086 +10529 * 21710 +20972 - 29578 +(31760 * 24687 * 11341 * 26580) +20324 * 12756 +31661 + 28205 +(18731 - 7736 * 28431 - 21135) +20917 + 19103 +3406 + 7966 +7534 * 31368 +19871 + 17052 +16838 + 10963 +2359 * 19610 +31432 - 18528 +21441 + 30152 +((17637 - 8361 / (21732 + 982 + 24549 + 4523)) + 25558 * 3919) +31411 + 11381 +16038 * 24212 +(7775 + 16726 * 7122 * 17869) +27609 - 19562 +14531 * 12318 +2678 * 4650 +(7169 + 11090 * 20945 * 25443) +29153 * 20270 +(24337 + 4183 * 19419 - 12133) +21506 / 15669 +(9232 - 4643 + 2343 - 8961) +14698 - 13938 +(24629 / 5881 * (21277 / 31193 * 13427 - 9330)) +9686 + 14853 +((4466 + 21943 + (11814 + 1748 + 24824 * 1981)) + 30604 * 7780) +29393 - 23207 +28236 * 9696 +2400 * 2473 +7264 * 23898 +31706 * 26448 +30535 + 17353 +17097 + 1056 +2334 - 9042 +11357 + 31695 +(((10024 + 24455 - 16763 + 14330) - 13555 * 22913) + 2228 - 10293) +19132 - 21108 +6395 * 5565 +3996 * 2978 +17585 - 12259 +14158 + 19303 +(1598 + 22546 + (26447 / 6922 - 22753 - 28975)) +23080 / 9730 +(19795 - 14146 * 7185 - 858) +(24893 - 17123 - 4062 * 18921) +(7104 + 4975 * ((((13253 - 25859 + (4323 - 18936 * 29866 * 26941)) - 20165 / 26441) - 28710 * 9783) - 12806 - 13874)) +(6520 * 18478 - 21920 + 32607) +(11772 + 27356 - 10274 * 14626) +4534 + 29509 +5761 + 10475 +((11821 + 28237 * 28039 - 24336) + 27579 * 22482) +25582 * 16022 +(25492 - 2859 - (20872 * 22837 * 24619 - 10766)) +(7690 * 23202 * 18395 + 29066) +28193 - 12334 +23940 - 14163 +(((21721 * 17613 - 3227 / 32556) + 18807 - 23919) + 3502 + 19132) +14588 - 16541 +25182 - 11297 +13890 * 5626 +22023 - 24580 +16903 + 17668 +18027 * 15080 +4907 - 16269 +19749 - 32524 +26395 + 9617 +30514 - 23237 +26887 / 18871 +(19294 * 21568 * (2860 - 27919 * 3786 * 16819)) +6941 * 23453 +(4866 / 4966 * 18006 - 14417) +13719 - 30553 +12919 - 19781 +(26161 / 4185 * 24009 * 14066) +((14065 * 11412 * (8201 / 12317 - 31831 + 22032)) * 15860 * 13136) +31058 - 4040 +4566 - 17823 +26743 - 18153 +31609 * 28133 +24833 - 8563 +26439 * 30267 +20051 * 12697 +30250 + 2800 +(8962 + 10624 * 4968 + 10135) +30476 * 31983 +18630 + 10024 +(32567 - 29912 / 6025 + 28970) +14103 + 1951 +9576 - 30456 +2809 - 25941 +10919 * 24480 +13891 - 29427 +23341 + 20547 +(5996 - 11479 + 24523 + 10332) +23147 * 28300 +4436 - 19992 +(2742 - 25798 - 28169 + 12898) +24562 / 10545 +((32697 * 2079 - 16870 + 9132) - 4144 - 2210) +29797 * 4442 +25775 + 24556 +8457 / 26179 +23494 - 29648 +28749 + 24368 +26717 * 27604 +3030 * 17269 +8029 + 116 +1445 + 10186 +28527 - 28886 +23324 - 4332 +10772 * 23853 +(15683 + 28967 * (30552 * 26911 / 3585 * 6109)) +10771 * 17998 +9461 * 30867 +26580 / 1879 +20792 - 22381 +10642 - 13918 +20973 - 7368 +25827 + 29145 +30186 + 19770 +27515 * 18186 +3210 * 22285 +((((27335 * 22535 / 23874 * 28866) * 28305 - 20914) + (15362 - 13152 - (14981 * 28215 * 22310 + 28425))) - (664 + 4023 / 1836 - 20481)) +102 - 26398 +10395 + 29659 +10139 + 2479 +29296 + 9973 +7720 - 32589 +27250 + 15986 +(16427 + 2124 + ((18761 * 8882 * 22057 / 6973) + 8067 * 14187)) +19926 - 22264 +32328 - 13990 +4686 + 14607 +7780 * 25561 +29452 * 12096 +(9325 - 29896 * (20730 * 30979 + 25523 + 32173)) +11325 - 7512 +31111 - 16552 +19436 - 2136 +8515 * 16266 +1727 + 31835 +21481 + 28642 +((((8674 - 17911 * 29544 + 19815) + (29604 + 1015 * 25372 * 25742)) - 13699 + 26829) * 17900 * 6356) +3430 - 13526 +26895 - 6402 +10823 / 7036 +10199 + 3708 +16289 + 19849 +(21120 * 28306 / 30743 - 11759) +3263 - 13842 +22807 - 21374 +27784 * 14240 +7760 + 12716 +27071 + 11630 +701 / 12882 +9965 * 10791 +16018 - 5049 +9910 / 15747 +(14078 * 26662 + 12181 - 3907) +32742 + 12792 +15343 - 26993 +15945 / 23253 +19343 + 1437 +31851 / 29737 +17383 + 10980 +9340 * 15432 +12929 * 6766 +(31008 * 29275 - (((12603 - 24822 * 15850 + 12346) + (8315 * 22484 - (27504 * 8165 - 10872 + 24063))) * 10262 / 15090)) +1332 - 1667 +15398 + 30389 +30148 * 22937 +14780 + 17453 +31014 * 25555 +14968 - 18077 +14007 + 25043 +(26994 - 28644 * 10841 + 27618) +23174 - 2298 +20448 * 9384 +11502 - 27050 +27931 - 7509 +4210 * 4437 +5284 * 7007 +((12714 * 5494 - (18875 * 21719 * 21107 - 10725)) * 18572 - 23911) +9037 + 31000 +16620 * 5894 +21514 + 5598 +2203 * 31104 +1478 + 757 +4420 - 31842 +(615 * 10264 + 10757 - 852) +13852 - 3532 +18165 - 19466 +22177 - 19858 +20052 * 28692 +(27488 - 18330 * 26626 * 30048) +9702 - 11384 +(((1988 - 430 - 30156 / 15872) * 830 * 29847) * 14999 - 8494) +176 - 30432 +(6887 * 13194 - 19750 - 18315) +17130 - 15028 +13420 - 13619 +18508 * 29569 +(26579 * 8461 * (7535 + 19712 + (21210 - 22921 * (10591 - 6766 + (30664 + 22332 + 14602 * 14473))))) +19325 - 1675 +5345 - 1477 +29415 + 15127 +6703 * 5668 +((29072 - 8097 - 27082 * 8784) + 135 - 19319) +31152 + 3665 +24020 - 15481 +5564 + 29952 +(9293 * 29098 / 2286 - 31358) +4405 + 1186 +(((10388 * 10801 * 30179 - 24843) / 5245 * 12356) - 31398 * 25376) +25674 + 30233 +(1100 - 3569 - (26905 * 24663 - ((28257 + 5127 + 22641 + 28980) * 16366 - 8108))) +(3561 + 4651 + (2106 - 27679 - (1429 + 1730 - ((20839 * 12208 + 598 * 29572) * 13025 + 27671)))) +4574 + 30052 +4142 / 13532 +25802 * 27606 +30373 - 320 +25762 * 30656 +7820 * 6975 +(30169 - 11629 * 5608 * 20073) +(((14638 * 5915 + 21545 - 19746) + (12731 + 8327 - 21002 * 14547)) + 9941 * 19949) +(11995 * 25773 / 31611 + 5109) +(19536 * 22080 * 17097 * 716) +24172 - 11023 +7690 - 8468 +(24533 * 4112 - 13782 * 31225) +29775 * 2767 +21676 * 8390 +14438 - 13190 +((31108 - 26959 / 16200 + 28520) + 31214 * 12886) +(9265 - 14362 + (580 * 9981 + (14857 - 19104 * 13530 - 6824))) +16745 * 9141 +31426 + 26053 +26195 - 19825 +8726 - 26170 +12242 + 13857 +1022 * 11022 +28619 * 25038 +5881 * 23454 +23695 - 32398 +(20761 * 15322 / 23690 * 31935) +3611 + 12121 +5380 - 14427 +6114 - 24236 +1247 * 25864 +(13887 - 5592 * (4312 + 21597 / 10040 * 11482)) +22785 - 27740 +4308 - 4278 +6481 + 11726 +31022 - 13092 +9047 + 1709 +18909 - 19486 +25210 * 4616 +14501 * 6202 +26522 * 26827 +(13279 + 7629 * 27289 / 17023) +22024 - 13748 +14501 * 28118 +22594 - 23838 +17687 * 3221 +2403 * 25913 +28165 + 8297 +12311 - 2803 +11448 - 32508 +(28269 * 8013 + 30585 * 21287) +28783 - 29007 +1881 - 20016 +25905 - 28095 +(16727 - 19269 - 15119 + 29478) +18756 * 17656 +20541 + 10993 +32543 + 9181 +21998 - 636 +5672 + 22119 +20252 * 31122 +(10820 + 662 * 15881 * 26554) +13591 + 28392 +22240 - 20233 +29478 - 21869 +((32397 + 19744 - (27301 * 8892 - 29394 * 23494)) - (7903 * 3541 + 23572 - 22308)) +24210 + 19866 +10032 - 11133 +19333 - 28644 +25322 - 31159 +29017 * 351 +23810 * 12700 +1090 * 10977 +19394 + 20257 +24888 - 6006 +30232 * 5265 +11271 * 14902 +((23321 + 9131 - (((21884 * 7343 * 13795 - 1415) - (4426 + 10207 - 30226 * 23508)) + 11730 - 24170)) / 16451 + 19430) +24559 * 27951 +1124 + 15313 +30854 - 28931 +4922 * 22613 +1729 * 10877 +(5833 - 15992 - (9735 - 4728 - (1139 + 30348 * 14049 - 7464))) +25115 - 27366 +(((22162 - 7392 * 17380 * 1556) + 7058 * 27892) + 24354 - 6930) +(25694 + 3678 + (22898 - 12651 * (25472 + 16463 * 6415 + 22387))) +14347 + 30654 +((32539 + 29490 / 23028 * 17309) + 14921 * 21078) +20607 * 12279 +15236 - 29023 +9753 * 22149 +3311 * 7566 +15218 / 8102 +((6739 + 21331 - 17175 + 9605) - (4457 * 11328 + 22981 * 9565)) +(25473 * 16081 - 31992 - 1063) +(15565 - 25420 - 4944 * 21978) +31334 + 26461 +10581 * 24414 +19135 - 28915 +7730 * 20370 +(17365 + 12878 + 3393 + 12475) +19761 - 29983 +12059 - 24993 +17970 / 9803 +6267 - 18914 +23087 + 3323 +17021 - 168 +21757 + 17415 +12500 * 21763 +(16280 * 3899 * 25182 * 23786) +7247 - 3410 +10960 * 29305 +((458 + 3224 * 21735 + 1222) + 16370 * 6141) +19439 + 18296 +1655 - 9832 +25114 + 23706 +17052 * 7163 +12879 / 28848 +12722 + 8694 +18612 + 12154 +8028 + 32062 +3232 + 17703 +32584 + 13099 +20099 * 26319 +3278 - 15642 +19450 + 21020 +18967 + 16950 +(7414 + 10764 * 29788 - 13047) +12377 - 27660 +4541 + 8247 +4584 - 9922 +7837 - 28612 +(6876 * 23871 + 30503 * 12159) +182 * 11073 +10182 + 29 +14636 - 10769 +9411 + 14995 +4998 - 8659 +(15508 / 11393 * 19880 * 21125) +20121 * 27997 +14617 * 23650 +16163 * 9895 +((10638 + 2214 * (((12963 * 12357 - 10087 / 2331) - 31383 + 27065) - 9917 * 5902)) * 2973 - 27691) +15375 * 12529 +29265 + 11381 +(17446 - 17597 + (25137 * 22701 - ((30014 + 32738 - 27519 + 19667) + 23797 - 5309))) +5753 - 3257 +9092 * 1511 +(29740 + 18932 - (13923 + 3680 - (17971 + 30245 * 28792 - 28017))) +13930 - 766 +(23463 - 11121 - 25430 - 19928) +16847 * 17522 +32123 - 10071 +(21421 * 11391 - 11908 - 22281) +22442 * 10028 +27384 - 24499 +10156 + 21425 +7338 * 27686 +20750 + 5689 +(5286 + 26953 + 5347 + 13594) +(9179 + 6316 + 11059 + 25914) +35 - 608 +11277 - 15812 +891 - 23134 +18510 - 22786 +25704 * 23636 +24663 * 4043 +23634 - 28834 +4992 - 12282 +28191 + 14060 +14109 / 14496 +(16101 + 19792 * 9254 / 3072) +17195 + 12684 +944 * 31147 +29586 - 16913 +683 + 23634 +16925 - 2352 +23216 + 26389 +22729 - 23141 +8806 * 16036 +(22625 * 7387 - 19066 - 11355) +29599 + 24443 +19052 + 30793 +5920 - 10990 +5013 * 26864 +21582 + 26270 +9729 + 20887 +14649 * 27939 +17995 + 3424 +13601 * 15144 +5436 - 25310 +24788 + 13720 +423 * 12056 +29705 + 14972 +21243 * 26951 +2243 - 17427 +9515 * 6783 +28640 * 23670 +((12775 * 22511 + 24858 * 25021) - (13978 + 28179 + 23486 * 31850)) +15863 + 4751 +25126 - 11536 +31573 - 19973 +21982 * 1663 +(25823 - 24191 - (28561 + 31267 - (25539 * 25097 + 30201 + 19407))) +11847 - 4248 +(((3932 + 17237 - 26637 + 20587) * 31532 - 23153) - 25454 - 21761) +23603 * 5735 +(9459 - 10037 * 6472 - 16000) +21139 - 18090 +657 * 27839 +11707 + 9606 +5711 - 18302 +5816 - 30662 +8642 / 21587 +18353 - 10878 +14333 + 3698 +10372 + 22167 +10475 - 458 +5736 + 9369 +8703 * 4376 +((28208 * 7289 * 26655 - 5662) + 24904 * 30328) +8691 + 13503 +2943 - 4550 +32153 - 27707 +(3060 + 27592 - 13731 + 10245) +2238 + 1345 +300 * 24468 +22195 - 31140 +(24806 + 9083 * (30043 * 29797 / 3908 - 1865)) +((18121 + 18260 * 25471 * 17865) + 28053 * 4967) +(32477 * 32040 + 6667 + 9442) +1499 + 30257 +(((16957 * 25546 - 24942 + 3567) * 12348 + 29790) - 18396 - 30576) +1961 - 30310 +5259 - 9103 +15883 * 21868 +25984 / 15270 +10524 + 25229 +2014 + 27829 +6709 - 21290 +((16454 * 24775 + 28250 * 5975) - 7787 - 32236) +2496 - 27659 +9043 + 4607 +(((30098 + 30979 * 3245 + 3227) * 28028 * 12955) + 1836 * 30858) +(5500 - 29903 - 7342 + 8605) +25814 - 830 +6738 * 22516 +5438 - 3492 +29069 - 17952 +11474 * 14160 +9871 * 22561 +1975 + 16828 +21828 - 22138 +(26861 * 415 - 29934 - 1031) +24903 - 29503 +13513 - 10646 +31580 - 11714 +21454 * 26345 +12014 + 9187 +11092 - 8189 +27478 + 8282 +9205 + 16521 +13737 + 2238 +8300 - 22753 +29447 + 28387 +253 / 25338 +4825 / 11437 +28987 - 9305 +17653 * 12073 +20301 - 1031 +16701 - 30425 +(24034 + 9730 + 20121 * 25155) +12960 + 32630 +6811 + 6518 +11284 - 13203 +(29358 / 12921 + 1783 + 1859) +(4652 + 20611 * (5302 + 28479 + 13253 * 1128)) +23202 + 12862 +((13683 + 23129 + (4008 - 22710 - 16973 * 31402)) * ((16881 - 25718 + 25701 * 14824) * 27657 * 31773)) +7986 / 26940 +((15994 * 22117 - 9865 + 27838) - 482 * 19353) +25987 - 5434 +12534 * 5643 +(6324 * 15071 / 25437 + 8321) +20207 / 4585 +22985 * 28510 +13712 * 202 +(24393 + 22717 + (13783 + 30986 + 7236 * 22018)) +24118 + 20976 +2643 * 28067 +16292 - 27264 +31434 / 17625 +(((23148 + 29973 - ((5523 * 32668 / 24250 - 17630) / 2091 - 7159)) * 6309 + 30505) - 4987 * 18486) +28299 - 21972 +((24444 * 22030 * 28721 + 2053) + 23783 / 6183) +(15564 + 5098 / (15574 - 31277 - (22540 * 24047 - ((19011 * 14576 * 14602 - 23752) * ((7377 / 32426 + 24717 - 21917) - 14657 + 13193))))) +(1326 / 10834 * 5248 - 27425) +27005 / 25622 +26980 - 8793 +2376 * 24099 +((10229 + 10982 - 19048 + 11393) + 15549 / 11044) +1221 - 24057 +8841 + 6740 +15818 - 9291 +169 + 10323 +(23650 * 15065 - 14150 + 30112) +(4545 + 32283 * 7659 - 4576) +26061 + 20922 +6857 - 1358 +6592 - 10004 +8396 - 13291 +25844 - 13081 +22699 * 30304 +23477 * 28440 +4330 * 3144 +20780 / 9383 +2103 - 1875 +(2491 - 31809 * 125 + 16353) +17520 - 23905 +17503 / 20203 +1685 * 28075 +10123 + 12902 +(26090 + 12512 / (14195 - 11441 + 29199 + 24799)) +14888 * 32407 +29701 - 8458 +7471 - 10431 +(9776 * 14457 - 21814 * 24062) +(9562 * 21810 * (26022 + 15228 - (19683 + 16854 * 27500 + 31676))) +26265 * 17347 +24745 * 22233 +26466 + 30123 +852 * 29027 +(32070 * 32589 - ((14533 - 23965 - 10169 + 19508) + 24381 / 9632)) +(14599 - 32347 + 30675 / 28983) +((23672 - 21287 / 6644 - 18405) + 12039 + 12458) +1159 + 556 +4055 - 4179 +(28659 + 17552 + (26166 + 1640 + 2622 / 7973)) +21947 * 10448 +21465 + 31178 +((15316 * 32538 + 13401 + 2144) - 22180 + 12607) +15671 * 22125 +(((24883 * 14310 * (26778 * 11041 + (31149 - 21648 + 29078 - 23864))) + 19809 + 10920) / 3080 * 29191) +17420 + 2975 +(29987 + 7293 + (30221 + 15648 * 10697 + 30560)) +(26763 * 8273 + 4149 + 18963) +6493 + 29595 +14373 - 5063 +((20465 - 6167 * 27036 - 6405) * 16796 + 9429) +2251 + 24301 +((28114 - 15626 * 29327 / 4815) + 27248 * 11913) +7636 + 16631 +2559 * 30800 +(12850 + 17345 * (18982 + 12763 + 30356 / 4452)) +30463 + 4346 +(15879 + 14974 * 7766 * 29939) +20274 - 19303 +1566 * 17175 +1361 + 5243 +19471 - 8533 +12379 + 16916 +30361 - 26006 +29165 * 6932 +6906 - 5229 +((21314 - 17599 * 3337 * 26726) - (7609 * 20608 + 28366 * 29110)) +3478 * 18588 +31087 + 32260 +32495 - 6036 +11398 / 30234 +8533 + 7633 +(21135 + 13963 - 30987 - 6806) +13569 / 23664 +((14697 - 13762 / 7376 * 25895) + 8743 / 27260) +11605 * 1891 +(19283 - 32048 * 19075 - 31914) +21380 / 25729 +(27204 * 19254 + (9060 - 20914 * (4070 * 32112 * 20992 - 2713))) +16299 + 15077 +2868 - 16367 +13171 - 29603 +(11378 * 27436 + 2537 - 9398) +24107 * 10438 +(28915 * 1659 - (28059 - 32556 + 24740 + 1262)) +5379 + 22782 +3463 - 26027 +((22134 - 9763 + ((8793 + 11542 * (12878 / 14620 * 14877 / 22868)) + (27284 + 5168 + 32055 * 1089))) * 32250 * 30160) +31527 * 9658 +27331 - 6848 +13432 - 31803 +1478 / 16142 +28821 + 18445 +32640 / 13102 +30979 * 17795 +(3117 + 467 * (13176 * 32081 * 20533 * 22086)) +(18935 - 28547 - (19365 * 37 * 4644 + 4173)) +20443 + 29748 +27036 - 26270 +2001 + 1196 +22910 - 6690 +(19429 + 15181 - 18628 + 8936) +24031 - 31843 +(28110 - 5036 + 29469 + 4945) +101 * 11581 +119 + 4482 +(11306 - 7567 - 26292 - 9655) +((5755 - 15902 - 17307 + 24074) + 11623 - 3061) +18805 + 4245 +1268 * 4408 +27682 + 30358 +31444 / 10657 +29192 - 24913 +(1704 - 15388 + 11530 + 5358) +18238 * 28335 +5507 * 30835 +30283 + 29779 +8351 - 1668 +25061 - 26249 +29068 + 8111 +23130 + 3648 +((9469 - 14075 * 13759 - 26200) - (21658 * 7136 - (((28923 * 575 * 24460 / 30622) * 6995 * 14314) / 8093 - 6000))) +24646 / 1807 +6957 / 6035 +21242 * 1912 +14850 + 14009 +22104 * 14690 +17044 + 13300 +10773 + 18525 +(17424 * 2968 + (31031 + 4658 + (2135 - 14563 + 22357 - 10348))) +16825 + 24356 +22124 - 16346 +7797 - 19163 +((401 * 9846 - ((15458 - 19852 * (12394 * 20261 + 26940 / 4231)) + 31650 + 3153)) * 21700 / 31123) +8398 + 1057 +(14566 + 2772 - 12779 - 8961) +29754 + 11904 +10919 - 10018 +((22616 + 17173 / 8350 + 14226) + 17194 * 30517) +29617 - 30630 +2858 - 2348 +5640 / 9388 +27098 * 29757 +24768 * 1304 +18455 * 21015 +4208 - 22271 +27608 + 3641 +29947 / 11066 +24883 * 22329 +25558 + 3551 +13777 * 26802 +21091 - 20813 +(((27141 * 5443 * 1596 * 20552) * 30867 - 18993) - ((((6645 - 14050 * (28802 - 25244 + (14496 * 24902 + 16608 * 25640))) + 24707 * 3643) * (22412 - 9669 + 19100 / 10759)) / 9891 * 30690)) +(6911 * 30171 / 17231 * 14921) +2548 - 18959 +15537 + 4902 +(17197 + 32627 + 27580 + 25) +(12198 * 289 * 13480 * 30803) +27065 + 20537 +(14915 + 10490 * 3721 * 1970) +31235 - 30886 +3716 + 27120 +30865 - 3575 +(((5447 * 18142 * 29513 - 3225) * 1700 * 27150) + (((10935 - 26800 + 1345 - 30628) * 23067 + 2409) - 18144 * 22073)) +(((4789 + 29008 - 30397 + 5752) / 2133 - 29212) + 7743 - 8384) +18189 + 79 +3727 * 29520 +(16436 + 27421 + ((17444 + 25611 / (13618 * 30449 * (20325 / 7438 * 3408 * 527))) + 19079 * 2341)) +((26560 + 10309 - 27487 - 1510) - 28903 + 10336) +(9267 - 6439 - 13842 * 30768) +4002 - 30163 +29334 + 2864 +(11997 - 22195 + 17156 + 17136) +14841 * 11537 +20942 + 12524 +(7915 * 2392 * (25305 + 11297 - 27334 + 14251)) +16198 * 5399 +22749 - 9512 +2357 * 7906 +28246 + 8860 +11663 - 22645 +21619 + 24650 +22481 * 32731 +3061 - 4131 +10244 + 5406 +17029 * 22939 +4598 + 1688 +21613 - 16167 +((17535 - 4504 + 28966 + 32247) / 27992 * 14663) +(29407 - 9228 / 22566 - 21948) +3630 * 25237 +18466 + 32086 +(31663 + 16647 * 7435 + 18834) +17373 - 5520 +((3198 + 17501 + 20988 / 26915) + (27021 * 16986 * (14498 / 31419 / 30101 + 14192))) +30695 - 7400 +31575 - 17453 +13059 + 25797 +19758 - 9108 +5446 - 23570 +22991 * 23915 +(((25191 + 19561 + 22822 - 8213) + 23934 + 20893) - 11787 - 15406) +(20314 * 28462 / (9229 - 16352 * 28470 + 8299)) +(404 + 30570 * ((11935 + 15359 - 27139 * 32560) * (14927 + 10603 - 8663 - 22495))) +10476 - 28962 +(28523 * 5292 + 31892 / 7413) +22644 / 1503 +(31841 - 12753 * 25857 + 16112) +16475 * 13578 +22822 - 27424 +(23234 * 4259 * 11453 - 27108) +22660 / 3239 +15830 * 24005 +20969 / 6243 +2790 - 6445 +((26690 + 7331 * 27632 + 4742) - 19633 * 14450) +(365 * 21143 - ((619 * 27635 * 14875 * 1008) + 22032 + 25382)) +15046 - 15180 +27673 + 12530 +32274 + 22847 +24974 * 12079 +12657 + 25984 +6723 * 7601 +1783 * 3200 +11366 * 6159 +(10751 + 5822 + 30321 * 30539) +(15414 + 25727 + 14684 - 6912) +9017 - 15439 +21731 - 28380 +9018 * 21498 +24595 * 4392 +((25552 - 4544 * 4838 - 32493) - 21564 + 17206) +18506 * 6753 +21145 - 14940 +31687 + 21549 +22166 - 30208 +15273 - 29022 +(6922 + 23573 * (2895 * 11795 + 15026 + 2705)) +27729 + 7675 +31535 * 25214 +7123 / 27040 +11972 + 25613 +3671 * 8344 +(30561 + 2704 * (20725 / 14191 + 495 * 11642)) +3168 * 19247 +16528 * 3706 +7710 - 1303 +27983 + 31647 +20994 + 2647 +(28524 - 24802 * 30138 * 24457) +15568 / 13531 +14248 - 15290 +19027 + 20317 +(1873 - 7357 / 15664 - 22144) +15801 * 10532 +(12321 * 2543 + 14321 + 32206) +(19268 * 20176 * 4787 - 22236) +(12218 * 5171 + (((28274 - 12357 * 10363 * 18513) / 16120 * 7990) - 1930 * 21614)) +4274 * 16692 +(16998 / 2152 + (9900 - 12373 * (11081 - 26987 + 12009 * 624))) +(22765 + 2570 + (2940 + 21138 - 32758 + 5662)) +1043 - 6089 +16461 * 28212 +1016 + 32711 +31629 + 8055 +8512 - 834 +(27382 * 20118 - 30069 + 119) +31905 * 18781 +8422 * 20534 +2688 + 5487 +1629 - 11849 +((15197 - 6924 + 27182 - 1591) * 20622 * 6412) +13499 + 31725 +8606 - 16028 +26777 * 17372 +13122 * 6857 +18617 * 17959 +(28939 * 32341 + 4995 * 7442) +(12065 + 11077 - 4381 * 19027) +23220 + 21961 +14597 + 22696 +(2473 * 10678 - 30344 - 8375) +16219 - 4923 +(18768 * 8194 + 17866 + 10913) +18834 * 17881 +12157 + 4804 +14273 + 25400 +(16313 - 31240 + 14901 * 17674) +22237 * 7111 +(9957 + 9985 * 20421 + 11684) +25631 - 21196 +(946 / 24320 + (1211 - 2655 / 10738 - 11063)) +8961 * 1674 +30119 * 24262 +32285 * 13330 +(24862 * 27995 + ((20186 + 2037 / 22402 + 1374) + 7983 - 3264)) +5531 - 12939 +15525 * 27766 +5305 * 9211 +5471 - 27906 +24109 + 14056 +((18759 + 26895 + 5391 - 32590) - ((31768 - 5405 - 31946 / 29819) - 7381 - 27993)) +18160 - 1940 +14455 * 7727 +14058 * 27437 +20040 - 4693 +32553 * 30050 +8807 - 7783 +(3234 + 16371 * 27300 + 1610) +29845 * 13468 +24312 - 4658 +6353 * 229 +170 * 17029 +29461 - 2884 +21600 * 4935 +(19678 * 9060 * 9745 + 24527) +9375 - 17746 +15377 - 6703 +3242 * 11163 +6940 / 4553 +32046 + 23667 +25836 + 29011 +(890 + 32272 / 27056 + 14484) +9907 + 5703 +((22293 * 13229 - 15807 - 6565) + 10382 - 11157) +14693 * 21348 +30407 - 6770 +(7015 - 22880 - 2218 * 18051) +13854 - 4845 +(8564 + 10493 + 13930 * 24453) +19126 + 7280 +22638 * 15940 +4353 - 20830 +18786 * 17021 +28561 - 1332 +5866 - 13290 +((((26969 * 21136 / 12193 + 13972) + 15101 * 28381) + (9671 / 29136 + (((12898 * 6280 * 27995 + 9571) + 3899 + 15582) + 5882 * 6401))) * 30952 + 22807) +((25487 + 27313 * 8246 + 4695) - (14948 * 6159 * 15181 + 15004)) +1774 - 23277 +29977 + 17465 +(25958 - 18813 * (2532 - 2015 - 16958 + 26722)) +23650 - 24358 +(23522 + 31106 - (2665 - 17099 + 17004 / 781)) +13735 - 14092 +3505 - 4261 +(16709 * 17209 * 32391 * 6169) +(30599 * 31993 + 27225 + 30156) +15750 - 26162 +19268 + 23649 +14436 - 29214 +(8328 - 4355 - (14057 + 20649 - ((23492 - 2723 + 16099 * 27731) - 12490 * 22529))) +11473 / 6794 +16993 - 31662 +24741 + 28421 +14079 + 3577 +(21907 + 14403 * 26823 + 3691) +20710 + 29030 +14745 - 16494 +(8524 + 4151 * 31207 + 17857) +990 * 31034 +30407 - 16480 +5876 + 18304 +3713 * 5911 +((26420 + 4723 - 17890 - 6814) - 19021 + 10463) +1395 + 30824 +(13891 * 341 * 13367 * 27070) +8914 - 1677 +7034 - 5548 +(3754 * 1159 + 15100 + 32524) +21354 - 12835 +21560 - 8920 +6262 + 20089 +379 * 29399 +11736 * 27042 +30219 + 14339 +4138 - 10187 +29207 - 32416 +(25982 + 25962 - 30627 * 5324) +16005 + 31010 +24319 - 740 +19720 * 28224 +18936 + 29691 +2494 + 28354 +25636 + 16114 +28333 * 12901 +(21956 * 23442 + (13938 - 9454 - (9683 + 8397 * 13599 * 28805))) +25290 * 19845 +28503 + 21821 +18658 * 7450 +26007 - 9480 +14123 * 14603 +3672 + 9438 +1472 * 14278 +4711 + 2060 +((29119 + 24420 + 14603 + 24520) * 3439 - 23449) +(1769 / 2984 + 30329 + 20585) +6194 * 10318 +(32447 + 907 - 921 * 3109) +(29202 - 20957 + 26592 * 7269) +7717 - 2255 +31538 * 32529 +21160 * 11463 +12946 / 1808 +25644 * 18595 +31436 + 11630 +1734 * 11850 +31648 + 12590 +27675 - 32208 +2707 - 23831 +(12856 * 12355 + ((11463 - 1124 - 2978 - 26065) - 25561 - 22510)) +3605 * 9236 +23678 - 3866 +27592 - 4775 +(((12162 + 8256 * 24484 / 10012) - ((24824 * 12191 / (16008 - 8921 * 23638 - 9414)) - ((19901 / 7673 - (16640 + 5871 - (26745 - 11737 - 16570 + 28866))) + (743 * 17030 - 19661 * 14156)))) - ((((14357 + 2644 + 23544 + 28110) * 30475 + 28368) * (11909 * 12959 + 29050 / 6872)) - 26833 + 3769)) +12131 + 7756 +23180 - 6135 +15748 - 11788 +10800 + 28786 +22645 - 10376 +23758 - 14879 +((15564 - 14102 + 14508 + 23759) + 19949 + 24092) +30003 + 8529 +(19801 - 17011 * (1352 * 8847 * ((9172 - 17042 - (24537 * 32268 + (20055 * 31670 / 9938 / 14061))) / 11467 * 11416))) +(13321 - 10798 + 26475 + 10312) +(7259 + 25183 + (7583 - 18361 * 12842 + 31391)) +20671 / 21917 +1326 + 685 +1416 - 21650 +31684 * 30085 +(6675 * 1386 + 6387 - 4261) +17791 * 30253 +10059 + 21683 +19325 + 18012 +27254 + 21453 +(680 - 30405 * 8028 * 30608) +18042 + 10130 +9127 - 11224 +17640 - 22424 +18874 + 11852 +14819 * 9840 +(18385 - 31781 * (17711 + 27905 + 25018 * 24290)) +26332 + 9908 +14733 / 29828 +22818 + 8635 +5155 + 4743 +5566 * 1721 +(8226 * 25133 + 10883 * 27196) +19295 - 28070 +31968 - 6144 +922 + 24147 +23128 * 1862 +24018 - 17076 +(14766 - 18570 * 945 * 31994) +(13382 * 28230 - 3807 + 11906) +4505 * 15455 +(6391 - 6408 + 3976 + 3542) +2624 + 6248 +(23749 * 11027 * 28215 + 11039) +24613 * 29351 +28999 - 20906 +4452 * 1516 +8771 + 5893 +(5510 - 11148 - (28563 - 28963 * 32279 * 24874)) +6292 + 30436 +1236 * 18479 +22359 + 12402 +14289 / 27067 +31245 * 22323 +(26053 + 32613 - 30823 * 17394) +(757 * 5160 - 11920 + 4230) +(20638 - 2087 * 32429 - 14336) +2448 * 23047 +(9870 * 2098 - 16527 * 18414) +15920 * 3598 +11861 * 2870 +(28604 / 22420 - 3719 - 9279) +(18308 + 29523 * 12963 + 1854) +9752 - 9698 +1662 - 14779 +(7923 - 29747 - 29712 - 9059) +(((25464 * 30949 + (24046 - 27661 + 32735 - 12928)) + ((29361 * 23072 * 9599 * 27457) * 10649 * 25981)) * 12791 + 26510) +28644 - 18018 +22534 - 9703 +(17791 + 20253 + (4244 + 23445 * (7302 + 4614 * 25783 * 23310))) +26091 + 19532 +(30560 + 13102 / (4003 - 21662 - 4453 - 9072)) +29539 * 21126 +((22782 - 8832 + 14616 + 11824) - 27565 + 14556) +12170 + 28807 +4363 + 25192 +9187 + 9258 +(801 * 16834 - 29208 + 25882) +8877 * 28151 +(((8455 + 14509 * 25477 * 32692) + (16824 * 986 - 5267 * 30455)) / (1237 * 17612 * ((16411 / 14033 + 19349 - 29760) - (31745 * 61 - 13973 - 31274)))) +6018 * 18847 +(24129 - 22429 - 9599 + 3130) +(27109 + 21040 + 30547 - 11835) +30455 / 23638 +8239 + 28288 +12702 - 26656 +(15255 / 3041 - 5196 * 26781) +(16849 - 24048 * 24725 / 31807) +(12487 / 15351 + (3277 + 7584 - 24858 * 4831)) +(17081 + 29014 - 18368 + 29642) +21575 * 10820 +(29178 - 5682 - ((30942 * 6433 * 5188 - 1336) + 4512 + 27561)) +14770 + 26760 +((((1207 / 20900 - 21848 - 15854) / 7555 * 17429) * ((2224 + 4555 - 29121 * 19280) * 32440 * 6106)) * 23301 - 17991) +23856 / 6915 +(6597 + 3998 - 21869 - 14924) +(((10832 + 10408 * (31141 - 29299 * 3727 * 4288)) - 20539 - 13086) - ((27690 - 28667 - 1341 + 29929) + 20034 + 16505)) +1941 + 30073 +3542 + 20859 +(24795 + 20869 - 29091 - 29485) +545 + 11162 +(21434 + 10415 - 32746 * 21961) +19620 - 20964 +2938 - 27815 +27383 + 29823 +(9573 * 16257 * 27840 + 8998) +32375 - 3792 +22689 - 7382 +2451 * 3291 +1652 + 5356 +(((12252 + 1154 - 30539 / 16183) * 4725 + 27561) - 31151 * 28003) +(8417 - 26015 + (17178 + 26886 + 32181 - 20675)) +31314 * 23301 +27021 - 8268 +((17957 / 1029 * (32523 + 25730 + 9217 + 31409)) + ((8663 + 4696 * 26526 + 11299) - 5965 - 1620)) +20910 + 27118 +((16147 - 23344 - 25906 * 21202) / 31159 + 15975) +(19567 + 1535 * (((22346 * 18098 - ((9289 + 19350 - 2691 - 1307) + ((25122 - 2331 * 19932 - 13700) + 26074 + 28104))) - 28703 + 23943) - 25818 + 19713)) +((16026 - 20807 - (3893 * 2153 - 27936 + 27292)) - 2452 + 9716) +21829 + 5730 +27556 - 16069 +30301 / 6558 +(1868 * 11830 * 9884 + 19965) +15764 + 30337 +((((6443 - 15880 * 14370 + 18577) + 22887 - 27607) * 4587 - 30862) - 31875 + 10815) +14015 + 25020 +18937 - 19408 +3106 - 30394 +23400 * 27281 +5860 - 2148 +17439 * 28431 +8048 * 2452 +8461 - 27649 +(23685 - 13624 + 18854 + 27318) +23409 / 15322 +(16681 / 6275 - 30024 + 12738) +28617 - 13930 +16734 - 6405 +13788 - 14966 +24042 - 25728 +(5017 * 26065 + (21022 / 28394 - 24512 - 30620)) +2022 + 11855 +17582 * 19281 +7009 / 26350 +6661 - 872 +25648 + 10178 +((30145 + 30986 + 7231 * 701) * 4392 - 10696) +5642 - 24156 +(6407 * 13706 + 27434 + 9202) +7945 - 20048 +17773 / 24324 +27041 - 6120 +2307 + 16919 +(30678 - 1661 - 10864 * 7038) +21283 - 11568 +28741 / 22694 +14204 + 18128 +32463 * 15422 +22488 - 20904 +12687 * 29054 +(19367 - 5462 - 19313 * 12634) +10535 - 29256 +21507 - 1244 +32645 * 14775 +26907 - 5008 +(16682 * 20549 + (25918 / 20801 + ((32062 - 8998 + 10904 * 5081) * 29731 / 22268))) +17457 * 8056 +22216 * 23641 +16519 + 24274 +(11247 * 19877 - 9339 + 28807) +22763 + 24365 +4141 - 20874 +12030 * 26350 +16798 * 106 +4601 - 12042 +16923 * 27158 +27397 / 15474 +(3840 - 2628 * 24691 - 19322) +13925 * 7768 +17513 / 30068 +(18802 - 19187 - (21443 * 28092 * 5414 * 7097)) +30588 + 16775 +(3467 - 20472 + 9846 * 7145) +(989 - 25129 * 8704 - 32653) +20538 + 15643 +18949 + 25297 +((115 + 26433 + 13788 - 27775) + 3653 - 15208) +32241 + 12508 +20215 - 30195 +(31898 + 19373 + 1182 * 14227) +12777 + 25143 +24728 - 5352 +661 + 17450 +15844 / 743 +25563 * 25470 +(31602 - 23972 + 6525 + 12388) +(11716 + 31527 - 8591 - 25444) +18391 * 7425 +28206 * 22269 +28815 - 6744 +26367 + 31916 +26443 - 17493 +27319 + 15903 +2620 * 26243 +30807 / 9762 +(9563 * 31666 - 10029 - 3103) +21245 * 2143 +26969 / 24559 +10658 * 11462 +((29079 + 1233 * ((6753 / 20002 * 17045 - 30550) - 4304 + 8404)) / (6431 - 25986 - 21270 * 14849)) +32703 * 411 +(25632 - 20677 / 23112 + 22868) +13934 + 5911 +(21250 / 20988 * (7531 + 13078 + 32584 * 13704)) +11202 + 24933 +28638 + 6394 +(3301 * 19826 * 20374 * 5087) +7007 - 18430 +9061 * 22751 +2130 + 15275 +22627 * 30660 +16525 - 20662 +2880 * 18005 +16667 + 13741 +8530 * 28675 +(26057 + 14427 * 13459 + 16475) +22818 + 3216 +10326 + 4797 +5988 - 28668 +7959 + 30949 +4348 * 327 +(23425 * 4092 - ((11099 + 14891 - 20375 + 22101) * 25714 * 22494)) +8562 * 9006 +17944 + 21543 +21720 * 11007 +9466 + 24433 +(14712 + 16231 - 10262 - 8054) +14038 - 4378 +25427 - 20784 +((27218 - 22232 + 27348 + 2372) + 31751 - 30298) +5129 * 17845 +31688 - 1397 +15413 + 10810 +((28317 + 12623 + 6676 - 18085) * 18990 * 12120) +26160 - 14276 +(25289 * 16654 + 11214 + 14095) +(15576 - 13537 - (24341 - 7075 + 2707 * 2646)) +19396 + 6365 +(9740 * 4113 - 30670 - 9474) +(18737 * 27654 * 31478 / 22486) +2349 - 5957 +1665 + 20459 +8215 * 5344 +32728 * 1635 +(20095 * 1855 * 19593 + 25932) +((8635 + 3768 + (2696 * 23403 - 3127 - 26515)) - 28738 - 21716) +24220 / 9049 +21183 / 504 +(16127 + 13119 + 26628 + 2904) +((31065 * 20106 * 28427 * 31345) + 12805 + 10875) +14987 + 12574 +(16922 + 787 + 22393 * 16909) +4745 + 24561 +16150 * 15271 +5855 * 31287 +30211 + 16250 +32193 - 3813 +3658 - 2457 +15729 + 32150 +18979 * 24269 +16009 - 514 +(10130 - 33 * 25021 - 15104) +9112 * 17378 +20647 + 30021 +16402 - 13411 +28988 * 23444 +3610 + 14871 +15659 - 21924 +9755 - 26246 +(25755 * 26094 - 23488 + 28086) +(((26915 - 32728 * 7161 * 330) / (10202 * 25070 * (24914 - 8745 - 14103 * 25923))) * 26349 * 22757) +25222 - 12381 +21920 - 29223 +6394 - 19524 +19446 - 7287 +22686 * 24146 +10700 / 1642 +17145 - 29543 +27498 - 23622 +23658 - 26618 +((12232 + 23615 + 56 * 31351) * 9799 / 28047) +30981 / 29182 +19155 - 25288 +15298 + 27923 +17254 + 20724 +723 + 15443 +903 + 17401 +9793 - 32155 +14438 - 6950 +6076 - 13140 +15272 * 1781 +(((7947 * 23885 * ((14215 * 22118 - 23247 * 23) - (11947 - 15294 / ((12098 - 9007 / 31529 * 12652) - 25738 + 4206)))) + 8670 - 516) * 26667 / 11467) +10253 - 19742 +1823 + 18319 +22486 - 14947 +16765 + 31012 +22359 * 18665 +(29728 - 28069 - 10470 * 737) +(27728 * 8065 * (24368 - 26526 - 21151 - 8577)) +(13873 - 30207 / 15219 - 16553) +(30946 * 16718 + 31310 + 10442) +32320 + 27738 +31497 * 10871 +24797 * 972 +26499 * 8016 +(25496 - 30574 - 8409 * 4136) +8009 * 21391 +30554 - 32477 +(21972 - 9892 * (26481 * 6320 * 3462 - 16204)) +805 * 19726 +11791 * 29541 +19399 * 11261 +24062 + 26626 +(20864 + 29049 * 29489 - 23139) +6120 + 9264 +(2319 * 18936 + 8402 * 19063) +(20415 + 26602 - 15129 * 8458) +18266 + 30882 +(31650 + 30782 + 29260 - 6537) +6333 * 9423 +9920 - 25332 +12450 / 20856 +29245 + 17069 +(25545 * 1378 - 13479 - 22775) +16182 - 31902 +23511 * 30214 +13798 - 7992 +5747 + 5274 +15121 / 1386 +((5283 + 21505 + ((20785 + 29886 + (24374 - 1519 - 9005 - 7783)) * 21004 - 24281)) * 18073 - 12673) +11551 + 4780 +26766 / 3005 +8636 + 7868 +6775 + 200 +8363 / 14187 +3479 / 7547 +(31779 + 11211 - ((6649 - 11104 * 24701 - 17842) - 11228 + 20366)) +5860 * 28659 +32021 - 2863 +11690 / 24263 +(22867 / 30937 * (13179 - 13719 * 12977 * 5978)) +24138 - 16442 +((22209 - 31181 - 16859 - 27427) + 10441 + 7710) +(4835 / 30512 * 15346 * 24753) +15421 - 10623 +13 * 13182 +(25792 - 26141 + (14326 + 11755 + 4027 - 3872)) +22083 * 4556 +7977 * 5384 +(16756 + 20095 + 15498 - 19583) +27401 + 31588 +24801 - 15331 +17642 - 26601 +25265 + 14996 +10677 - 28694 +((((5992 - 27329 * 7708 * 27635) + 23776 - 6418) + 24626 - 28878) + 32112 * 13153) +16413 * 12275 +761 * 2100 +3416 * 7003 +(6102 + 25397 + 13814 * 31539) +6085 - 505 +13613 * 30317 +(29075 + 3227 + (7403 * 12413 * 20192 - 23560)) +24856 * 10986 +(7470 * 5511 + 23443 / 3818) +6572 - 8755 +31088 * 6793 +29921 + 11607 +31783 * 3684 +19150 - 21275 +(8707 * 16559 * 31131 + 32027) +11791 + 13074 +(11479 - 25132 * 18528 - 8400) +20864 - 9556 +26226 * 25607 +7068 + 16839 +9956 * 22135 +27416 - 5535 +8940 * 23932 +19008 - 31730 +19678 - 27849 +(29311 * 28453 - 17959 * 1141) +24411 + 25211 +26190 * 8390 +(11087 - 7631 - ((8152 * 11815 - 23396 + 355) * ((23988 + 30035 + 139 - 4096) - 20549 * 16543))) +((104 * 3396 - (17160 - 25866 + 3810 * 282)) - 24615 * 621) +(7584 + 7396 - 17005 - 12464) +28906 / 3755 +(3155 + 22068 - (26320 * 17063 - 20230 - 17560)) +(21067 + 29809 - (5679 - 22081 + 23155 + 28479)) +(28279 / 12239 - 22967 * 10810) +12565 + 11969 +(14146 - 12371 - ((14738 + 7881 * (4555 * 21998 + (28923 - 3996 * (20983 * 31106 * 24451 - 7716)))) * 23350 * 20226)) +(22027 * 8764 + 4608 + 27557) +22941 - 31286 +31404 - 19180 +9393 * 28351 +26478 + 18295 +30471 - 18192 +2973 - 5673 +15979 / 5366 +(25665 - 3136 + (1652 + 5507 - 23111 - 32541)) +23623 - 22940 +11796 * 5338 +24275 * 25518 +(((28763 * 14995 + (29608 * 25052 + 1497 * 7831)) - 26783 + 30403) - 5024 - 26709) +11587 + 18547 +3413 / 10938 +19221 * 639 +(29994 - 12759 - 20921 / 20331) +8436 + 19581 +15600 - 19819 +9327 * 26087 +7660 + 31453 +((9710 + 22194 - 1015 - 3587) * 14499 + 32680) +12640 - 4484 +(14225 - 10682 - 14153 + 15412) +17148 / 9971 +31805 + 11003 +(8921 + 197 * 14773 + 3914) +3628 * 21535 +28985 - 25678 +28983 / 19851 +15490 * 8207 +((20633 - 17873 + 607 - 24859) / 26849 + 9415) +30698 * 7313 +4310 + 23257 +(13973 - 26791 - 13892 - 3129) +29367 + 11542 +25507 * 5240 +25385 * 24460 +12027 * 24957 +(22684 * 8695 - 16949 + 7751) +315 + 8166 +14705 * 29 +((801 - 27116 + 1872 + 2020) + 7919 + 4007) +6907 - 27574 +5244 * 18803 +21189 * 21893 +7058 * 31970 +27671 + 15986 +571 * 3790 +4458 * 32110 +(3000 + 13398 - 16718 + 21092) +538 + 15498 +30593 + 8509 +6546 - 20774 +14655 * 3776 +27782 + 3871 +17492 - 18094 +17373 * 26079 +26127 * 15269 +17332 - 3940 +(4078 + 1995 * 22488 + 13088) +32219 - 30147 +9188 - 8431 +27254 + 2607 +10761 + 3994 +17341 - 24572 +(7023 / 10449 - 19678 / 186) +(((((27948 * 18779 * 3690 / 16552) + 32425 - 27885) - 4123 + 19967) - 25968 + 22377) * (9828 * 10432 - 17746 + 3178)) +25502 - 22754 +(14534 - 3028 + (26251 - 19133 - 7920 * 32105)) +(9466 + 29884 - 28352 * 5093) +32217 - 17504 +27389 - 11141 +(15978 * 29270 / 5880 - 20209) +(14982 - 11002 / 29189 * 26639) +(21770 - 6886 * (20059 * 2925 + 25795 / 29113)) +28817 + 5712 +30122 - 4736 +23519 * 22919 +9582 - 3899 +28189 + 31558 +16101 * 10532 +15414 * 5359 +19080 - 32384 +6310 / 8665 +(23351 / 106 + 19535 + 25992) +32129 - 21165 +(90 - 24994 * 5302 + 3966) +15725 - 8165 +15736 * 7014 +20347 - 23431 +27802 * 18733 +23044 * 31049 +8890 - 23218 +11991 * 6777 +(((2230 - 4131 - 6469 * 31423) - 20111 - 3079) * 23131 + 23678) +(7257 + 1916 + 7891 * 17282) +12729 * 6275 +1307 * 20204 +25228 + 4775 +4084 - 18362 +(17764 * 30289 - 12497 - 24950) +27431 - 26573 +20984 * 4782 +(6348 * 8689 + 13914 - 30898) +11233 - 9048 +20973 - 3951 +32521 - 13209 +8852 - 31182 +20652 - 13426 +6318 * 9000 +3069 * 24763 +20574 + 4561 +5045 * 1820 +29417 + 22195 +14500 / 1739 +16594 - 30372 +(23590 + 22875 + (30482 * 9680 / 32679 - 1961)) +7473 / 14879 +17105 * 1623 +13302 + 3859 +2678 + 26851 +(6391 * 13809 - 25174 / 19266) +28362 / 16430 +20844 - 9651 +8434 + 11693 +(8600 * 13640 + (((16155 - 25816 + 12168 * 25894) + 32548 - 28091) / 3405 + 11642)) +13835 * 8328 +21668 - 14702 +21161 + 7305 +(32018 * 31942 + 26396 * 950) +((3425 - 16437 + (5796 * 23983 * 27046 * 188)) - 26372 - 18981) +7109 * 17340 +3734 + 20641 +10455 * 8215 +(31230 / 24148 - 29476 * 14296) +13743 * 22491 +(15362 - 14579 * 7964 - 20138) +(4696 * 6153 * ((13361 - 27459 / 18022 + 6668) * 5830 * 13395)) +10929 + 27323 +14863 - 26627 +3136 / 4435 +568 + 19054 +11255 - 32133 +226 - 6968 +29585 * 4502 +27900 - 22668 +15091 * 12987 +5913 * 7706 +(19902 * 30789 - 31280 * 13478) +10594 * 12749 +15709 / 4914 +15912 + 23067 +507 - 12817 +14740 - 18218 +3851 - 16415 +(24941 * 733 + 4594 * 22867) +(12844 * 11877 + ((1137 * 10879 / 894 - 17451) + 9342 + 23028)) +15633 + 18759 +7836 * 32261 +(24514 * 20229 * 26743 * 691) +20575 - 3934 +15327 - 17135 +(1732 - 20494 - 27836 * 11331) +(18888 - 14243 * (6177 + 24407 * (32573 * 22970 - 30996 * 28255))) +30954 + 16068 +(5069 - 11096 + 4407 * 2270) +13330 - 29061 +18547 - 23343 +8456 - 12613 +((11613 + 32491 - 24100 + 15805) * 21410 * 22224) +1096 - 23683 +(6826 - 31359 * 2324 + 1420) +31660 - 1715 +(7884 * 14280 + (17553 - 11262 * 21672 * 17950)) +(19114 * 28118 * 28556 / 1902) +14305 + 24377 +22391 + 31031 +12045 / 13402 +1658 + 3917 +9515 - 22 +15124 / 28532 +26500 - 14700 +((1822 + 29342 - 13031 * 17789) - 26532 * 25721) +8522 * 12593 +((30731 + 21237 * 4072 * 9052) * (30633 * 23268 * 20024 + 28775)) +16444 - 23329 +3312 / 1097 +18188 - 22069 +4907 / 19759 +21867 - 6596 +24182 / 32481 +27 + 23148 +13224 / 26944 +(15124 / 18679 - 25047 - 29581) +14379 - 22745 +((((15718 - 2040 - 23257 * 9407) * 18474 + 29779) / (29390 - 24777 / 7341 + 1416)) - 6623 * 1728) +29389 + 30436 +(14841 + 28812 * 26113 * 30746) +10148 - 12417 +(1693 + 13861 - 15385 + 22371) +1337 * 18874 +(1438 * 17006 * 8563 * 4112) +32633 - 2365 +15443 * 12862 +11914 + 2381 +12278 - 16600 +(16845 - 1352 - 857 + 7529) +((27217 + 25276 * 26329 + 5147) + 22435 + 9937) +16900 * 29989 +13940 / 17640 +7419 / 4526 +(10469 * 28015 + 24625 - 6529) +1571 + 15795 +12880 - 26188 +7474 - 6538 +7292 + 30798 +(65 + 18049 * 16717 - 24282) +63 - 7512 +(28401 + 25917 * 25199 + 28776) +15833 - 30365 +16549 / 25977 +(11535 - 14410 + 7358 / 8573) +32334 + 11510 +(16604 * 25315 - 23911 * 13036) +10775 + 5798 +32120 * 28405 +28514 - 7122 +26407 * 27463 +32338 * 12830 +5972 - 10487 +25666 + 6315 +21936 - 22159 +23806 - 30574 +(8394 - 10517 / 26388 + 22505) +((17152 - 20244 - 16288 + 6960) - 758 + 29058) +((30387 + 25050 + ((3024 - 10819 + (14638 * 15637 * 19871 + 14961)) * (15257 + 265 * 29808 * 6530))) * 8088 - 19054) +32251 + 19456 +8046 / 22880 +25468 + 2161 +27795 + 7261 +17211 * 2202 +(25817 + 16974 - 138 - 27576) +27733 + 560 +21419 - 32673 +10544 * 8334 +(13246 + 23019 * (15856 * 6679 * 160 + 14057)) +21865 - 16489 +25564 - 21221 +(2587 - 14926 - (17588 * 16241 * 17859 + 10845)) +933 - 8292 +28811 * 25814 +((9575 - 17017 - 23124 + 7812) * 11442 - 17359) +18144 + 12041 +27427 - 14133 +27557 - 18410 +((23877 + 10648 + 24059 - 23908) / 5751 / 18197) +(13526 - 32020 * (29703 - 31526 * 5178 + 13021)) +26967 * 751 +28030 / 27942 +(((21929 - 9805 * 22833 * 18321) + 12586 * 29646) * 32067 * 13582) +(4354 * 24023 - 9009 + 14281) +13057 + 3289 +(16902 + 3204 + (21839 - 26988 + 13768 - 9550)) +31750 * 22882 +31805 + 18493 +31541 / 2598 +(11691 + 22538 - 30643 + 29208) +11146 * 13997 +10280 - 25403 +20746 - 1252 +10213 - 18516 +(26858 + 19131 - (15108 / 19892 - (26287 * 29815 - 3307 - 4888))) +1254 + 20748 +20136 / 24795 +26182 + 30615 +29896 - 23054 +17020 - 17468 +18106 - 4829 +2995 * 7953 +23014 * 6034 +2470 - 8548 +14157 * 15584 +5738 / 14297 +26647 - 12458 +8172 * 6849 +10874 * 17729 +(24696 - 24630 * 15413 + 4718) +12638 - 11023 +13638 + 13597 +(27955 + 26062 / 29013 + 12141) +(19013 + 27181 / 32398 - 14106) +(4635 - 28868 + ((3204 * 13516 / 7887 - 7151) + 22784 * 20440)) +21597 - 6998 +26165 + 28567 +29657 * 15606 +((1680 - 5793 - ((17013 + 1403 * 2630 + 29853) + 3528 + 28841)) - 28102 * 3137) +18082 - 22967 +28329 + 22507 +8979 + 2173 +15550 / 7158 +25793 + 7987 +(24154 - 20131 - 31365 - 28804) +31318 / 30636 +(26360 * 10880 - 29670 - 5264) +15650 * 27242 +15904 - 9758 +13222 + 28160 +((16475 + 3144 + 30401 + 25541) * (25288 / 30006 + 1148 - 18276)) +21749 + 8370 +12758 - 1302 +(7734 * 18357 + (23170 / 4686 + 2756 * 12976)) +21750 * 19106 +20417 / 27500 +(29596 - 16640 * 12863 / 14849) +15208 + 20445 +1804 * 15471 +((11445 * 20279 + 16889 + 12213) * (22113 * 27028 * 16699 - 14051)) +27959 * 17160 +5130 - 15693 +(31207 - 5868 * 31987 * 31537) +8435 + 23728 +2199 / 30970 +10202 + 17527 +12962 - 15235 +27961 - 18621 +(((8746 / 28919 / 31215 - 28998) * (9477 + 21038 + 29803 * 25409)) + 23761 - 17284) +(3330 * 30098 * 8843 - 24927) +31984 + 1900 +(6147 / 27637 * (23540 * 23791 * 6118 * 14442)) +3933 * 11427 +16797 / 31213 +5720 / 5778 +28513 / 10918 +9380 * 17036 +14521 - 22799 +(12370 + 3552 - ((19997 * 32493 + 24229 + 25558) - (18548 - 19624 + 2779 * 27877))) +((19595 * 1768 * (32518 - 28972 / (24900 - 7582 * ((30248 * 5329 + 391 - 31329) * 12909 + 29241)))) + 9633 / 25292) +17944 + 5632 +21929 * 20949 +1801 * 13614 +22091 - 12267 +(30575 + 28054 + 18106 + 5417) +15652 - 1687 +27074 * 1073 +26114 + 25749 +29977 * 19806 +611 * 20638 +((22341 / 31655 - 11267 * 26714) + 18199 / 10252) +29162 * 32765 +(21495 - 30316 * (17837 + 2761 / ((30866 * 23823 - 2505 + 28978) * 20941 + 27901))) +26593 + 4367 +28515 + 3913 +25023 + 25703 +15490 / 27455 +27162 * 27100 +11695 * 25685 +7217 * 12937 +13668 + 29381 +30003 * 26398 +1847 * 23200 +(78 * 20099 - 12564 * 12776) +20780 - 10925 +(((26184 * 8022 + 4728 * 430) - 11301 - 25729) * 22139 * 13320) +(9905 * 13247 * (21639 + 30860 / 29296 * 5474)) +18647 / 6573 +(2956 / 14862 + (6640 - 31250 - 8519 * 11156)) +12262 * 22954 +5732 - 23787 +8996 - 32109 +30675 - 454 +25140 + 19079 +10337 * 11990 +6820 - 36 +(((8434 - 6753 - (21998 * 28416 * 4262 + 4295)) + 17909 * 2877) * (6540 + 9513 + 22892 - 9431)) +18253 - 18733 +7999 * 24815 +(26140 / 13558 * 28666 - 25969) +28720 + 11953 +1461 / 29955 +5267 / 2843 +(14607 - 9485 - 32319 * 25466) +19850 * 25785 +(4502 * 8912 * 10920 - 12775) +7912 - 15641 +12492 / 23932 +2660 - 14226 +4743 * 9615 +31350 + 26505 +15909 + 32724 +15227 + 2168 +15128 * 29209 +17436 - 23170 +3030 * 12172 +(19833 + 20268 * (14617 + 2645 - 11011 + 17311)) +4785 - 7728 +15082 * 12922 +(16176 / 5284 * 23040 * 25440) +32040 * 23780 +(457 / 6270 + 24182 * 24313) +(6494 * 5255 * 10366 - 11779) +27594 * 17707 +15080 + 26608 +17238 * 14785 +7540 + 3501 +12879 + 23107 +18167 * 31001 +1657 - 14800 +(13542 * 13050 * (22861 - 18314 - (25963 - 28548 / 27869 + 30883))) +21043 + 11702 +8311 + 25976 +(28438 + 8319 + (32477 * 9173 - (17717 * 6763 * 8144 + 26954))) +((31475 + 14701 - 6536 * 10254) + 15634 - 3306) +7284 + 9728 +3999 * 724 +17821 + 16683 +((31600 + 8161 * 11186 * 6514) - 5271 - 16618) +13913 * 3766 +(20487 + 2105 + 29195 - 26531) +(7895 * 10818 - (20296 + 13736 / (32466 - 9308 - 20106 + 19005))) +6988 - 4617 +27042 - 17731 +116 + 23521 +9223 + 30230 +25235 - 20872 +16392 + 25358 +5094 + 9849 +(4758 * 7251 - 27521 + 29518) +25202 - 3763 +2316 / 32730 +23434 + 12222 +14830 + 17854 +5397 / 26363 +10474 + 10039 +15826 / 20845 +27012 * 30502 +(25385 - 22845 - 13522 + 17863) +(11063 - 26054 - (19641 - 10400 * 3254 - 17762)) +26513 + 11425 +15658 * 1997 +(1793 + 6247 - 29671 * 9125) +((6558 + 4710 - 26548 * 13187) - 26944 * 13896) +32496 * 22947 +2412 - 19908 +23971 - 25555 +(32044 + 10546 * 29443 + 12524) +20508 * 21339 +21930 / 28582 +936 - 28501 +11185 + 1513 +(22893 - 30920 - 19497 * 27932) +7116 * 22122 +15909 - 7514 +32229 * 1820 +(13685 + 21395 * 8376 - 14278) +(13 + 10903 - 217 / 536) +29933 * 27172 +19085 / 3009 +27255 + 16546 +(6352 - 11961 * 5538 - 18796) +14838 * 9463 +13606 - 16892 +6382 + 23491 +25235 + 10770 +(321 + 24122 - (21409 - 28647 - 20761 - 7481)) +4280 * 30847 +(6866 - 28557 * 5806 - 28891) +(17175 * 8958 / 16003 + 29432) +29888 * 4991 +(4471 - 4540 * 21017 - 3333) +((1422 + 3414 + 29784 + 12250) - (26939 + 16611 - 5419 - 19632)) +16615 + 5542 +21304 + 566 +13505 * 13682 +(8566 - 1608 - 18377 * 4913) +(19159 + 8229 + 17618 + 25240) +28152 + 29187 +((17930 - 23744 * 3522 + 2526) * 13192 * 17648) +21651 * 12360 +14110 * 20529 +21917 - 14858 +23000 * 10649 +9601 / 30605 +(21644 - 7746 + 2765 + 9296) +4950 - 30010 +1748 - 20432 +(233 * 13364 * 18089 + 13828) +8891 + 20602 +13091 / 12236 +4957 - 5440 +22865 + 29988 +13732 * 27867 +5271 - 26782 +((15004 - 20545 * ((21167 - 11326 - 15258 - 22520) * 29191 + 23696)) - 23996 + 28988) +25842 - 12081 +28380 / 24390 +32744 + 9041 +28081 * 3154 +(25891 * 27046 + 31858 + 20260) +30261 * 29933 +(14437 * 3163 + (10088 + 18577 / (9714 + 17414 + 12638 + 12518))) +27970 * 9229 +9148 * 5518 +9914 / 31357 +2678 + 11173 +2259 - 20909 +(6252 / 9387 + (32368 - 7775 * (23153 + 7616 - 22627 * 6607))) +25178 + 13552 +24137 + 31282 +1527 / 30358 +31391 * 29908 +19560 + 23934 +(((21221 * 19510 + 24196 / 23176) - 4666 - 22537) + (((26795 / 11538 + 22605 - 12586) * 17289 * 2721) * (((31732 + 16905 + (8352 * 24320 - 10285 - 15504)) + 3708 + 19988) + 16505 - 29397))) +6719 / 23933 +((6342 * 7139 / ((1014 * 28484 / 10791 * 29148) + 28529 / 13800)) + 430 + 13080) +31227 + 7000 +23733 + 21415 +29219 / 20810 +24916 + 22581 +(4256 - 2548 + 23881 + 22152) +8872 / 28764 +10532 + 23850 +(21753 * 12611 - 31151 * 3045) +26158 * 27751 +27779 - 27118 +21634 - 5822 +6856 * 17287 +3532 - 6598 +(8967 * 3913 + 22598 - 24983) +((12723 * 6752 + (12765 + 25112 * (8409 - 1253 + (902 * 18179 * 23328 * 23660)))) + (13363 * 10553 * (25109 + 1989 * 23555 - 30578))) +(18368 * 1112 - 13699 / 5896) +25647 + 929 +18596 * 24216 +16790 - 1309 +23722 - 30005 +(9677 * 12850 - (14220 * 10357 - 24189 * 19528)) +12539 * 27303 +(24652 - 9716 + 30005 / 21343) +((((19317 * 25637 - 13967 * 13717) * 24959 + 31628) * ((27393 * 30905 + 24461 * 6523) + ((22579 - 25452 - 24742 * 11089) / 2650 + 4356))) - 11924 + 28699) +230 + 10273 +(((27221 * 9594 + 22962 - 13479) * 26904 * 25070) + 9419 - 20212) +23716 + 22718 +250 * 28258 +(28809 + 9411 - (28143 + 8502 + 2005 - 2178)) +18356 + 23925 +((25996 - 10224 - 15132 * 24670) * 776 * 25835) +15235 * 3405 +22311 + 17739 +3499 * 2213 +(18102 * 16280 + 11252 + 10501) +2326 - 5813 +12356 * 11053 +11771 * 28809 +18883 + 26975 +28407 + 18492 +27223 - 32325 +((7608 - 6297 * 2254 - 6682) * 14707 - 5752) +17252 + 1029 +(14783 * 32250 + 29139 + 32046) +(10451 + 31248 + (5538 - 3617 * (4122 * 8721 - 1658 + 12734))) +4133 - 21066 +(22396 * 21659 - 12325 * 25187) +1197 + 26260 +2326 * 15030 +10969 - 3228 +18439 / 21513 +(7395 + 8824 + ((31913 / 10118 * 22051 + 15069) + 30393 / 17407)) +5162 * 8171 +4752 + 16424 +7310 * 12837 +8040 + 26731 +(28303 * 21569 * (26170 * 8772 - 30257 - 21563)) +7449 + 24614 +18697 + 32622 +(10144 * 18341 + 24501 - 26293) +268 + 17605 +(578 + 18597 / 6601 - 24362) +(25981 - 8403 * 30995 * 86) +21631 + 24191 +397 * 11799 +10923 + 17192 +(3866 - 5054 + 311 - 27476) +((503 + 18309 + 5492 - 14459) + 10523 - 28216) +8533 + 8159 +27102 * 8366 +12856 / 27235 +12821 - 27432 +2581 + 32405 +29673 - 13961 +(8882 * 19568 * 12996 - 3792) +(19332 + 31597 * 5984 - 23743) +3102 - 14126 +31092 * 27274 +25436 + 15628 +13203 - 2358 +22545 - 15448 +4931 - 29790 +(14271 * 2992 - 11760 + 8165) +23729 + 26974 +(6928 * 12864 - 30226 + 31539) +15754 * 22183 +31917 - 20676 +22051 * 27242 +30379 - 3809 +(19901 + 359 + 21820 / 20445) +19217 / 7950 +21344 + 30873 +(32144 + 25340 * 23743 - 4398) +(22674 + 15199 * 26933 + 20724) +9033 * 30419 +13892 + 30411 +15582 / 12066 +20310 - 12983 +16174 / 22185 +25182 - 29883 +7825 - 24291 +2964 / 14439 +(9195 + 1555 + 25873 - 26939) +((11726 - 257 + 32115 - 19308) * (27812 - 21669 + 29128 * 15944)) +946 + 2612 +23626 * 17579 +(29425 * 9255 - 4694 - 19445) +15206 - 28939 +14656 * 19843 +((17361 + 3485 + 9744 + 13248) + 25973 + 760) +(27780 * 10325 * ((14174 * 8234 / 737 * 14303) * ((15974 - 4624 * (13615 + 3107 - 6630 - 10787)) * (19887 + 13745 - 29900 * 19445)))) +28203 - 5684 +12120 - 17399 +13291 - 4041 +29174 - 21778 +20954 * 6580 +25331 - 26094 +(24678 * 16753 - 20799 / 20684) +150 + 9140 +9997 - 6083 +24048 - 19483 +8819 - 4852 +26980 - 23708 +10242 + 21440 +((22718 - 1527 + ((2800 + 30016 + (19881 + 1519 - 859 + 18327)) - 4069 * 17665)) + 14158 + 21774) +30959 + 13359 +7183 - 17073 +(2862 + 27193 * 31622 - 14414) +10898 - 4842 +17930 - 27529 +(15883 + 23760 - 19522 + 30602) +24221 * 16700 +32167 + 5191 +30352 / 17249 +27183 * 26074 +16617 + 27993 +11243 * 30109 +9258 * 15023 +18279 + 13226 +(6330 * 6270 - 19708 * 3607) +(12059 - 1642 + 5313 - 6238) +32649 * 6438 +10426 - 21066 +12050 - 922 +6067 * 23685 +15039 - 11457 +9362 * 24859 +3616 - 22347 +5412 * 12098 +27116 - 3855 +25625 + 26029 +17516 - 30836 +(32322 + 20262 - 14105 * 28939) +((8032 - 29456 - 3737 * 29729) - 18572 * 22338) +16222 + 15374 +(6891 * 15356 * (32582 + 3176 / (16825 + 4403 - (18180 - 5450 - (16404 + 26946 - 19271 / 9197))))) +19944 * 19233 +24888 + 10087 +17867 * 32143 +21306 + 21192 +26650 * 21305 +(3896 + 13267 - ((31504 + 21989 + (27393 + 5684 + 2561 * 31360)) - 7069 + 13710)) +15700 * 14951 +(26699 + 12154 + 3255 - 31662) +(25143 * 25266 * 4996 / 24777) +14564 + 14758 +27174 - 3730 +(26774 - 24713 * 28544 - 28283) +30988 - 12755 +32637 * 12988 +3441 - 20160 +(13779 - 25300 / 27198 - 13892) +19460 * 25470 +16920 * 30512 +32567 - 17126 +7303 * 22947 +28288 + 13309 +(25192 * 27050 - 8263 + 4004) +15557 * 12048 +319 + 22901 +2932 - 26936 +((20447 + 31335 * 13043 * 18083) + 3392 - 431) +(5503 * 12165 - 25172 * 28183) +((20104 - 5525 + 21117 + 4422) + 3239 - 19452) +21480 * 17617 +31874 / 2693 +19758 * 28965 +(20838 + 1191 * (30528 + 19790 * 22391 * 5495)) +966 + 953 +14194 * 25762 +(27189 + 15464 - 21358 * 1365) +17366 - 12790 +15990 + 32582 +(5840 - 10583 + 3425 - 6312) +17420 * 18167 +3028 + 19457 +19789 - 15825 +((17733 - 3548 + 19610 / 22027) + (14273 + 16843 + 12276 + 19225)) +24687 + 27013 +25811 * 11038 +5120 + 26605 +((31358 + 135 - 1859 / 4074) + 31424 + 22162) +4610 + 5245 +(((32047 / 22604 * 10675 * 28498) - 16164 + 23861) / 16903 - 6988) +282 + 27816 +30078 * 32288 +19642 - 32058 +((2499 + 17769 / 10913 / 30330) * 568 * 31950) +15668 + 5206 +((((24616 - 23116 + 2601 + 27735) - 2422 - 5285) - 22046 - 28031) * 24866 + 20929) +24512 * 31524 +22789 * 3783 +3983 * 28175 +((2174 - 25669 + (15848 + 29032 / (3722 + 6784 * 31058 * 16958))) + 32663 - 6311) +8460 - 15972 +22907 + 32559 +13512 * 9839 +12058 * 14584 +15380 + 5349 +25244 * 20373 +(26278 + 2489 + 5379 - 25650) +7299 * 1557 +31334 * 26680 +14621 * 30229 +13487 + 18039 +25944 + 11229 +17659 * 143 +(22975 + 4161 / 25612 + 23679) +23336 * 29946 +(22273 + 19589 / 28816 * 27254) +27958 + 16016 +((18805 * 9809 - ((13796 + 4683 + 18041 - 5823) * 30775 * 23723)) * (4221 * 7653 - (12810 * 25846 * 8406 + 25263))) +8764 + 27272 +19597 / 21591 +4111 + 2193 +9997 - 26207 +4364 + 17272 +28476 + 1924 +(5696 - 23768 - 6037 * 13555) +(1095 * 8182 * (((23635 * 6886 + 17040 - 21062) * ((((5546 / 5974 * (14056 - 20283 - (8969 + 3986 - (19437 * 24154 * 5749 - 7768)))) / (2172 - 32285 * 31238 + 12220)) - 7598 - 9457) - 565 - 16794)) - (21357 + 17589 - 12802 + 30483))) +(27374 * 12487 + 6184 * 9614) +7719 * 5048 +27873 - 21309 +(23603 - 23679 - 24439 * 31068) +(21311 * 9958 * 27939 * 14709) +15934 + 6977 +6081 * 25971 +18366 * 6376 +(22977 * 1504 * 16359 + 492) +3446 + 7500 +(3287 - 8986 * 26437 - 24049) +30692 - 14709 +7421 - 20493 +((19935 + 1852 * 27794 * 10725) - 2547 + 29568) +21725 + 27490 +471 - 6143 +26702 + 29578 +13903 + 25500 +7108 / 8873 +((2807 * 26979 + 31921 * 31545) + (12548 - 12828 - 31895 * 14537)) +13282 - 21134 +5337 * 21878 +3184 * 14029 +31064 + 22853 +5110 - 12346 +14800 + 32354 +339 * 4058 +1269 + 6245 +12510 - 21829 +22367 - 2541 +((5985 + 5057 + 320 - 22043) + (17723 - 20132 - 20884 * 24616)) +(30493 - 20626 + (19517 * 9727 * (16696 - 23156 + 14833 * 31654))) +(8711 * 12397 - 10622 + 14666) +19591 + 24526 +17584 * 14492 +17848 * 14982 +7805 + 26255 +21103 * 15502 +21382 * 8098 +19342 + 14395 +20590 + 3505 +9592 + 15265 +(4161 - 83 + (17426 * 28527 - ((7273 + 24511 / 20252 * 939) + 8630 + 3376))) +((107 - 7852 - 32108 + 18992) - 8031 / 20698) +(28855 + 19065 / 6823 - 13254) +19766 * 26148 +27061 * 31963 +17057 - 10428 +21223 - 9039 +32670 - 13872 +10775 / 4051 +1486 * 4247 +((13314 * 3788 - 29756 - 8896) - 12622 - 10104) +17694 + 19629 +15348 + 7001 +21005 + 29364 +(7455 + 13205 + 28135 / 11601) +17508 + 14190 +31282 * 32162 +(27850 * 21316 - 23003 * 14596) +345 * 31456 +25461 + 25462 +11512 - 3439 +16201 * 24633 +3989 - 11477 +18523 - 19201 +12370 * 29224 +26820 * 16493 +15163 + 28435 +4136 / 30444 +((8246 + 30265 * 17921 - 5429) / 23471 + 23925) +15520 + 20843 +(3036 * 15152 * 4485 + 11176) +(6422 - 23468 - (5825 + 23676 - 11825 - 19496)) +10465 * 25289 +3531 - 20083 +(32438 - 11311 - 17176 + 23524) +26307 - 25422 +22728 - 24370 +20985 * 17980 +24402 * 30306 +20923 * 26682 +30987 - 3964 +12667 + 19337 +12454 + 31419 +19529 + 5595 +21398 - 4556 +(16221 / 29627 + 3533 / 10018) +27455 * 17379 +32577 - 14873 +23284 + 22288 +(7594 * 5825 + 1870 + 21720) +31516 * 20889 +3993 + 3302 +(28859 - 1638 * (25412 + 27987 * 13481 - 4876)) +12283 - 4932 +25682 + 29616 +562 * 13785 +22392 - 32493 +6637 / 9595 +(3760 - 22814 * (6033 * 8286 + 32080 - 15106)) +((480 - 17282 * 3042 * 2164) - 27894 * 1338) +31487 + 18496 +23836 - 19210 +1952 + 25687 +735 * 17183 +12121 + 23948 +29643 * 8863 +10749 + 14685 +31811 * 28684 +11056 - 14504 +(25388 + 29787 + (((11422 * 7939 / 2759 + 3769) * 13828 - 8353) + 25713 * 22550)) +32714 * 23669 +30251 * 19580 +1162 - 27447 +(21928 + 11363 + 25166 + 16472) +(3567 - 23313 + 390 / 8515) +25128 + 22876 +6610 * 12398 +31035 * 9978 +(6449 - 367 / 28813 * 1475) +(11467 - 18403 - 18156 + 27247) +27020 - 2124 +10673 + 5144 +30743 - 21997 +(25628 * 9395 - 5616 / 16180) +27552 - 3320 +(26229 - 18378 - 31302 - 2906) +(6557 * 15554 + 9293 + 10332) +(18687 * 1892 + 27194 * 19224) +29615 * 4772 +(24533 + 21464 + 17652 - 22034) +20658 / 10068 +14389 - 1714 +31366 * 16063 +425 + 26450 +26656 - 182 +24001 - 8026 +117 * 13608 +8631 - 1519 +((27897 + 7149 + ((13960 + 2052 * 19584 - 13554) * ((29752 + 569 - 11220 / 18757) * (7710 / 11624 + 9153 / 24871)))) * 28720 * 26488) +(5477 - 25177 + 13483 - 5344) +20263 + 21847 +29362 + 26030 +(12196 / 6631 - (23311 + 3860 - 15824 - 32478)) +26619 * 21506 +8582 / 12477 +20498 - 16104 +13791 - 21309 +9772 - 6584 +26878 - 16456 +27116 + 23968 +((5054 - 19718 * (25804 * 22782 + 32391 + 7611)) + 32602 + 4130) +15365 + 2361 +5205 * 32072 +6292 * 26362 +7914 * 25073 +11364 * 3013 +((25119 - 17114 * 24982 + 22128) * (11466 + 12772 * 12052 / 30327)) +19189 / 31089 +8272 - 26344 +18009 + 19157 +11923 - 23222 +(8143 + 5148 + 21030 + 26326) +30536 * 15775 +21059 + 24349 +30089 + 16728 +8951 + 13000 +18396 * 2999 +((13611 * 17109 * (((16599 - 28389 * 2996 * 15068) + (30979 + 9658 + 11717 - 14840)) * 9551 + 17294)) * (9316 + 24201 - 28434 - 9933)) +1500 - 14635 +27531 + 14586 +16712 * 27271 +12483 - 28153 +3810 + 29056 +(30112 / 30619 * 25818 * 16693) +1657 * 20668 +8717 - 10350 +3100 * 12889 +(29202 * 19951 / 25124 - 401) +4715 + 16782 +22458 + 16496 +26501 / 30050 +200 / 15658 +13640 - 17033 +13638 * 30355 +2656 / 3555 +23816 * 31065 +27492 - 29273 +15985 - 25634 +(15026 + 2705 - 12311 - 712) +(8796 / 22798 + 12817 / 28647) +(10243 + 30467 * (9248 * 2720 * 20096 * 6211)) +(15528 - 2523 / (13115 * 3307 + (22810 - 584 * 12169 + 7825))) +11845 - 13437 +9944 * 18580 +8078 - 13666 +30222 / 18519 +29181 * 11556 +(14404 * 31692 - 10770 * 7887) +23008 + 11445 +11251 - 22141 +(2979 + 31878 - 30357 + 27465) +10129 - 29123 +(31027 * 12985 / (9164 * 9545 + 24773 - 11681)) +24307 / 895 +7546 - 9807 +16566 - 29743 +((12959 - 3405 - 25333 + 3852) + 28460 - 1731) +27026 / 4366 +(26271 + 6785 - 26679 * 12904) +31899 - 23998 +14838 * 11549 +4130 / 22908 +21330 * 14778 +(20927 * 29805 + ((22053 - 20634 * 29019 - 15258) * 6814 + 1438)) +22762 + 16381 +12359 * 750 +14032 + 13435 +((12802 * 23477 + 8565 * 29444) / 6430 + 71) +4627 - 18536 +31550 - 27685 +14956 * 32692 +20824 - 10225 +25919 + 25986 +(24030 * 5569 / 12824 + 32093) +7742 * 10740 +5140 - 11585 +12539 + 25526 +13116 * 1602 +(4005 - 12292 * 642 * 28478) +32083 * 25730 +26735 - 6255 +16830 + 20712 +(((7886 + 22266 * 29979 - 6288) + ((29606 - 5449 * 1591 - 5293) - 29098 - 14431)) + (19792 * 12188 + 27835 * 29582)) +9228 - 14951 +11901 - 18834 +27356 + 16894 +((22686 - 5707 + 12223 - 11575) * 10346 * 29098) +11360 * 8599 +6194 * 3199 +5780 + 24826 +((17321 - 5072 * 27990 + 16695) + (11198 * 23697 * 915 / 29997)) +((29873 + 24557 * 5698 * 18620) + 29026 - 25265) +1425 + 7825 +((5780 * 3642 * 8421 * 26100) - 3021 * 19681) +(17414 * 20744 / 18344 + 13490) +7941 / 3653 +15084 - 11317 +26352 * 24830 +28104 * 27929 +16895 * 9076 +25088 - 12514 +((15743 - 20746 * 21396 + 11411) - 10835 * 25317) +12656 - 1289 +22649 + 10707 +(27058 + 16846 + 9636 - 27462) +4923 * 22427 +7633 - 22792 +8497 - 856 +(((5441 * 15106 - 18269 + 25329) + (((22602 * 2492 * ((16504 * 19186 * 9431 / 2162) - 4498 + 6939)) + 28924 * 15283) - (11018 * 7590 - 2182 - 30402))) * 29920 - 14753) +(12792 * 32680 + 19515 + 20130) +21435 * 23942 +16375 + 9670 +2155 + 26375 +(22342 + 3082 * 11101 * 5995) +((15895 + 22724 - 29310 + 20876) + 24147 * 15957) +29798 - 32109 +22324 + 18152 +10683 + 14151 +(24382 - 25117 - (1320 - 14701 * 19200 * 29612)) +28108 + 224 +28517 / 24480 +11797 * 22678 +16135 + 8695 +10031 - 17731 +9138 + 14699 +((1753 * 8039 * 6109 - 26077) - (30747 + 23627 + 5492 * 13982)) +15050 * 20274 +4215 - 31996 +((10471 * 12660 - 9930 - 4493) - (14174 - 27553 - 19750 * 4872)) +14431 + 29450 +((25416 + 13287 - ((13922 * 5241 + (29560 - 1666 * 398 * 32144)) - 13521 + 858)) - 14350 + 13432) +28344 + 9424 +(32020 + 14093 * 14982 * 5239) +((1738 * 31950 - 13111 - 25978) + 32285 - 28480) +26000 + 14918 +22530 - 11745 +(17554 + 17534 + 20105 * 8124) +31685 + 31382 +25119 * 19781 +((3952 + 31002 + 10128 + 23754) + 23578 - 13279) +20447 * 3022 +31986 - 15105 +4524 * 11738 +29334 + 6248 +17260 * 3836 +2964 - 10697 +3695 - 25936 +4715 * 32152 +(10025 - 17676 / 14050 / 16344) +(27886 + 12738 + (11544 - 25688 + 30941 + 3297)) +17967 - 5812 +(7734 - 5808 * (1281 - 13007 * (30011 + 15706 + ((2442 * 17223 - 12532 * 17146) + 23674 * 21751)))) +(20406 - 9639 + 31933 - 28755) +30238 - 29210 +4767 * 13887 +(28189 * 17392 - 8400 * 30487) +9555 - 5709 +16224 - 23521 +2389 + 30301 +(12722 - 30954 * ((10421 - 17003 - 7680 - 30466) * 12179 + 28248)) +15609 + 25657 +30874 + 28454 +19962 * 17628 +28235 - 20402 +25257 - 21790 +5093 * 26690 +21532 - 5295 +27874 * 14424 +11242 + 27330 +4759 - 5045 +17460 * 12265 +18343 / 3649 +(1696 * 13733 + (3152 * 22678 - 13408 * 27087)) +20985 + 25624 +9011 - 19261 +30398 / 1165 +(6184 * 29806 - 8106 - 15662) +8957 + 3192 +17004 * 21803 +(15333 * 15430 + 28944 - 19606) +(12883 + 29180 + 18672 - 31936) +24483 + 5565 +28572 * 21796 +(21858 * 26058 - (12205 / 22858 * 26518 * 22575)) +25465 - 10094 +9906 / 28689 +(5890 * 30266 + 17002 - 9199) +7729 - 14537 +15920 - 23464 +8382 + 22154 +24154 * 11511 +32024 - 9735 +25187 / 8580 +((19318 * 12953 - 25290 / 19670) + 27749 - 17059) +(((12317 * 32710 + 3013 - 25701) + (2522 + 15484 - (2766 * 26099 + (15590 * 25325 - 23821 * 32538)))) - (18919 - 29858 / 3932 - 1109)) +29715 - 13118 +((15232 + 27507 + 16673 / 3819) - (23725 * 5347 * 28056 + 15731)) +3227 / 10659 +((7688 - 22473 * 3841 + 20954) * (3354 - 30799 + ((6085 * 2424 - 30335 + 733) - ((19583 - 11506 * 13442 - 8149) - (31914 - 27682 + ((24186 + 11280 + 19332 * 19702) + 10494 - 25378)))))) +6058 - 5107 +(29133 / 9374 - 31182 + 9486) +6559 * 29423 +((24059 + 16001 + 9497 * 20534) / 29651 - 19071) +8390 + 6674 +3869 - 30438 +6155 + 27819 +13727 * 21623 +(((29647 * 25777 - 18207 * 11036) + (1372 * 22029 / 15468 - 25363)) + 19734 + 32710) +904 - 27429 +15792 + 4652 +8376 - 28597 +((26924 * 29644 - 24925 * 18473) + (30043 - 10376 * (9363 + 6014 + 16391 / 7573))) +((29058 - 25992 - 6870 * 25773) + 12967 - 1157) +(17409 - 15107 / 27775 - 11204) +16752 * 13010 +20665 - 3641 +23319 - 17628 +(22362 * 27483 * 9156 + 3724) +(5668 * 20747 - 31786 - 29718) +11681 - 7348 +(12513 - 16237 + 24967 - 27752) +(5624 * 5480 * 26315 / 8894) +10185 - 19521 +25989 * 8812 +((6852 + 14478 * 31554 + 6707) - 11357 * 12522) +9884 * 31243 +(20083 + 1872 - 29365 * 19527) +26524 * 23011 +18287 * 8102 +(14717 * 11301 * 2231 - 20106) +896 / 16380 +23672 + 24481 +6627 * 4101 +22707 * 18159 +10676 + 29040 +((30275 * 13608 * 1577 * 25849) - (((13635 * 26370 - 31615 - 2943) + (27530 + 11306 - 15729 - 6439)) + 7161 + 16065)) +26951 * 2286 +21132 * 29759 +16817 + 11403 +17950 + 12979 +20718 + 11324 +9539 + 25083 +11935 / 3628 +27120 - 7886 +12577 + 13140 +(29605 - 29420 + 15311 + 18718) +(15604 - 24422 + 19537 * 24461) +10706 + 11224 +(5812 * 28780 + 13737 * 6427) +21590 * 22908 +14074 / 24087 +12281 - 27517 +6293 * 13889 +31121 - 31351 +9768 + 32359 +30470 - 8889 +18768 * 27499 +26633 / 4710 +(13431 + 1221 * 3891 + 20320) +29388 + 14413 +2039 + 950 +31820 + 4632 +14245 + 14612 +11551 - 31387 +13290 - 26447 +25575 * 17383 +(18043 * 6382 + 5901 * 5947) +12614 - 8047 +11239 * 13731 +12267 + 21726 +4851 + 29211 +13308 / 7556 +32107 / 23565 +((14624 * 23180 - 10682 - 12645) + 525 * 2143) +11799 + 5362 +28381 - 19872 +((25532 * 1378 - 17614 / 31422) - 9551 + 14379) +20332 * 139 +(22350 + 3014 + 9109 * 3345) +1140 + 12243 +((9941 - 16809 * (((18550 + 12226 + 19595 - 16995) - 20994 * 28461) + 25045 * 17849)) - 22636 - 29181) +26365 - 28896 +31468 + 13644 +12269 - 15713 +17125 - 10005 +(6972 + 659 * 16612 - 16504) +(16150 * 31354 * 26703 - 29347) +(28249 * 2728 * 20139 + 21759) +13018 - 14550 +22519 * 2146 +20365 + 11362 +5951 * 11275 +16731 - 503 +(14073 * 1469 / (5206 * 2561 * 14309 - 11860)) +26519 - 14624 +2446 + 20357 +30396 * 30435 +((29442 + 13662 * (603 + 12577 + (18963 + 17717 + (2950 * 3726 - ((3357 / 16122 - 26703 / 31617) * (4520 - 15335 * 15143 + 30226)))))) * 21201 - 19108) +5883 - 6361 +18038 * 2211 +((9610 + 17782 * 29221 * 32486) + ((10343 - 30769 - 31648 * 30728) / (11485 + 24342 - 11903 * 15143))) +(1081 - 21975 * 25745 * 28066) +20195 * 8403 +32609 + 14593 +12553 - 16258 +28866 + 19230 +25051 - 6351 +31085 - 12035 +20032 / 213 +17425 - 22674 +9646 * 24382 +(31601 / 11644 / 29332 + 7970) +25261 - 11758 +18565 + 28418 +(30007 - 31018 - 13321 + 26482) +30095 / 17696 +(4089 - 16276 * ((16276 - 16601 / 10540 + 32206) + 10133 + 10645)) +(2800 + 3027 - 27177 + 12696) +(206 / 23225 * (30245 * 1858 + 9704 / 10187)) +(3029 * 5997 + (18241 + 29375 * 13653 + 8095)) +(4094 - 24539 + 25146 - 27357) +3904 * 29279 +1239 * 15536 +28374 - 4219 +(8087 / 23559 * (16560 * 4354 - 32632 - 19852)) +(29643 - 15184 + 24788 + 23115) +((21331 + 8358 * 23568 * 31686) + 21716 + 9) +5468 * 32595 +22273 * 32150 +(28407 - 28051 - 7797 - 9888) +13564 - 2503 +29765 - 4709 +26551 - 9202 +(4938 * 4454 * 20863 + 10770) +(3842 + 15429 * 31632 * 13041) +20806 + 28078 +22304 + 17087 +3129 * 5690 +24313 + 15310 +11440 - 18243 +15872 * 13882 +19527 + 27262 +14260 - 23396 +14671 * 30926 +9301 + 16062 +15493 / 28550 +996 - 5195 +20257 - 17686 +(14022 - 1778 + (30167 * 4339 - 3763 * 32445)) +25662 * 22731 +16154 + 6029 +(29701 / 27798 + 31316 - 7731) +16962 * 14640 +(31834 + 28388 + 5367 - 20186) +((24127 * 22059 * (24699 * 13352 - 1241 - 22370)) - (14009 / 29375 - 13750 + 390)) +(11665 - 10436 - (23383 + 16510 + 25313 / 25619)) +23641 + 28920 +11599 - 29180 +5544 - 622 +32630 + 11225 +30075 - 14683 +(23131 + 13532 + (7778 + 13578 * 4086 * 767)) +14114 - 26962 +((((13434 * 20691 + 26472 * 10560) * 15480 + 2377) + 12468 + 16721) - (25746 / 26500 - 19867 * 24812)) +(27684 * 5228 - 11314 / 31746) +((26658 + 18479 * 20186 - 1237) - 23906 * 16159) +6405 * 31692 +20537 + 13427 +9553 + 22619 +3825 + 22836 +30726 + 20712 +(5844 * 17263 * 27730 - 25611) +7330 + 3482 +29759 - 30895 +31684 + 6300 +28991 * 23395 +4520 * 1736 +4384 - 14085 +(24181 * 17811 + 31592 - 26633) +(22906 + 15783 - 16892 - 20915) +(29949 - 29071 + ((16498 / 8926 - 22799 + 13480) + 26302 * 24758)) +32533 - 2689 +21441 + 3662 +(12264 - 23436 / 32125 - 19436) +2661 + 20920 +(12974 * 21607 - 18179 / 16041) +(20538 - 20139 - 3451 - 14044) +896 + 28491 +22014 * 28250 +2942 * 1557 +11982 + 8398 +19091 * 15033 +13706 * 8022 +((18617 + 17307 - 27579 - 10322) / 5238 * 2036) +(((1594 * 25382 - 20986 + 14111) + 4169 * 13056) + 779 * 9334) +20964 - 433 +2506 - 27702 +(21751 * 2053 - 5602 * 31347) +(4240 + 30851 - 14395 - 25261) +(26900 - 22346 - (27048 / 4365 + (24447 + 8146 * 28565 + 17584))) +29631 * 19379 +847 * 23267 +11783 + 32179 +523 - 161 +6567 * 6695 +27251 + 27468 +27532 + 15045 +21905 - 12396 +6694 - 4599 +11988 * 24326 +21673 * 9402 +18450 - 8114 +5207 - 22647 +16568 - 32452 +6841 * 28020 +((4891 + 10084 + 16145 + 5774) + 14433 / 30286) +27161 - 31508 +12162 + 29426 +10720 - 32710 +18925 - 29072 +(13585 + 29975 - 6455 - 1448) +22373 + 17200 +30335 * 3760 +19952 - 29818 +4164 - 16490 +15924 * 7292 +(26028 / 9011 + 20672 - 10555) +24648 + 8651 +(27089 * 22143 / (((27250 + 540 - (12666 - 4678 - (19694 / 10110 + 1888 * 16393))) + (((((1338 + 13490 + 12114 - 18125) + (31872 + 4783 + 20092 + 31558)) / 14236 * 8715) - 4847 + 4234) * (21295 - 21648 - ((10262 / 16321 - (25366 * 27161 - 8350 + 23008)) * 19195 - 12712)))) + ((27527 - 11162 - (26346 - 21958 - 28482 * 30443)) + 18408 + 5396))) +17692 * 8923 +27576 + 5931 +(8102 * 10627 + (21948 + 13211 - 370 + 18860)) +(30623 + 32654 * 19006 - 19170) +19985 * 521 +4819 + 22274 +(9106 + 30043 * (28765 * 14444 - 26594 - 6129)) +((30309 - 29661 + 27720 * 27211) + 2125 + 31965) +7029 - 16295 +5614 - 366 +((13081 * 9672 - (10350 / 27949 - 22056 * 6605)) - (21608 + 10688 * (865 * 13807 - 15666 + 1868))) +1664 - 23597 +21298 - 9139 +13100 * 25938 +17886 - 30154 +19598 - 15080 +8653 * 21187 +(((((14568 * 29304 - (18029 + 19561 + 17413 * 28722)) - 8294 - 1823) - 30079 / 3870) * 16437 + 4113) * 23442 + 1632) +((((6548 - 31989 * (23105 - 5880 * 11296 * 3232)) + (31531 - 22668 - 2233 - 21516)) + 9935 - 4912) / 24115 / 30152) +4173 + 14742 +32540 * 22754 +(11374 - 29455 - 12947 + 18475) +10713 + 32755 +16045 - 17035 +15354 * 15297 +((1892 * 24891 * 2202 - 24648) + 16509 * 19567) +29593 + 20831 +26368 - 32162 +(14725 + 32415 + (((20015 + 29195 - 23520 - 23174) - 10897 + 1889) * 9940 + 14655)) +1814 - 3660 +22208 * 5245 +113 + 6402 +15914 / 8238 +17515 * 10163 +21289 - 30364 +2751 / 28767 +(8172 - 29562 + (12421 / 14041 * ((30028 + 26444 - ((11436 + 26398 - 29328 * 17004) - (23519 * 7975 + (6293 + 25817 + 12432 - 22603)))) + (4313 - 10162 * 5455 * 24513)))) +1035 - 27205 +1332 + 22593 +(28061 + 27098 + 8677 + 22684) +29469 * 20257 +32556 + 27664 +11150 - 27884 +((15707 + 30988 * 7004 * 11530) - 24294 + 30670) +29433 - 23915 +((14680 + 21569 / 26046 * 32598) - 10271 - 20209) +(25158 + 15576 * (12886 - 242 - (20774 + 30940 * 3222 - 4767))) +12016 * 17287 +575 * 31357 +(22475 - 21704 * (6163 * 24733 - 1239 * 30259)) +30126 + 15319 +(13505 - 28561 + ((19701 + 29635 * (26779 / 23996 + 31180 * 4645)) * (8656 + 5792 * 28674 - 32389))) +(21982 + 20295 / ((11722 * 14191 - 17248 * 3451) + 31578 - 11599)) +23904 * 22071 +16430 - 14660 +(3979 * 23792 - (20039 * 14202 * 17399 * 12602)) +29119 - 6218 +25943 + 30733 +10973 / 12534 +(21647 * 25008 * (23991 * 28988 / 5790 * 924)) +((178 + 9364 - 26538 - 23401) - (12671 * 9954 - 888 - 21345)) +(11983 / 24097 - 31095 + 20752) +7916 - 23163 +18497 + 23959 +(22563 + 8292 + 1800 - 3311) +(((((3928 - 24668 / 19279 - 23810) - ((9772 + 9368 + 12136 - 31774) - 22483 * 19397)) + 1625 + 1792) * (20901 - 26455 * (26164 + 23892 * 16301 + 15298))) + 11864 * 15564) +23743 - 4325 +7224 / 31173 +(5319 + 281 + 5132 * 30067) +(14362 + 16316 - 1560 - 15848) +7401 + 15432 +28503 - 29732 +6593 - 4066 +(28554 - 28329 * 8016 + 27305) +13147 + 16293 +17532 * 20654 +(12226 - 2297 * (22982 - 28932 + 4453 - 5828)) +(((32534 - 13428 - 6327 + 31773) * (1720 + 30894 - 30763 * 29194)) / 3112 - 11139) +18594 * 6429 +25459 - 2578 +5521 - 30794 +(10939 * 4405 - 9875 - 28165) +1631 * 29626 +20363 / 9332 +9835 * 4203 +24226 + 21773 +4178 + 27512 +4513 - 15200 +(25848 * 6657 - 30266 * 9525) +(7259 - 9948 + 22667 - 28213) +(24684 * 26711 + 581 * 2236) +31383 - 20107 +15077 / 12566 +27960 * 25427 +(12346 + 24164 * 25660 + 25230) +((((19683 - 27359 - 22392 * 7106) * 32665 - 28661) - ((((5437 + 18432 * 9307 * 5444) + 31245 - 30200) - 24191 + 10648) - 18730 + 21324)) / 13277 + 32397) +1131 - 25737 +1364 + 18412 +((31537 + 7075 * (13779 - 28982 - 2424 - 12510)) - 24961 * 21416) +6672 * 30064 +(28689 * 6887 * 17307 - 20857) +3373 - 1252 +(31739 * 585 * 17494 - 1453) +((3164 - 18781 / 4015 + 18462) + 7241 - 27681) +10946 + 13014 +20887 - 12426 +(23398 * 28599 * 21464 - 25980) +24731 / 31285 +24896 * 9948 +30348 / 16284 +17782 + 2946 +25793 - 22612 +13238 + 15392 +18681 + 11238 +5548 * 29196 +13258 / 16118 +728 * 10377 +13033 + 8834 +24523 * 19964 +(17338 - 1652 * 16587 - 20522) +7895 / 9764 +(22304 / 6191 - 14369 * 10062) +6928 * 13276 +1671 - 27957 +1143 - 21243 +22814 * 5315 +22576 * 21182 +7110 + 28418 +(7285 - 412 * 16409 * 30896) +15663 + 26595 +9654 * 26610 +6078 + 14773 +9951 - 51 +(7663 - 22038 + 19265 - 51) +26957 - 12391 +24946 * 27583 +28194 + 16596 +3843 * 30312 +(9912 * 24562 - ((31824 * 20024 + 27641 * 27500) - 32088 * 31102)) +((11029 - 28383 + ((18333 * 30898 + (10674 * 4442 - 18680 * 26189)) / (16825 + 8334 + 16335 - 31308))) * 29575 - 17796) +4577 * 3457 +21745 + 3751 +16990 - 18085 +22429 * 3230 +(3208 / 16969 + 30388 + 5415) +11506 + 4126 +((23602 + 25140 - 16837 * 18373) * (13719 - 29104 * 30487 + 14075)) +21623 + 10907 +16632 + 31849 +(31495 - 32221 * 10681 * 25022) +11663 / 12553 +29359 - 17199 +27557 - 30586 +7503 - 31189 +21616 / 32078 +16430 + 5188 +9875 - 2933 +9052 + 14670 +24763 * 10693 +19514 / 11825 +5605 / 30487 +17007 - 24420 +7382 + 29041 +25657 * 13258 +(1544 + 727 + 21045 * 11109) +(4366 - 8660 * 26315 - 25138) +6257 + 28680 +7964 - 22644 +18674 - 2419 +(23806 * 524 * 18604 * 11140) +11013 - 11287 +26044 + 8593 +4211 + 27189 +983 - 7236 +537 * 2582 +2125 + 29851 +4955 * 24833 +12269 + 25306 +37 * 973 +6055 + 29919 +(8944 - 1911 + (11972 * 32573 * ((285 * 2243 - 18228 * 14050) - 32340 + 1301))) +(24691 - 9253 + 4957 + 20593) +4606 - 12099 +21931 - 15886 +25817 - 24575 +20174 * 6510 +(11989 * 9189 * (25468 + 28647 - 30112 * 7142)) +2722 + 3856 +24373 - 32745 +25619 * 24556 +21470 * 23622 +5012 - 9371 +27166 * 20977 +(1071 + 5780 + (20236 - 30725 * 17564 * 29374)) +27670 + 11435 +29077 * 32478 +18126 + 8983 +26333 - 9773 +1372 - 14765 +25451 - 19006 +24113 - 5310 +4628 * 32625 +31005 * 20809 +(29732 + 20148 + (23411 / 4658 + (15363 - 31520 * 10774 / 5084))) +10403 + 27527 +((17217 * 25575 - 27423 - 10333) * 20186 * 30056) +6801 * 19318 +25930 * 24173 +17999 * 30537 +25410 * 541 +1914 * 9502 +20825 - 9421 +7640 + 29636 +30525 + 24649 +27739 + 15851 +12979 + 10293 +((8562 + 7419 - 8086 + 22182) + 4073 + 21419) +28300 - 14426 +6659 * 29240 +28384 - 14539 +10804 + 5984 +20668 * 29820 +9705 + 28554 +21721 - 27705 +7394 - 25302 +((8244 + 15802 + 993 * 27845) * (26969 * 3215 / 20017 * 13317)) +162 * 29616 +4797 * 26767 +((499 / 23061 + 4051 / 17323) - ((23978 - 18166 * ((32178 * 9575 - 28565 / 5297) * 20824 + 16971)) + 29840 * 6195)) +(2890 + 21964 - 16936 - 28671) +9394 + 32639 +13012 - 7317 +14074 * 23582 +27974 + 232 +7904 * 23736 +31288 * 14299 +((21902 * 7046 * 6598 - 6318) - 1292 - 1086) +14713 * 26862 +28808 + 27771 +11852 * 20029 +4878 - 25147 +21144 - 21782 +17251 * 766 +28425 + 15923 +12254 - 25106 +((17567 + 21184 + 4734 - 26711) + 20038 * 14501) +4287 - 8374 +13978 * 29094 +12314 - 16329 +20464 * 4857 +5584 - 5423 +8993 + 20977 +12094 * 18746 +21966 * 12798 +28990 * 5515 +(28780 - 21505 + 25425 + 27933) +8332 + 23322 +(2501 - 1693 - 31865 - 21118) +((((29582 * 25616 + 29643 * 12818) / 23719 + 20595) * 15830 + 2343) - 56 * 20334) +25420 - 28084 +248 - 14355 +6151 + 23814 +13298 - 9560 +12282 * 5205 +6935 / 23662 +28475 + 11654 +6873 + 17533 +(14001 * 27769 - 17252 * 25345) +7024 + 32036 +(14534 / 27566 - 334 * 9661) +(31324 + 15254 * 6462 + 10100) +(5897 - 27279 * 12795 + 21684) +20849 * 28952 +26386 / 23506 +18438 * 26249 +1521 + 5279 +3189 * 30088 +(22090 * 15113 + (14500 / 27676 + (30359 * 10469 * 25701 - 22400))) +22301 - 13146 +(13321 * 30711 - 9819 + 25031) +((496 - 17655 / 2719 + 20042) / 5457 - 23475) +22220 + 30937 +27900 * 29068 +(28986 - 25456 - 29593 + 17807) +31557 * 19027 +32568 + 21330 +((27551 - 29679 * 30610 + 13694) - 31498 + 27086) +12484 - 26986 +(4096 + 13498 / (3349 * 12085 + 26844 + 764)) +(29476 * 14296 / 5404 * 32619) +25988 / 14421 +21291 + 20012 +1133 * 28972 +(30347 * 13242 - 2985 * 3976) +22665 + 12741 +10154 * 30928 +(29898 + 9897 + 12654 - 25232) +11073 * 14815 +(10149 + 3640 - 29512 + 31879) +21595 + 28825 +7115 - 24464 +(14937 * 3093 + (18730 - 6700 + (14123 - 19874 * (((19211 + 9839 * (9546 * 1274 + (4517 * 18686 - 9278 * 22396))) + 2094 * 23489) + ((5294 - 4838 * 7985 + 28050) - 11908 + 14491))))) +14432 - 5157 +11405 - 3500 +(32201 + 31569 - (25993 - 32688 * 17220 + 16063)) +29189 - 27853 +31629 + 20030 +5796 * 26312 +10884 * 8995 +20897 / 15795 +10240 + 3975 +((25688 - 3270 * 31805 - 24338) - 6087 / 23095) +28825 - 17289 +1449 * 14976 +1652 * 16303 +18860 - 778 +11360 * 23452 +(17489 - 23289 + 4514 / 22069) +25108 + 4001 +16773 * 9008 +(3689 * 18732 * 15644 + 25524) +11238 * 28579 +23081 - 27389 +3381 * 12646 +28396 * 32271 +7674 + 7603 +18480 * 17108 +28257 / 26761 +16239 + 20319 +4010 + 10020 +32606 + 5877 +6434 + 19342 +20759 * 27187 +(10146 / 13496 * 599 * 11811) +5182 - 18092 +7557 * 6319 +20026 + 7851 +14884 - 30543 +14789 * 30210 +15092 - 16393 +(28019 + 10934 * 23360 - 8746) +2772 + 31799 +20371 * 4692 +900 / 26388 +23238 * 25532 +(23691 + 4736 + 26317 / 3810) +(4316 - 12370 / 28837 + 14938) +10986 + 29390 +(14123 + 27165 - 8607 * 9113) +16407 * 6912 +6869 + 3156 +30342 + 12125 +10747 + 16481 +(21195 + 17407 + 25436 + 28314) +6666 - 5321 +(15502 * 14524 * 18748 * 18169) +32752 * 13328 +25850 * 26850 +23689 + 22999 +(10937 * 20935 * 9063 / 6970) +16748 - 29499 +(11402 * 19226 + 9201 * 18344) +31685 + 23977 +8582 + 18696 +20788 + 1678 +7616 * 11839 +(14211 * 22457 + 25096 * 31583) +32006 * 3991 +6990 - 21485 +30073 * 17955 +21480 + 13648 +20284 + 31418 +13272 - 11898 +11867 - 30698 +17936 + 8256 +7991 * 2066 +27272 + 32052 +(20847 - 29663 - (809 * 27495 * 14498 - 9026)) +17664 - 3305 +((4156 - 5581 - 22978 / 28410) * 2728 - 30427) +(((24965 + 5699 - 8317 - 2673) - 2246 + 17001) * (15099 + 2402 + 25294 * 2844)) +17095 * 19160 +3906 - 8770 +(5208 - 32291 - 13697 / 21203) +(6939 - 23618 * (29241 * 26791 - ((14222 - 16965 * 20793 - 21469) + 16791 + 17373))) +19436 * 32557 +(2880 - 1417 + 9622 - 30466) +(29709 - 1800 * 9104 - 29831) +17714 * 10250 +27931 * 27627 +16136 + 25531 +(8755 - 7273 * 20038 / 5948) +12198 * 16046 +19090 + 3868 +14134 - 14348 +20310 + 10507 +5584 - 9865 +3368 + 10098 +29780 - 14922 +32169 - 6885 +(5267 - 32642 + 6697 * 8539) +18666 - 15684 +31356 / 4896 +22438 * 26253 +30235 + 26518 +5532 * 20642 +(((10014 + 27674 * 20725 - 26264) / 15056 + 23643) - 22909 * 25116) +((10298 - 4742 - (((2532 + 4462 - (24282 * 31874 - 29213 - 19412)) - 20170 * 21550) - 13423 / 9321)) / 19389 * 26004) +4644 - 14689 +(22612 - 20014 - 30707 + 9549) +31340 * 28495 +15285 * 12814 +31358 * 27369 +17196 * 11281 +(((12548 + 25060 + 9723 + 11159) - 31022 - 22504) * 15489 * 31362) +(5046 + 7970 * 471 + 3293) +21575 * 27611 +24068 * 2637 +((1845 - 17270 * 3647 + 29801) / 21782 * 8517) +(14573 / 15093 + (30116 - 16004 * 14796 - 23696)) +27317 * 16795 +20015 * 15045 +6193 * 11835 +(17295 * 18861 / 5103 - 6082) +28771 + 13257 +31755 * 21847 +25820 + 23623 +29571 + 17905 +(26132 - 14691 + 21005 + 10387) +13119 / 30177 +13618 - 15603 +(16869 + 24770 - 4168 * 8153) +16895 + 13494 +(14589 * 11375 + ((26385 - 9129 - 22085 * 19545) - 32259 + 6860)) +30786 + 29563 +22688 * 14253 +5455 * 7487 +24416 * 18421 +23737 + 290 +3868 - 8682 +(8714 - 13151 - 24810 / 11147) +22218 + 22327 +21971 + 17347 +7283 - 1020 +(3061 * 29903 + 32541 - 23120) +10024 * 515 +10162 - 17563 diff --git a/src/subprojects/packcc/benchmark/inputs/json.json b/src/subprojects/packcc/benchmark/inputs/json.json new file mode 100644 index 00000000..ba534605 --- /dev/null +++ b/src/subprojects/packcc/benchmark/inputs/json.json @@ -0,0 +1,9002 @@ +[ + { + "_id": "616eeee5c9331980bba69fd7", + "index": 0, + "guid": "dd7edd5a-8213-4392-8a65-26587da4e267", + "isActive": false, + "balance": "$3,794.91", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "brown", + "name": "Clarice Baird", + "gender": "female", + "company": "POLARIA", + "email": "claricebaird@polaria.com", + "phone": "+1 (808) 557-3724", + "address": "779 Glenwood Road, Brookfield, Alaska, 222", + "about": "Eiusmod commodo dolore eiusmod ea fugiat aliquip ea excepteur nulla velit sint. Enim excepteur ipsum nulla voluptate id ut occaecat adipisicing nostrud est culpa. Minim minim cillum id dolor.\r\n", + "registered": "2014-12-20T06:44:14 -01:00", + "latitude": -5.955038, + "longitude": 141.128292, + "tags": [ + "minim", + "ut", + "dolor", + "dolor", + "et", + "exercitation", + "sint" + ], + "friends": [ + { + "id": 0, + "name": "Isabel Moreno" + }, + { + "id": 1, + "name": "Gina Wise" + }, + { + "id": 2, + "name": "Riley Hobbs" + } + ], + "greeting": "Hello, Clarice Baird! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5d1d8ff24671ed601", + "index": 1, + "guid": "4746c522-3de7-4c7e-b384-3ab41ea9947d", + "isActive": true, + "balance": "$1,455.02", + "picture": "http://placehold.it/32x32", + "age": 20, + "eyeColor": "green", + "name": "Hallie Copeland", + "gender": "female", + "company": "HANDSHAKE", + "email": "halliecopeland@handshake.com", + "phone": "+1 (840) 497-3083", + "address": "762 Lancaster Avenue, Taycheedah, Missouri, 5596", + "about": "Voluptate adipisicing do officia labore sint et mollit occaecat excepteur pariatur. Eiusmod eu nulla laboris elit id elit quis. Lorem consectetur sint cupidatat commodo nisi officia officia irure esse reprehenderit aliqua labore qui aliqua. Elit veniam commodo dolore do ullamco. Culpa fugiat nostrud velit occaecat anim excepteur ipsum.\r\n", + "registered": "2016-10-07T09:12:56 -02:00", + "latitude": -5.300461, + "longitude": -146.509029, + "tags": [ + "eu", + "amet", + "do", + "labore", + "eiusmod", + "ut", + "voluptate" + ], + "friends": [ + { + "id": 0, + "name": "Janis Kim" + }, + { + "id": 1, + "name": "Tanya Riddle" + }, + { + "id": 2, + "name": "Betsy Acevedo" + } + ], + "greeting": "Hello, Hallie Copeland! You have 9 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5ccddcf53eaef3c8e", + "index": 2, + "guid": "c8d038fb-7a95-49e0-87f8-3c11bf802095", + "isActive": true, + "balance": "$1,210.23", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "green", + "name": "Cline Johnston", + "gender": "male", + "company": "ARCTIQ", + "email": "clinejohnston@arctiq.com", + "phone": "+1 (979) 476-3073", + "address": "510 Tilden Avenue, Rodman, Hawaii, 2767", + "about": "Eu cupidatat quis amet proident nostrud. Sunt non id cupidatat aliqua. Anim magna proident dolor et aliqua aliquip ad dolor. Quis deserunt occaecat excepteur nulla nostrud tempor ex minim esse veniam non. Cupidatat veniam sit nostrud Lorem amet.\r\n", + "registered": "2019-08-16T02:49:13 -02:00", + "latitude": 34.306099, + "longitude": 34.55533, + "tags": [ + "quis", + "aute", + "proident", + "est", + "magna", + "ea", + "ipsum" + ], + "friends": [ + { + "id": 0, + "name": "Sally Cohen" + }, + { + "id": 1, + "name": "Mccoy Horton" + }, + { + "id": 2, + "name": "Brittney Sanchez" + } + ], + "greeting": "Hello, Cline Johnston! You have 2 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5d49b6b47a66a7d51", + "index": 3, + "guid": "9285aa3a-2bd1-4b4c-9bd5-c57edc91f25b", + "isActive": false, + "balance": "$2,140.08", + "picture": "http://placehold.it/32x32", + "age": 32, + "eyeColor": "blue", + "name": "Jefferson Melendez", + "gender": "male", + "company": "MANGELICA", + "email": "jeffersonmelendez@mangelica.com", + "phone": "+1 (959) 419-3121", + "address": "134 Schenck Street, Dola, Ohio, 6034", + "about": "Enim fugiat ipsum incididunt ad. Enim incididunt veniam proident magna labore est culpa sunt elit consectetur eu reprehenderit ad. Ad reprehenderit sunt voluptate excepteur. Reprehenderit veniam eiusmod fugiat duis amet id. Ea commodo ut reprehenderit laborum est ad excepteur deserunt culpa est culpa. Nisi nostrud nostrud ipsum laborum eu et cupidatat commodo est nostrud laborum in sint nisi.\r\n", + "registered": "2018-04-22T10:27:57 -02:00", + "latitude": -35.226816, + "longitude": 6.744672, + "tags": [ + "tempor", + "do", + "deserunt", + "ipsum", + "adipisicing", + "elit", + "qui" + ], + "friends": [ + { + "id": 0, + "name": "Ada Newman" + }, + { + "id": 1, + "name": "Sweeney Horn" + }, + { + "id": 2, + "name": "Vang Thornton" + } + ], + "greeting": "Hello, Jefferson Melendez! You have 8 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee51a539522d1f8b2a3", + "index": 4, + "guid": "eee02632-debf-4202-b496-5eec6ee1ae42", + "isActive": true, + "balance": "$3,073.01", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "green", + "name": "Arlene Delgado", + "gender": "female", + "company": "SURELOGIC", + "email": "arlenedelgado@surelogic.com", + "phone": "+1 (951) 471-3144", + "address": "663 Irwin Street, Bowden, Federated States Of Micronesia, 981", + "about": "Culpa cillum et do ipsum reprehenderit reprehenderit cupidatat. Proident incididunt deserunt id quis ex enim occaecat commodo elit sunt ex. Officia pariatur non anim commodo adipisicing anim sint in occaecat. Nulla ullamco consectetur culpa ea est officia occaecat mollit. Fugiat pariatur duis nisi velit ad laborum et sit cillum adipisicing. Excepteur laborum voluptate qui veniam do nisi laboris ullamco commodo. Eu culpa laboris elit eu est elit mollit minim qui ullamco Lorem tempor.\r\n", + "registered": "2016-06-07T09:05:55 -02:00", + "latitude": -77.781086, + "longitude": -70.272973, + "tags": [ + "enim", + "Lorem", + "tempor", + "proident", + "ipsum", + "et", + "commodo" + ], + "friends": [ + { + "id": 0, + "name": "Garrett Salazar" + }, + { + "id": 1, + "name": "Patsy Sheppard" + }, + { + "id": 2, + "name": "Barton Fitzpatrick" + } + ], + "greeting": "Hello, Arlene Delgado! You have 3 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5761c19ca200930c2", + "index": 5, + "guid": "e3173561-c964-4ce3-9031-fef090bf39c7", + "isActive": false, + "balance": "$3,659.57", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "green", + "name": "Juliette Aguilar", + "gender": "female", + "company": "PLASMOS", + "email": "julietteaguilar@plasmos.com", + "phone": "+1 (889) 443-2823", + "address": "302 Oliver Street, Belmont, New Hampshire, 5216", + "about": "Deserunt occaecat commodo ut duis culpa et. Veniam elit enim et quis exercitation amet eiusmod. Incididunt cupidatat id nisi pariatur tempor id aute id aliquip. Nulla anim elit voluptate ea. Sint consequat officia et voluptate id ipsum eiusmod amet anim. Amet consequat aliqua commodo aute. Culpa adipisicing reprehenderit tempor ipsum duis ex elit ex ad exercitation anim ut.\r\n", + "registered": "2017-08-25T01:55:52 -02:00", + "latitude": 57.466829, + "longitude": 61.902854, + "tags": [ + "aute", + "labore", + "velit", + "consequat", + "pariatur", + "ullamco", + "dolore" + ], + "friends": [ + { + "id": 0, + "name": "Wiggins Mosley" + }, + { + "id": 1, + "name": "Estrada Valenzuela" + }, + { + "id": 2, + "name": "Lula Roach" + } + ], + "greeting": "Hello, Juliette Aguilar! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee56d86d12fd8230ffb", + "index": 6, + "guid": "cd6253c9-cec5-466e-a7ce-d98f49e45018", + "isActive": true, + "balance": "$2,268.43", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "green", + "name": "Francis Paul", + "gender": "female", + "company": "CEPRENE", + "email": "francispaul@ceprene.com", + "phone": "+1 (942) 570-3940", + "address": "485 Etna Street, Williamson, Utah, 7895", + "about": "Pariatur Lorem ea occaecat fugiat. Veniam officia commodo et tempor. Officia consectetur commodo ex voluptate pariatur et. Voluptate culpa velit duis in qui laborum nulla proident.\r\n", + "registered": "2020-11-12T06:48:54 -01:00", + "latitude": 17.454265, + "longitude": 8.271245, + "tags": [ + "voluptate", + "tempor", + "ullamco", + "consectetur", + "aliqua", + "enim", + "commodo" + ], + "friends": [ + { + "id": 0, + "name": "Kristine Solis" + }, + { + "id": 1, + "name": "Arline Miles" + }, + { + "id": 2, + "name": "Ruth Stephenson" + } + ], + "greeting": "Hello, Francis Paul! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee59c0477b1dc135828", + "index": 7, + "guid": "c17440f7-4101-4801-93fe-b3ee35a7b8b9", + "isActive": true, + "balance": "$3,147.76", + "picture": "http://placehold.it/32x32", + "age": 26, + "eyeColor": "green", + "name": "Blair Berg", + "gender": "male", + "company": "CIPROMOX", + "email": "blairberg@cipromox.com", + "phone": "+1 (846) 453-2614", + "address": "326 Gardner Avenue, Roy, Pennsylvania, 7209", + "about": "Anim veniam ad consectetur veniam adipisicing id nostrud laboris ex nostrud labore nulla mollit reprehenderit. Voluptate ipsum do proident est nostrud aliquip pariatur. Laboris dolore mollit voluptate et voluptate. Exercitation nostrud id aliquip consequat incididunt. Aliquip minim anim irure minim magna. Do sint ex proident duis in voluptate do mollit consectetur velit dolore.\r\n", + "registered": "2017-06-27T01:49:08 -02:00", + "latitude": -8.431681, + "longitude": -21.257797, + "tags": [ + "ex", + "cupidatat", + "tempor", + "velit", + "minim", + "laboris", + "est" + ], + "friends": [ + { + "id": 0, + "name": "Mcgee Campbell" + }, + { + "id": 1, + "name": "Lucile Sosa" + }, + { + "id": 2, + "name": "Gordon Cain" + } + ], + "greeting": "Hello, Blair Berg! You have 2 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee54acdeaecc644cc02", + "index": 8, + "guid": "74f51de7-67ab-483f-be70-13075a30ae6e", + "isActive": true, + "balance": "$1,045.30", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Bethany Olson", + "gender": "female", + "company": "ANOCHA", + "email": "bethanyolson@anocha.com", + "phone": "+1 (961) 543-3707", + "address": "776 Centre Street, Harmon, North Dakota, 7125", + "about": "Aute ad culpa do laboris labore duis ipsum ullamco. Consectetur est reprehenderit qui id ad irure velit consequat pariatur nostrud ipsum labore duis. Lorem ullamco Lorem nisi ut. Veniam amet laboris ex ullamco ad aliquip minim mollit nostrud consequat laboris dolor. Quis pariatur aliquip non cupidatat duis fugiat non deserunt.\r\n", + "registered": "2017-08-26T01:28:10 -02:00", + "latitude": -71.324721, + "longitude": -152.980103, + "tags": [ + "laboris", + "nisi", + "incididunt", + "proident", + "mollit", + "magna", + "ut" + ], + "friends": [ + { + "id": 0, + "name": "Penny Lloyd" + }, + { + "id": 1, + "name": "Boone Soto" + }, + { + "id": 2, + "name": "Allison Dotson" + } + ], + "greeting": "Hello, Bethany Olson! You have 7 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5ef28786dc61ea595", + "index": 9, + "guid": "becc89d2-4ba6-4526-bafb-d6910f247f41", + "isActive": false, + "balance": "$2,504.46", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "green", + "name": "Hicks Cortez", + "gender": "male", + "company": "ORGANICA", + "email": "hickscortez@organica.com", + "phone": "+1 (880) 498-3909", + "address": "516 Jefferson Avenue, Talpa, Delaware, 8239", + "about": "Veniam do veniam ea ea sit ex nostrud pariatur incididunt laboris. Irure enim nisi quis aute do dolor quis id. Enim dolore nulla proident commodo laboris excepteur.\r\n", + "registered": "2019-12-01T03:57:30 -01:00", + "latitude": -13.629896, + "longitude": 172.978206, + "tags": [ + "amet", + "nulla", + "ex", + "in", + "duis", + "dolore", + "dolor" + ], + "friends": [ + { + "id": 0, + "name": "Willa Mckenzie" + }, + { + "id": 1, + "name": "Clements Mullen" + }, + { + "id": 2, + "name": "Corine Rosario" + } + ], + "greeting": "Hello, Hicks Cortez! You have 9 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee50fc5d292c74321aa", + "index": 10, + "guid": "86305716-9d23-47a5-8fd5-c8eeb7896888", + "isActive": true, + "balance": "$1,801.76", + "picture": "http://placehold.it/32x32", + "age": 20, + "eyeColor": "brown", + "name": "Jensen Mckinney", + "gender": "male", + "company": "TRASOLA", + "email": "jensenmckinney@trasola.com", + "phone": "+1 (989) 586-2257", + "address": "546 Jackson Street, Chalfant, Nevada, 8968", + "about": "Culpa eu dolore deserunt anim Lorem amet excepteur. Ipsum ipsum laborum mollit sunt ullamco voluptate. Irure quis duis incididunt voluptate do duis magna laboris officia voluptate adipisicing dolore. Id anim fugiat dolore amet et. Nulla voluptate amet labore ut qui ea est fugiat voluptate non ea dolore laborum.\r\n", + "registered": "2020-02-25T07:28:01 -01:00", + "latitude": -10.182114, + "longitude": 142.280862, + "tags": [ + "labore", + "aliqua", + "laboris", + "ex", + "do", + "do", + "duis" + ], + "friends": [ + { + "id": 0, + "name": "Wilson Bridges" + }, + { + "id": 1, + "name": "Frankie Kline" + }, + { + "id": 2, + "name": "Carly Hopper" + } + ], + "greeting": "Hello, Jensen Mckinney! You have 7 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee53616c7f4c2287899", + "index": 11, + "guid": "e8ad6c51-2b04-4668-89eb-fac420d5391b", + "isActive": false, + "balance": "$2,258.93", + "picture": "http://placehold.it/32x32", + "age": 20, + "eyeColor": "blue", + "name": "Beulah Mcgowan", + "gender": "female", + "company": "GOGOL", + "email": "beulahmcgowan@gogol.com", + "phone": "+1 (830) 494-2145", + "address": "502 Clinton Avenue, Sunwest, Montana, 6438", + "about": "Minim adipisicing ipsum cupidatat laborum dolor. Aliqua aliquip qui mollit non. Dolor duis nisi ullamco culpa excepteur veniam. Ex ullamco dolore non Lorem qui voluptate id ipsum in cupidatat. Cupidatat aute ipsum minim sint ad. Excepteur pariatur excepteur commodo reprehenderit ex excepteur eu ex laboris veniam ad pariatur. Laborum ullamco ullamco cupidatat commodo.\r\n", + "registered": "2019-01-17T06:37:26 -01:00", + "latitude": -11.197451, + "longitude": -175.656933, + "tags": [ + "do", + "veniam", + "culpa", + "voluptate", + "magna", + "esse", + "esse" + ], + "friends": [ + { + "id": 0, + "name": "Brianna Hebert" + }, + { + "id": 1, + "name": "Deanne Petty" + }, + { + "id": 2, + "name": "Brock Barker" + } + ], + "greeting": "Hello, Beulah Mcgowan! You have 5 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee56d6f4acf1e31553d", + "index": 12, + "guid": "6ce1383e-1afb-43a7-aea7-1dc2821a3220", + "isActive": false, + "balance": "$2,247.57", + "picture": "http://placehold.it/32x32", + "age": 20, + "eyeColor": "brown", + "name": "Johnston Mitchell", + "gender": "male", + "company": "INTERGEEK", + "email": "johnstonmitchell@intergeek.com", + "phone": "+1 (979) 427-2619", + "address": "777 Scott Avenue, Yorklyn, Arizona, 5818", + "about": "Incididunt et irure irure ex Lorem. Dolor amet ad sit exercitation esse aliqua aliquip dolor ex irure nisi fugiat amet. Nisi occaecat pariatur veniam ipsum laboris ullamco duis aute culpa.\r\n", + "registered": "2018-01-05T10:05:41 -01:00", + "latitude": -58.304026, + "longitude": -124.843976, + "tags": [ + "irure", + "proident", + "ullamco", + "culpa", + "voluptate", + "ad", + "et" + ], + "friends": [ + { + "id": 0, + "name": "Fry Barron" + }, + { + "id": 1, + "name": "Wade Wallace" + }, + { + "id": 2, + "name": "Milagros Mann" + } + ], + "greeting": "Hello, Johnston Mitchell! You have 4 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee569fee5e2afcd918a", + "index": 13, + "guid": "92922f2b-a20e-42f1-b725-ee8267fed652", + "isActive": false, + "balance": "$3,977.25", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "brown", + "name": "Barbara Marsh", + "gender": "female", + "company": "GINKLE", + "email": "barbaramarsh@ginkle.com", + "phone": "+1 (813) 599-2377", + "address": "734 Boynton Place, Klondike, Massachusetts, 8432", + "about": "Est eiusmod ea ea occaecat voluptate sunt mollit fugiat minim veniam. Commodo in ea adipisicing mollit excepteur labore ex dolor Lorem aute. Sunt ipsum ipsum Lorem dolore laborum. Ipsum do labore nisi officia ex sint consequat nisi aliquip culpa. Enim ut elit pariatur labore laboris qui ex tempor Lorem amet ea velit amet.\r\n", + "registered": "2019-03-07T06:20:54 -01:00", + "latitude": -17.787105, + "longitude": 56.264694, + "tags": [ + "consequat", + "occaecat", + "eiusmod", + "enim", + "sit", + "magna", + "magna" + ], + "friends": [ + { + "id": 0, + "name": "Wyatt Juarez" + }, + { + "id": 1, + "name": "Jo Houston" + }, + { + "id": 2, + "name": "Macias Wilson" + } + ], + "greeting": "Hello, Barbara Marsh! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5a69f048b040973a3", + "index": 14, + "guid": "3922bd3d-125d-44ad-a3f6-d2a90b57ff12", + "isActive": false, + "balance": "$2,783.09", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "green", + "name": "White Bradshaw", + "gender": "male", + "company": "COLLAIRE", + "email": "whitebradshaw@collaire.com", + "phone": "+1 (868) 457-2491", + "address": "492 Lawn Court, Diaperville, Maryland, 8728", + "about": "Consequat dolor proident elit cupidatat non qui. Laboris enim anim culpa minim velit culpa anim pariatur et in ex sunt. Ea nulla consectetur labore voluptate officia velit in incididunt aliquip est. Cupidatat consectetur voluptate nisi consectetur nostrud aliqua irure elit consequat adipisicing culpa. Fugiat magna pariatur ea non nulla Lorem quis. Excepteur velit ipsum pariatur reprehenderit anim laborum consectetur ut laborum.\r\n", + "registered": "2021-06-13T10:42:46 -02:00", + "latitude": 43.841024, + "longitude": 23.382462, + "tags": [ + "sint", + "ex", + "consectetur", + "nisi", + "ea", + "do", + "laboris" + ], + "friends": [ + { + "id": 0, + "name": "Hilda Rivera" + }, + { + "id": 1, + "name": "Durham Henderson" + }, + { + "id": 2, + "name": "Allyson Villarreal" + } + ], + "greeting": "Hello, White Bradshaw! You have 9 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee52a6ae7743e693925", + "index": 15, + "guid": "84f5d014-ea4c-490f-802f-43b56a836990", + "isActive": false, + "balance": "$3,027.09", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "brown", + "name": "Corina Manning", + "gender": "female", + "company": "COMVENE", + "email": "corinamanning@comvene.com", + "phone": "+1 (968) 407-3561", + "address": "803 Boerum Street, Holtville, Florida, 9083", + "about": "Sint ullamco sint occaecat cupidatat voluptate aliquip ex. In duis labore magna occaecat eu ullamco ipsum quis. Et cillum ea laboris reprehenderit ullamco veniam irure qui dolor sit. Veniam laboris incididunt dolor elit ut consequat sunt consequat. Lorem aute consectetur velit qui Lorem. Officia ipsum voluptate nisi duis incididunt do aute est. Anim est dolore sint occaecat occaecat ipsum ipsum sint cupidatat deserunt labore aliquip.\r\n", + "registered": "2021-02-26T05:17:49 -01:00", + "latitude": -17.963342, + "longitude": 19.421553, + "tags": [ + "adipisicing", + "deserunt", + "id", + "ea", + "occaecat", + "excepteur", + "ipsum" + ], + "friends": [ + { + "id": 0, + "name": "Vilma Wilkins" + }, + { + "id": 1, + "name": "Russo Joyner" + }, + { + "id": 2, + "name": "Angelina Mcknight" + } + ], + "greeting": "Hello, Corina Manning! You have 6 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5a294e3ba90586c0e", + "index": 16, + "guid": "4e38f395-56cc-4296-9c04-8ab8c12ef16c", + "isActive": false, + "balance": "$3,226.52", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "green", + "name": "Cochran Gordon", + "gender": "male", + "company": "OPPORTECH", + "email": "cochrangordon@opportech.com", + "phone": "+1 (919) 554-3842", + "address": "828 Moultrie Street, Harrison, Washington, 6207", + "about": "Aute pariatur quis magna qui voluptate sit irure aliquip ipsum eiusmod veniam ipsum et. Sint minim in cupidatat ea commodo deserunt labore cillum sint commodo consectetur aute. Nostrud sit sint laboris mollit amet excepteur Lorem. Aliquip culpa elit ullamco ex irure. Dolor mollit nostrud ullamco et et commodo excepteur. Nostrud amet excepteur Lorem anim.\r\n", + "registered": "2014-09-18T07:24:45 -02:00", + "latitude": 2.953595, + "longitude": -97.068344, + "tags": [ + "elit", + "cupidatat", + "id", + "fugiat", + "ipsum", + "reprehenderit", + "eiusmod" + ], + "friends": [ + { + "id": 0, + "name": "Josefa Howe" + }, + { + "id": 1, + "name": "Lavonne Cunningham" + }, + { + "id": 2, + "name": "Wendy Bishop" + } + ], + "greeting": "Hello, Cochran Gordon! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5db9e50e59b2091d3", + "index": 17, + "guid": "3c676c90-702c-4a0f-baf3-4b039907c96d", + "isActive": true, + "balance": "$2,671.37", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Ramsey Schneider", + "gender": "male", + "company": "ZAGGLES", + "email": "ramseyschneider@zaggles.com", + "phone": "+1 (908) 555-3356", + "address": "865 Seagate Terrace, Jardine, Virginia, 9062", + "about": "Excepteur proident aliqua sint cupidatat sunt Lorem ad eiusmod consequat ad. Et pariatur est nisi enim amet reprehenderit non anim sit tempor excepteur. Anim qui excepteur labore nisi. Sit amet anim quis nostrud occaecat magna exercitation dolor. Officia irure ad id proident ea ad incididunt laborum cillum sunt aliqua deserunt nisi officia. Lorem veniam magna et culpa do.\r\n", + "registered": "2014-10-24T07:42:27 -02:00", + "latitude": -58.510909, + "longitude": -149.031468, + "tags": [ + "ea", + "veniam", + "minim", + "excepteur", + "reprehenderit", + "quis", + "nulla" + ], + "friends": [ + { + "id": 0, + "name": "Acevedo Whitaker" + }, + { + "id": 1, + "name": "Love William" + }, + { + "id": 2, + "name": "Pauline French" + } + ], + "greeting": "Hello, Ramsey Schneider! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5c9ce2a29759ebba7", + "index": 18, + "guid": "4fe2e4b4-5060-4f26-bdcb-a08b56ac52d1", + "isActive": false, + "balance": "$1,291.53", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "brown", + "name": "Bauer Salas", + "gender": "male", + "company": "HYDROCOM", + "email": "bauersalas@hydrocom.com", + "phone": "+1 (858) 486-2282", + "address": "411 Harwood Place, Groveville, Oklahoma, 5301", + "about": "Officia ut esse non mollit nostrud reprehenderit consectetur adipisicing eu exercitation Lorem. Minim elit aute labore ullamco labore sunt esse quis mollit do. Id fugiat do consectetur mollit ex. Tempor laboris do ipsum irure.\r\n", + "registered": "2017-02-09T12:53:20 -01:00", + "latitude": -39.56287, + "longitude": -34.355224, + "tags": [ + "aliquip", + "consequat", + "elit", + "deserunt", + "ex", + "tempor", + "excepteur" + ], + "friends": [ + { + "id": 0, + "name": "Holmes Bradley" + }, + { + "id": 1, + "name": "Thornton Mercado" + }, + { + "id": 2, + "name": "Latasha Newton" + } + ], + "greeting": "Hello, Bauer Salas! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee51fd77ffeb8c34a15", + "index": 19, + "guid": "a0c3b4e5-fb37-4cd0-988c-6f27eccc7aca", + "isActive": true, + "balance": "$1,114.41", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "blue", + "name": "Cherie Guzman", + "gender": "female", + "company": "KATAKANA", + "email": "cherieguzman@katakana.com", + "phone": "+1 (871) 580-3809", + "address": "564 Banker Street, Advance, Mississippi, 1396", + "about": "Non duis sunt sunt minim incididunt sit proident magna commodo in. Consequat ut id reprehenderit nulla non elit in consequat. Incididunt proident laborum eu eu culpa deserunt aute. Labore proident aute Lorem culpa fugiat do sint veniam occaecat consequat laborum fugiat commodo sint. Id cillum quis duis consequat. Incididunt enim pariatur nostrud culpa ipsum tempor anim eu voluptate ullamco sint cillum.\r\n", + "registered": "2021-08-06T12:53:43 -02:00", + "latitude": 5.34241, + "longitude": -30.290634, + "tags": [ + "cillum", + "et", + "nisi", + "irure", + "qui", + "veniam", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Giles Burch" + }, + { + "id": 1, + "name": "Mcmillan Stone" + }, + { + "id": 2, + "name": "Cantu Clay" + } + ], + "greeting": "Hello, Cherie Guzman! You have 9 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee55d213d8fb8971a0b", + "index": 20, + "guid": "dad3f662-b8c5-4810-80aa-0cee3fc34ad1", + "isActive": false, + "balance": "$3,548.71", + "picture": "http://placehold.it/32x32", + "age": 33, + "eyeColor": "green", + "name": "Benton Luna", + "gender": "male", + "company": "CAPSCREEN", + "email": "bentonluna@capscreen.com", + "phone": "+1 (924) 503-2544", + "address": "154 Hill Street, Zeba, Wisconsin, 1926", + "about": "Fugiat mollit nostrud culpa dolor ut reprehenderit aliquip ea. Qui cupidatat ad laboris labore est do dolor excepteur occaecat esse fugiat. Consectetur sit sit veniam tempor exercitation. Amet sint eu voluptate ex deserunt laboris. Ut non qui qui commodo. Nulla voluptate elit pariatur veniam irure aliqua minim eu sit velit sunt sint quis laborum.\r\n", + "registered": "2018-05-19T07:40:58 -02:00", + "latitude": 61.397626, + "longitude": -65.76991, + "tags": [ + "enim", + "reprehenderit", + "culpa", + "dolore", + "amet", + "commodo", + "occaecat" + ], + "friends": [ + { + "id": 0, + "name": "Finley Elliott" + }, + { + "id": 1, + "name": "Erma Santiago" + }, + { + "id": 2, + "name": "Mcintyre Ford" + } + ], + "greeting": "Hello, Benton Luna! You have 7 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee563ae3239fb9b342b", + "index": 21, + "guid": "ae5a339f-3597-4c1f-8608-1f8c41267376", + "isActive": false, + "balance": "$2,551.88", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "brown", + "name": "Miriam Trevino", + "gender": "female", + "company": "TERAPRENE", + "email": "miriamtrevino@teraprene.com", + "phone": "+1 (976) 521-3741", + "address": "712 National Drive, Bayview, South Dakota, 156", + "about": "Occaecat officia minim reprehenderit exercitation. Aute eu excepteur eiusmod ut laborum. Qui adipisicing magna quis eiusmod.\r\n", + "registered": "2016-07-10T04:48:52 -02:00", + "latitude": 64.72301, + "longitude": 168.577287, + "tags": [ + "ea", + "ullamco", + "magna", + "exercitation", + "enim", + "et", + "aliqua" + ], + "friends": [ + { + "id": 0, + "name": "Good Ruiz" + }, + { + "id": 1, + "name": "Merrill Palmer" + }, + { + "id": 2, + "name": "Herring Gray" + } + ], + "greeting": "Hello, Miriam Trevino! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee55ca2ad181c87c67a", + "index": 22, + "guid": "c29532e9-ab22-4c67-9062-dc92d6c65d63", + "isActive": false, + "balance": "$2,335.23", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "green", + "name": "Rosario Kennedy", + "gender": "female", + "company": "NSPIRE", + "email": "rosariokennedy@nspire.com", + "phone": "+1 (947) 432-2392", + "address": "999 Walker Court, Dowling, Georgia, 5185", + "about": "Deserunt nisi exercitation laboris aliqua velit nisi. Aute consequat ex culpa aliqua et anim do duis. Veniam aliqua id consequat irure quis sunt.\r\n", + "registered": "2016-12-31T05:02:51 -01:00", + "latitude": -73.171515, + "longitude": 102.274378, + "tags": [ + "cupidatat", + "officia", + "ex", + "et", + "fugiat", + "dolore", + "laboris" + ], + "friends": [ + { + "id": 0, + "name": "Jordan Nelson" + }, + { + "id": 1, + "name": "Benita Macias" + }, + { + "id": 2, + "name": "Emerson Guthrie" + } + ], + "greeting": "Hello, Rosario Kennedy! You have 7 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5caffd3a636a08103", + "index": 23, + "guid": "70b8d6cb-5b6f-44fb-ba83-83cd63705314", + "isActive": true, + "balance": "$2,917.43", + "picture": "http://placehold.it/32x32", + "age": 33, + "eyeColor": "green", + "name": "Harriet Cervantes", + "gender": "female", + "company": "RAMEON", + "email": "harrietcervantes@rameon.com", + "phone": "+1 (836) 471-2195", + "address": "189 Irving Place, Bloomington, Connecticut, 6306", + "about": "Ea sunt sint esse cillum dolore excepteur non consectetur ad. Mollit amet dolor sint duis ut consequat tempor culpa commodo aute aliqua. Exercitation consequat velit dolore minim consequat nisi sunt velit enim anim ad. Fugiat Lorem ex non do nulla exercitation dolor quis esse consequat incididunt incididunt mollit. Irure consectetur elit ea quis do labore culpa laboris ullamco nulla exercitation.\r\n", + "registered": "2019-09-08T03:14:11 -02:00", + "latitude": 62.000937, + "longitude": 65.481082, + "tags": [ + "ipsum", + "ullamco", + "nulla", + "id", + "consectetur", + "est", + "amet" + ], + "friends": [ + { + "id": 0, + "name": "Armstrong Byrd" + }, + { + "id": 1, + "name": "Pacheco Pollard" + }, + { + "id": 2, + "name": "Eugenia Petersen" + } + ], + "greeting": "Hello, Harriet Cervantes! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5fec6905076146ea8", + "index": 24, + "guid": "d20b39d6-8e87-4777-845b-f1ed9062cf12", + "isActive": false, + "balance": "$1,720.20", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "blue", + "name": "Alexis Sweet", + "gender": "female", + "company": "VISALIA", + "email": "alexissweet@visalia.com", + "phone": "+1 (872) 556-2882", + "address": "206 Schermerhorn Street, Wintersburg, West Virginia, 6132", + "about": "Aliquip ut id in sint duis aliquip tempor mollit. Labore mollit ea sit aliquip proident aute id proident reprehenderit nulla Lorem non. In culpa in aliquip cillum veniam duis aliquip ad nostrud aute ea. Labore commodo exercitation veniam velit ullamco. Laborum occaecat aliquip ut commodo voluptate deserunt officia deserunt Lorem aute adipisicing magna magna laborum. Irure cupidatat tempor exercitation tempor laboris eiusmod consequat veniam eu esse eiusmod eiusmod.\r\n", + "registered": "2014-05-13T09:28:41 -02:00", + "latitude": 4.011056, + "longitude": 118.205224, + "tags": [ + "et", + "aliquip", + "duis", + "laboris", + "laboris", + "amet", + "amet" + ], + "friends": [ + { + "id": 0, + "name": "Tammie Meyer" + }, + { + "id": 1, + "name": "Roman Mendoza" + }, + { + "id": 2, + "name": "Norris Burt" + } + ], + "greeting": "Hello, Alexis Sweet! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee58ef47bf590026601", + "index": 25, + "guid": "a78eb54a-2335-42a5-870a-8dabf4ea78aa", + "isActive": true, + "balance": "$1,905.58", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "green", + "name": "Beryl Holmes", + "gender": "female", + "company": "FIBRODYNE", + "email": "berylholmes@fibrodyne.com", + "phone": "+1 (901) 489-3595", + "address": "371 Balfour Place, Teasdale, Marshall Islands, 2201", + "about": "Esse cupidatat dolore eu aliqua. Dolor et occaecat incididunt do sint. Sint laborum magna consectetur duis proident nulla irure non ut eiusmod enim esse sit. Velit ad laborum do eu. Reprehenderit non ipsum mollit sint commodo quis voluptate in. Id mollit ullamco consectetur excepteur ex qui dolore dolor aute nostrud velit nostrud amet irure. Laboris magna dolore veniam eiusmod.\r\n", + "registered": "2020-02-19T09:41:48 -01:00", + "latitude": -89.975486, + "longitude": 77.541182, + "tags": [ + "proident", + "occaecat", + "laboris", + "eiusmod", + "quis", + "do", + "et" + ], + "friends": [ + { + "id": 0, + "name": "Bridges Brooks" + }, + { + "id": 1, + "name": "Hannah Shannon" + }, + { + "id": 2, + "name": "Melisa Fletcher" + } + ], + "greeting": "Hello, Beryl Holmes! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee50d4a87fd5ee83247", + "index": 26, + "guid": "dbb21e25-5d8b-40ca-a4f3-7406eb1f59a4", + "isActive": false, + "balance": "$2,275.10", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "green", + "name": "Hampton Garner", + "gender": "male", + "company": "FUTURITY", + "email": "hamptongarner@futurity.com", + "phone": "+1 (897) 569-2980", + "address": "608 Court Street, Kent, Arkansas, 9950", + "about": "Cupidatat esse pariatur non duis tempor esse ea. Laborum aliquip tempor culpa nulla consequat voluptate cupidatat proident do ut do. Et cupidatat ut mollit excepteur ad magna. Ea enim qui exercitation ullamco mollit incididunt eu commodo aliqua eiusmod et amet nisi non.\r\n", + "registered": "2018-08-20T07:51:12 -02:00", + "latitude": -72.371189, + "longitude": -75.08946, + "tags": [ + "nostrud", + "quis", + "esse", + "labore", + "pariatur", + "ea", + "sit" + ], + "friends": [ + { + "id": 0, + "name": "Lucy Fisher" + }, + { + "id": 1, + "name": "Cannon Rivers" + }, + { + "id": 2, + "name": "Lindsey Colon" + } + ], + "greeting": "Hello, Hampton Garner! You have 1 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee511b73484c3e36b18", + "index": 27, + "guid": "04798deb-a874-4132-b377-e09d47632e1c", + "isActive": true, + "balance": "$3,552.43", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "green", + "name": "Celina Johns", + "gender": "female", + "company": "COMTOURS", + "email": "celinajohns@comtours.com", + "phone": "+1 (919) 484-2480", + "address": "883 Ashford Street, Saticoy, Oregon, 4667", + "about": "Ex consectetur nisi tempor anim est dolor est. Sit mollit proident nostrud sint cillum ad nisi consectetur aliquip incididunt nisi ea dolore officia. Fugiat occaecat minim laborum velit eu irure. Qui tempor ut eiusmod laborum cillum proident dolore aliqua laboris commodo exercitation Lorem mollit est. Culpa magna tempor duis cupidatat duis aliquip. Veniam dolor commodo duis laborum quis.\r\n", + "registered": "2017-01-13T09:19:15 -01:00", + "latitude": 26.506106, + "longitude": 166.328553, + "tags": [ + "nisi", + "do", + "culpa", + "Lorem", + "aliquip", + "Lorem", + "adipisicing" + ], + "friends": [ + { + "id": 0, + "name": "Nunez Freeman" + }, + { + "id": 1, + "name": "Coleen Patton" + }, + { + "id": 2, + "name": "Welch Mills" + } + ], + "greeting": "Hello, Celina Johns! You have 6 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5bf048655c2e53328", + "index": 28, + "guid": "02666bb1-80da-4b43-b114-61eea5b291ce", + "isActive": true, + "balance": "$3,233.90", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "brown", + "name": "Hendrix Monroe", + "gender": "male", + "company": "ORBEAN", + "email": "hendrixmonroe@orbean.com", + "phone": "+1 (853) 563-2653", + "address": "618 Quentin Street, Mooresburg, Puerto Rico, 6091", + "about": "Officia adipisicing ex voluptate mollit culpa nisi velit laboris nisi. Et aliqua in mollit velit anim aute labore. Nisi id Lorem do proident duis laboris ea. Id exercitation enim pariatur proident culpa enim exercitation exercitation dolor est ad voluptate. Proident irure reprehenderit consectetur voluptate ea officia excepteur. Aliqua ullamco do in commodo sint magna magna ex sint culpa voluptate cupidatat sit dolor. Qui ut occaecat esse exercitation.\r\n", + "registered": "2020-09-01T11:56:23 -02:00", + "latitude": -78.793525, + "longitude": 114.977976, + "tags": [ + "ipsum", + "aliquip", + "magna", + "dolor", + "veniam", + "tempor", + "laboris" + ], + "friends": [ + { + "id": 0, + "name": "Heather Potter" + }, + { + "id": 1, + "name": "Joanne Rosa" + }, + { + "id": 2, + "name": "Carolina Garrison" + } + ], + "greeting": "Hello, Hendrix Monroe! You have 4 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee54baf7e744e51dad9", + "index": 29, + "guid": "3f9f9d6e-da28-401e-a606-bbf5251ce38d", + "isActive": false, + "balance": "$1,550.72", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "brown", + "name": "Black Reid", + "gender": "male", + "company": "NEUROCELL", + "email": "blackreid@neurocell.com", + "phone": "+1 (910) 525-2563", + "address": "925 Tompkins Place, Vicksburg, Idaho, 1574", + "about": "Magna proident proident sunt duis. Est incididunt sit incididunt ut eu Lorem nisi sint eiusmod esse officia incididunt exercitation enim. Pariatur commodo velit qui ipsum ullamco nulla. Est dolor mollit minim amet aliqua excepteur esse velit nulla aliquip labore fugiat ex ullamco. Aute ipsum sit veniam est minim duis elit dolore sunt nulla sunt.\r\n", + "registered": "2015-12-13T07:16:39 -01:00", + "latitude": -54.537678, + "longitude": 107.957571, + "tags": [ + "aliqua", + "pariatur", + "est", + "nisi", + "adipisicing", + "dolor", + "fugiat" + ], + "friends": [ + { + "id": 0, + "name": "Joyce Lucas" + }, + { + "id": 1, + "name": "Roxanne Pate" + }, + { + "id": 2, + "name": "Winnie Yates" + } + ], + "greeting": "Hello, Black Reid! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5df64007f20643ae7", + "index": 30, + "guid": "64ae68a8-dee2-443a-81db-03a99b63ab84", + "isActive": false, + "balance": "$3,986.64", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "green", + "name": "Mason Pierce", + "gender": "male", + "company": "REMOTION", + "email": "masonpierce@remotion.com", + "phone": "+1 (817) 422-3872", + "address": "760 Melrose Street, Sanborn, New Mexico, 3484", + "about": "Nulla voluptate consequat aliquip excepteur eu. Occaecat irure exercitation quis labore veniam ea enim ullamco esse excepteur labore. Velit est incididunt duis qui et eiusmod nulla sit dolor culpa. Duis velit laboris proident veniam amet dolore exercitation anim. Ipsum cillum pariatur cillum velit. Occaecat occaecat Lorem magna occaecat exercitation dolore sint sint. Excepteur ex sint quis consequat ullamco adipisicing laborum Lorem sunt ea quis non.\r\n", + "registered": "2017-06-05T05:39:46 -02:00", + "latitude": 50.544792, + "longitude": -161.516331, + "tags": [ + "eu", + "ullamco", + "nisi", + "eiusmod", + "enim", + "proident", + "cillum" + ], + "friends": [ + { + "id": 0, + "name": "Alta Benson" + }, + { + "id": 1, + "name": "Blackwell Chapman" + }, + { + "id": 2, + "name": "Herrera Oliver" + } + ], + "greeting": "Hello, Mason Pierce! You have 4 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5b8304aafdd8be1aa", + "index": 31, + "guid": "1f761267-ec0e-4f31-a66a-b984121858a6", + "isActive": false, + "balance": "$2,018.19", + "picture": "http://placehold.it/32x32", + "age": 37, + "eyeColor": "green", + "name": "Madge Sloan", + "gender": "female", + "company": "GALLAXIA", + "email": "madgesloan@gallaxia.com", + "phone": "+1 (849) 456-2573", + "address": "261 Lombardy Street, Gambrills, Minnesota, 5509", + "about": "Aliqua in deserunt ex occaecat. Laboris ullamco Lorem cupidatat incididunt non amet Lorem adipisicing qui labore. Ea et voluptate pariatur excepteur nostrud laboris. Excepteur ad nulla aute nostrud commodo occaecat nostrud tempor cillum in occaecat occaecat et. Voluptate et fugiat voluptate aliquip nisi ea veniam fugiat nulla ut dolore consectetur exercitation. Ea quis et laboris ex amet.\r\n", + "registered": "2018-06-21T11:39:57 -02:00", + "latitude": 1.190471, + "longitude": 41.557569, + "tags": [ + "velit", + "qui", + "dolore", + "amet", + "ipsum", + "duis", + "et" + ], + "friends": [ + { + "id": 0, + "name": "Ware Fuentes" + }, + { + "id": 1, + "name": "Hoover Boone" + }, + { + "id": 2, + "name": "Morse Cline" + } + ], + "greeting": "Hello, Madge Sloan! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee50afe4dcb59b2f31d", + "index": 32, + "guid": "56bc1708-fc97-4b09-b85f-1f51422f9ccc", + "isActive": true, + "balance": "$3,008.31", + "picture": "http://placehold.it/32x32", + "age": 37, + "eyeColor": "brown", + "name": "Phelps Sampson", + "gender": "male", + "company": "GLEAMINK", + "email": "phelpssampson@gleamink.com", + "phone": "+1 (841) 589-2176", + "address": "828 Fleet Place, Belvoir, Iowa, 4957", + "about": "Aliqua exercitation dolor qui laboris exercitation aliqua mollit eu ad dolor tempor. Sint ipsum ipsum cillum commodo elit. Pariatur ad veniam elit pariatur consectetur consectetur cupidatat occaecat ullamco anim deserunt aliqua tempor. Veniam mollit anim ex eiusmod. Consectetur veniam deserunt qui sunt elit.\r\n", + "registered": "2017-10-22T04:09:39 -02:00", + "latitude": 30.261509, + "longitude": -87.056284, + "tags": [ + "officia", + "eiusmod", + "et", + "in", + "laborum", + "proident", + "cillum" + ], + "friends": [ + { + "id": 0, + "name": "Cooley Gilliam" + }, + { + "id": 1, + "name": "Woods Nunez" + }, + { + "id": 2, + "name": "Monroe Fleming" + } + ], + "greeting": "Hello, Phelps Sampson! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee55b63b1ce9129c995", + "index": 33, + "guid": "e18edf1f-256c-41ae-bec0-bb29deb3f2f4", + "isActive": true, + "balance": "$3,927.59", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "brown", + "name": "Dona Bryant", + "gender": "female", + "company": "EBIDCO", + "email": "donabryant@ebidco.com", + "phone": "+1 (918) 432-2629", + "address": "426 Ferris Street, Snyderville, Maine, 6928", + "about": "Do irure consequat aliqua pariatur cillum exercitation est occaecat. Duis qui irure ipsum anim aute. Laborum consequat nostrud id amet. Laboris esse aute cillum veniam commodo incididunt reprehenderit. In nisi Lorem deserunt sint commodo sint minim. Incididunt dolore Lorem est in cillum aute id nostrud anim sit.\r\n", + "registered": "2014-09-27T06:14:41 -02:00", + "latitude": 46.864891, + "longitude": 37.935244, + "tags": [ + "et", + "minim", + "occaecat", + "elit", + "sint", + "occaecat", + "adipisicing" + ], + "friends": [ + { + "id": 0, + "name": "Parks Henson" + }, + { + "id": 1, + "name": "Paige Macdonald" + }, + { + "id": 2, + "name": "Sharlene Holcomb" + } + ], + "greeting": "Hello, Dona Bryant! You have 4 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5cdb24ff15c82ab59", + "index": 34, + "guid": "b2430d4b-b21d-4f3e-8866-7cc7400438a7", + "isActive": false, + "balance": "$3,606.97", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "green", + "name": "James Foreman", + "gender": "female", + "company": "QUINTITY", + "email": "jamesforeman@quintity.com", + "phone": "+1 (941) 440-3649", + "address": "944 Vandalia Avenue, Rosburg, Tennessee, 3115", + "about": "Voluptate velit magna aute qui mollit consectetur. Elit esse enim exercitation incididunt ullamco eu qui. Ipsum deserunt irure commodo duis dolor reprehenderit nulla proident. Esse sit deserunt nisi culpa amet cupidatat minim dolor magna exercitation. Dolor occaecat ea dolor eiusmod ut voluptate. Non excepteur enim do culpa et aliqua aute consectetur cillum mollit minim tempor.\r\n", + "registered": "2020-01-14T07:30:18 -01:00", + "latitude": -79.798076, + "longitude": 174.697346, + "tags": [ + "nulla", + "incididunt", + "et", + "occaecat", + "non", + "amet", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Joanna Peters" + }, + { + "id": 1, + "name": "Santana Stewart" + }, + { + "id": 2, + "name": "Atkins Farmer" + } + ], + "greeting": "Hello, James Foreman! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee535121cb09b60c94b", + "index": 35, + "guid": "888471d3-29bb-46ed-8397-b06ea2b11266", + "isActive": false, + "balance": "$1,190.56", + "picture": "http://placehold.it/32x32", + "age": 37, + "eyeColor": "green", + "name": "Solis Spence", + "gender": "male", + "company": "STEELFAB", + "email": "solisspence@steelfab.com", + "phone": "+1 (830) 527-2151", + "address": "700 Bryant Street, Magnolia, Palau, 1515", + "about": "Sit mollit magna aute ut id eu commodo culpa aliqua consequat. Nisi do aliqua do est Lorem occaecat tempor consequat aliquip eiusmod. Ullamco ad sit anim excepteur irure exercitation sint ipsum culpa consequat fugiat incididunt adipisicing.\r\n", + "registered": "2021-01-11T10:18:43 -01:00", + "latitude": 41.499253, + "longitude": -70.499437, + "tags": [ + "cupidatat", + "ut", + "pariatur", + "ad", + "excepteur", + "dolore", + "eiusmod" + ], + "friends": [ + { + "id": 0, + "name": "Burks Garcia" + }, + { + "id": 1, + "name": "Celia Murray" + }, + { + "id": 2, + "name": "Morgan Griffin" + } + ], + "greeting": "Hello, Solis Spence! You have 6 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee504c87f311e12851b", + "index": 36, + "guid": "b87f4bff-bb35-429d-81fb-81551c141326", + "isActive": true, + "balance": "$1,030.03", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "green", + "name": "Stewart Cox", + "gender": "male", + "company": "APPLIDEC", + "email": "stewartcox@applidec.com", + "phone": "+1 (885) 591-2206", + "address": "495 Wolcott Street, Blanco, Kansas, 6801", + "about": "Consectetur magna nisi sunt aute ut. Labore ipsum dolore incididunt cillum minim pariatur ullamco consectetur consectetur ex amet. Ut esse mollit proident labore. Id incididunt velit ullamco ipsum sit laborum consectetur amet amet sint qui. Sint Lorem voluptate ad in.\r\n", + "registered": "2020-08-14T12:57:19 -02:00", + "latitude": -77.958293, + "longitude": -99.88448, + "tags": [ + "anim", + "est", + "ad", + "amet", + "ipsum", + "aute", + "non" + ], + "friends": [ + { + "id": 0, + "name": "Hawkins Holland" + }, + { + "id": 1, + "name": "Howe Christian" + }, + { + "id": 2, + "name": "Pierce England" + } + ], + "greeting": "Hello, Stewart Cox! You have 3 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee551d05d5e9ea2aea8", + "index": 37, + "guid": "2297d1bc-c3bc-45c0-82c6-58918f377292", + "isActive": true, + "balance": "$3,991.68", + "picture": "http://placehold.it/32x32", + "age": 20, + "eyeColor": "green", + "name": "Scott Carlson", + "gender": "male", + "company": "MEDIFAX", + "email": "scottcarlson@medifax.com", + "phone": "+1 (872) 487-2122", + "address": "861 Maple Avenue, Jenkinsville, American Samoa, 430", + "about": "Nulla eu aute sunt Lorem. Dolore nostrud est culpa cillum id ut non nulla consequat quis adipisicing non amet dolore. Cupidatat consectetur nostrud non magna ex elit duis dolore et ex proident reprehenderit. Cupidatat dolore magna officia consequat sint nisi. Dolor anim minim elit ad velit enim et.\r\n", + "registered": "2016-04-11T02:29:16 -02:00", + "latitude": -57.14206, + "longitude": 166.771713, + "tags": [ + "nisi", + "est", + "nulla", + "amet", + "elit", + "commodo", + "id" + ], + "friends": [ + { + "id": 0, + "name": "Cooper Rodgers" + }, + { + "id": 1, + "name": "Hobbs Lyons" + }, + { + "id": 2, + "name": "Bishop Osborn" + } + ], + "greeting": "Hello, Scott Carlson! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5b0e4061dbb179abe", + "index": 38, + "guid": "07358e1c-d47f-45b6-a27c-562ee0b1da6c", + "isActive": true, + "balance": "$2,060.98", + "picture": "http://placehold.it/32x32", + "age": 20, + "eyeColor": "brown", + "name": "Lorrie Duke", + "gender": "female", + "company": "ERSUM", + "email": "lorrieduke@ersum.com", + "phone": "+1 (908) 470-2882", + "address": "125 Elm Place, Indio, South Carolina, 9794", + "about": "Dolor exercitation dolore excepteur ut labore ipsum anim laboris pariatur consequat ut deserunt. Irure exercitation eu sunt ad ipsum voluptate sint voluptate nostrud et cillum mollit dolore. Sunt eu voluptate consectetur irure laborum mollit tempor. Incididunt dolor cupidatat est cupidatat laborum ex magna cillum reprehenderit. Incididunt laborum ea culpa tempor.\r\n", + "registered": "2018-12-19T03:12:31 -01:00", + "latitude": -51.868334, + "longitude": 168.685644, + "tags": [ + "sit", + "mollit", + "id", + "fugiat", + "est", + "qui", + "eiusmod" + ], + "friends": [ + { + "id": 0, + "name": "Valentine Mcmahon" + }, + { + "id": 1, + "name": "Brenda Moody" + }, + { + "id": 2, + "name": "Isabelle Bauer" + } + ], + "greeting": "Hello, Lorrie Duke! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5f7e7af4f05459329", + "index": 39, + "guid": "1a554877-11db-4475-9587-6fa8d590f2d1", + "isActive": true, + "balance": "$3,266.49", + "picture": "http://placehold.it/32x32", + "age": 32, + "eyeColor": "blue", + "name": "Travis Wagner", + "gender": "male", + "company": "KOFFEE", + "email": "traviswagner@koffee.com", + "phone": "+1 (820) 504-2983", + "address": "395 Garland Court, Sisquoc, Indiana, 4195", + "about": "Excepteur do sint reprehenderit tempor tempor ut ex cupidatat occaecat in. Et amet labore et est. Quis elit aute ullamco deserunt enim elit veniam. Nulla sint qui excepteur esse consectetur.\r\n", + "registered": "2019-10-28T03:57:10 -01:00", + "latitude": -84.379131, + "longitude": -0.742789, + "tags": [ + "adipisicing", + "cillum", + "Lorem", + "sint", + "sunt", + "incididunt", + "est" + ], + "friends": [ + { + "id": 0, + "name": "Baker Lindsay" + }, + { + "id": 1, + "name": "Lambert Crawford" + }, + { + "id": 2, + "name": "Gilliam Garrett" + } + ], + "greeting": "Hello, Travis Wagner! You have 4 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5240ea84b61bc4a76", + "index": 40, + "guid": "c2fdc61e-ba5b-42e8-bc94-204cf93dd757", + "isActive": true, + "balance": "$2,184.82", + "picture": "http://placehold.it/32x32", + "age": 26, + "eyeColor": "blue", + "name": "Buchanan Dillon", + "gender": "male", + "company": "ENDIPINE", + "email": "buchanandillon@endipine.com", + "phone": "+1 (826) 594-2282", + "address": "964 Ruby Street, Wells, District Of Columbia, 2246", + "about": "Aliqua mollit laboris reprehenderit laboris et consectetur amet ullamco pariatur. Laborum tempor enim dolore consectetur excepteur mollit quis voluptate elit. Culpa ad qui magna consequat dolore incididunt cillum magna aliquip duis aliquip cillum irure amet.\r\n", + "registered": "2021-01-06T01:32:39 -01:00", + "latitude": 60.155664, + "longitude": -106.658835, + "tags": [ + "qui", + "nisi", + "excepteur", + "nostrud", + "anim", + "cupidatat", + "fugiat" + ], + "friends": [ + { + "id": 0, + "name": "Mccall Noel" + }, + { + "id": 1, + "name": "Turner Barlow" + }, + { + "id": 2, + "name": "Shannon Carey" + } + ], + "greeting": "Hello, Buchanan Dillon! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5febf6ecbdb248c49", + "index": 41, + "guid": "46b45b3b-ba2f-4d84-bbb9-f06147e5aee4", + "isActive": true, + "balance": "$1,050.75", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "brown", + "name": "Terry Wyatt", + "gender": "female", + "company": "FLOTONIC", + "email": "terrywyatt@flotonic.com", + "phone": "+1 (901) 428-2800", + "address": "785 Sedgwick Place, Hamilton, Wyoming, 6047", + "about": "Sint incididunt aliquip id Lorem consequat enim id incididunt veniam ex nisi culpa. Labore enim elit labore voluptate adipisicing magna excepteur nulla. Ea ea laboris nisi incididunt sunt consectetur minim dolor ea sunt laboris adipisicing. Ad Lorem aute nostrud ullamco pariatur culpa fugiat. Excepteur officia laborum in nulla.\r\n", + "registered": "2021-05-17T07:53:43 -02:00", + "latitude": 21.95598, + "longitude": -49.266936, + "tags": [ + "anim", + "velit", + "sunt", + "est", + "reprehenderit", + "pariatur", + "consequat" + ], + "friends": [ + { + "id": 0, + "name": "Julia Morgan" + }, + { + "id": 1, + "name": "Powell Finch" + }, + { + "id": 2, + "name": "Raquel Norton" + } + ], + "greeting": "Hello, Terry Wyatt! You have 2 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee510bba4e8044c15e4", + "index": 42, + "guid": "c1891db9-927c-4c85-af33-f3d9cb2c656b", + "isActive": true, + "balance": "$3,195.20", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "green", + "name": "Todd Irwin", + "gender": "male", + "company": "QUANTALIA", + "email": "toddirwin@quantalia.com", + "phone": "+1 (838) 520-2586", + "address": "829 Lynch Street, Goldfield, Texas, 1303", + "about": "Irure nisi aliqua excepteur cillum culpa adipisicing tempor esse laborum minim mollit minim Lorem deserunt. Nisi do ullamco ut incididunt in proident reprehenderit irure commodo. Tempor culpa consequat duis pariatur id esse excepteur do pariatur do enim. Excepteur eu adipisicing sit cillum ex minim commodo nostrud. Qui anim quis eu elit in fugiat cupidatat deserunt. Minim adipisicing voluptate adipisicing excepteur ipsum anim. Voluptate aliquip pariatur eiusmod amet exercitation reprehenderit ex aliqua officia velit veniam non id ipsum.\r\n", + "registered": "2015-05-10T01:00:09 -02:00", + "latitude": 1.149855, + "longitude": -74.439245, + "tags": [ + "cupidatat", + "amet", + "nostrud", + "in", + "commodo", + "dolor", + "in" + ], + "friends": [ + { + "id": 0, + "name": "Hensley Stevenson" + }, + { + "id": 1, + "name": "Erna Holden" + }, + { + "id": 2, + "name": "Jeannette Bennett" + } + ], + "greeting": "Hello, Todd Irwin! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee59b75013b263b44c0", + "index": 43, + "guid": "12d2f185-2ae7-4575-b767-e4b97969a9f6", + "isActive": false, + "balance": "$1,926.98", + "picture": "http://placehold.it/32x32", + "age": 34, + "eyeColor": "blue", + "name": "Sosa Greene", + "gender": "male", + "company": "BRAINCLIP", + "email": "sosagreene@brainclip.com", + "phone": "+1 (889) 437-2909", + "address": "853 Moffat Street, Sharon, Rhode Island, 6236", + "about": "Sit non esse cillum laboris duis sit elit excepteur. Nulla occaecat proident voluptate in. Labore proident sint excepteur nisi.\r\n", + "registered": "2015-06-15T01:43:42 -02:00", + "latitude": -79.172877, + "longitude": -118.724698, + "tags": [ + "voluptate", + "mollit", + "labore", + "excepteur", + "Lorem", + "id", + "eu" + ], + "friends": [ + { + "id": 0, + "name": "Charity Hancock" + }, + { + "id": 1, + "name": "Lynnette Rocha" + }, + { + "id": 2, + "name": "Bettye Rice" + } + ], + "greeting": "Hello, Sosa Greene! You have 4 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5d054ad3d3cac9ca3", + "index": 44, + "guid": "19b6577e-ecf0-44e9-a7f8-a5a240f8c1d0", + "isActive": false, + "balance": "$3,612.86", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "brown", + "name": "Phyllis Stanton", + "gender": "female", + "company": "SUPREMIA", + "email": "phyllisstanton@supremia.com", + "phone": "+1 (961) 567-2908", + "address": "978 Prospect Place, Tonopah, Louisiana, 3309", + "about": "Tempor irure velit nisi nisi culpa reprehenderit veniam. Occaecat sit dolore duis qui commodo. Deserunt ipsum cillum aute quis elit proident nostrud ut culpa fugiat dolore veniam duis est. Esse qui anim tempor nisi nulla eu Lorem Lorem non. Qui in ipsum do occaecat. Culpa eiusmod do sit dolor anim do aliqua commodo irure veniam culpa ex.\r\n", + "registered": "2015-02-15T12:19:34 -01:00", + "latitude": 65.254596, + "longitude": -158.948696, + "tags": [ + "occaecat", + "nulla", + "aliquip", + "pariatur", + "adipisicing", + "eiusmod", + "aliqua" + ], + "friends": [ + { + "id": 0, + "name": "Katina Kelley" + }, + { + "id": 1, + "name": "Trina Decker" + }, + { + "id": 2, + "name": "Yesenia Morse" + } + ], + "greeting": "Hello, Phyllis Stanton! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee54a738590c00d6f6c", + "index": 45, + "guid": "6f784ac9-e607-4d54-9825-8917078c9f4d", + "isActive": false, + "balance": "$2,127.03", + "picture": "http://placehold.it/32x32", + "age": 20, + "eyeColor": "brown", + "name": "Earlene Simon", + "gender": "female", + "company": "RECRISYS", + "email": "earlenesimon@recrisys.com", + "phone": "+1 (831) 576-3334", + "address": "513 Willoughby Avenue, Woodburn, Illinois, 8907", + "about": "Eu tempor occaecat occaecat eu excepteur. Nostrud eu quis proident elit elit reprehenderit velit Lorem magna ullamco sunt. Culpa anim sunt qui consectetur dolor aliquip esse sunt ullamco laborum velit do.\r\n", + "registered": "2015-08-18T03:31:15 -02:00", + "latitude": 29.413032, + "longitude": -133.192246, + "tags": [ + "officia", + "elit", + "officia", + "nulla", + "nisi", + "sint", + "irure" + ], + "friends": [ + { + "id": 0, + "name": "Fitzgerald Vaughan" + }, + { + "id": 1, + "name": "Colette Sherman" + }, + { + "id": 2, + "name": "Guerrero Glenn" + } + ], + "greeting": "Hello, Earlene Simon! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5dc31908e0d70383a", + "index": 46, + "guid": "8ce3cbf6-c1d0-4a16-a9e8-77350d24e633", + "isActive": true, + "balance": "$2,970.73", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "green", + "name": "Byers Lynch", + "gender": "male", + "company": "HOUSEDOWN", + "email": "byerslynch@housedown.com", + "phone": "+1 (950) 599-3248", + "address": "160 Billings Place, Templeton, Guam, 9434", + "about": "Nostrud nostrud officia aute aliquip proident. Velit commodo exercitation tempor tempor sint et in deserunt magna irure velit velit consequat. Incididunt ea labore mollit sint officia dolore veniam officia. Deserunt ipsum ex Lorem aliqua fugiat aliqua. Duis ea aliqua eiusmod cillum laborum magna.\r\n", + "registered": "2019-12-01T08:09:46 -01:00", + "latitude": -59.562845, + "longitude": 72.12822, + "tags": [ + "voluptate", + "deserunt", + "elit", + "do", + "officia", + "occaecat", + "Lorem" + ], + "friends": [ + { + "id": 0, + "name": "Kramer Kinney" + }, + { + "id": 1, + "name": "Dawn Pearson" + }, + { + "id": 2, + "name": "Nichole Duffy" + } + ], + "greeting": "Hello, Byers Lynch! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee59ea33052eb3f3a98", + "index": 47, + "guid": "46c948fd-7040-40dd-b304-1f4956347276", + "isActive": true, + "balance": "$1,869.34", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "brown", + "name": "Morin Roth", + "gender": "male", + "company": "SONGBIRD", + "email": "morinroth@songbird.com", + "phone": "+1 (841) 553-2216", + "address": "632 Crown Street, Hilltop, New York, 1684", + "about": "Et dolor eu duis laborum ut exercitation amet. Duis dolor eu aliqua velit tempor sunt consequat. Amet cupidatat laborum fugiat cillum sunt ullamco pariatur adipisicing eu ullamco aliquip tempor. Nisi irure irure exercitation ad nulla. Officia do dolor cillum nulla ex laboris.\r\n", + "registered": "2017-10-08T07:03:09 -02:00", + "latitude": -42.285548, + "longitude": 2.559845, + "tags": [ + "pariatur", + "mollit", + "sint", + "adipisicing", + "eiusmod", + "in", + "exercitation" + ], + "friends": [ + { + "id": 0, + "name": "Downs Jefferson" + }, + { + "id": 1, + "name": "Casey Berger" + }, + { + "id": 2, + "name": "Woodard Reeves" + } + ], + "greeting": "Hello, Morin Roth! You have 4 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5ec78fa21af709610", + "index": 48, + "guid": "bfa99a20-9473-48f1-83b0-c3212e7ba773", + "isActive": false, + "balance": "$1,911.55", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "green", + "name": "Marsh Robertson", + "gender": "male", + "company": "OATFARM", + "email": "marshrobertson@oatfarm.com", + "phone": "+1 (880) 493-3836", + "address": "322 Clifford Place, Brogan, Colorado, 323", + "about": "Cillum cupidatat deserunt proident consectetur velit Lorem duis qui veniam ad ea voluptate nisi est. Labore ullamco excepteur quis nostrud elit incididunt esse sunt. Exercitation minim proident veniam reprehenderit nulla tempor laborum enim ut. Excepteur reprehenderit cillum mollit adipisicing eu esse incididunt adipisicing. Minim dolor dolor consequat sunt deserunt id sunt qui eu ipsum sit elit. Exercitation commodo Lorem eu aliquip adipisicing laborum. Ipsum magna pariatur laborum excepteur velit aute dolor mollit.\r\n", + "registered": "2019-04-10T05:12:27 -02:00", + "latitude": -23.391903, + "longitude": 119.968307, + "tags": [ + "pariatur", + "nisi", + "non", + "proident", + "ea", + "ipsum", + "cillum" + ], + "friends": [ + { + "id": 0, + "name": "Ballard Watkins" + }, + { + "id": 1, + "name": "Gomez Kirby" + }, + { + "id": 2, + "name": "Owens Rowland" + } + ], + "greeting": "Hello, Marsh Robertson! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee58fef70f3f6a3945e", + "index": 49, + "guid": "08682987-0de7-49ce-8874-27eeb1d65fe4", + "isActive": true, + "balance": "$1,548.47", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "brown", + "name": "Candice Clayton", + "gender": "female", + "company": "SQUISH", + "email": "candiceclayton@squish.com", + "phone": "+1 (852) 570-3839", + "address": "475 Irving Street, Munjor, Michigan, 4000", + "about": "Anim aliqua elit dolor nulla magna. Sunt eu duis Lorem quis labore adipisicing ad irure quis anim ea velit deserunt ut. Aliquip pariatur excepteur ipsum aliqua sunt dolor consequat excepteur laboris mollit. Ex sint do ullamco fugiat sint irure velit enim tempor et voluptate reprehenderit in. Adipisicing Lorem sit in ullamco officia tempor elit consectetur ullamco enim commodo.\r\n", + "registered": "2016-10-02T07:11:35 -02:00", + "latitude": -28.313052, + "longitude": -115.536943, + "tags": [ + "commodo", + "esse", + "cupidatat", + "excepteur", + "proident", + "eu", + "enim" + ], + "friends": [ + { + "id": 0, + "name": "Elva Wilcox" + }, + { + "id": 1, + "name": "Francesca Wright" + }, + { + "id": 2, + "name": "Humphrey Harvey" + } + ], + "greeting": "Hello, Candice Clayton! You have 2 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee560bf998ce7115b87", + "index": 50, + "guid": "ac04a0f6-d028-413d-b605-ff98bec9252c", + "isActive": true, + "balance": "$3,219.76", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "blue", + "name": "Miller Hicks", + "gender": "male", + "company": "ZENTHALL", + "email": "millerhicks@zenthall.com", + "phone": "+1 (969) 474-2875", + "address": "810 Orient Avenue, Chicopee, Vermont, 4275", + "about": "Cupidatat aute exercitation pariatur officia mollit minim quis non esse adipisicing ea magna exercitation tempor. Minim eiusmod minim irure deserunt aute velit aute dolore ut. Veniam pariatur dolore officia pariatur amet minim ut dolore adipisicing ipsum deserunt occaecat. Aliqua ut laboris nostrud aliqua ut commodo incididunt exercitation reprehenderit. Exercitation consectetur ex voluptate magna excepteur Lorem minim eiusmod ex voluptate fugiat sit mollit.\r\n", + "registered": "2017-02-19T07:43:32 -01:00", + "latitude": -47.475337, + "longitude": 27.342601, + "tags": [ + "duis", + "aute", + "sit", + "deserunt", + "commodo", + "ex", + "quis" + ], + "friends": [ + { + "id": 0, + "name": "Deloris Good" + }, + { + "id": 1, + "name": "Hall Hood" + }, + { + "id": 2, + "name": "Victoria Howell" + } + ], + "greeting": "Hello, Miller Hicks! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee57688a97ad05b55bf", + "index": 51, + "guid": "ea98d473-6042-4feb-bfa5-15251453c39f", + "isActive": false, + "balance": "$1,331.35", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "green", + "name": "Alma Cantrell", + "gender": "female", + "company": "ASSISTIX", + "email": "almacantrell@assistix.com", + "phone": "+1 (933) 486-3825", + "address": "507 Clara Street, Beaulieu, New Jersey, 2645", + "about": "Quis sint consectetur nostrud ex Lorem sit ex. Pariatur do pariatur veniam do pariatur do proident elit mollit occaecat laboris quis. Aute adipisicing consectetur nisi excepteur.\r\n", + "registered": "2016-10-04T10:01:19 -02:00", + "latitude": 78.534712, + "longitude": -58.175918, + "tags": [ + "fugiat", + "ex", + "adipisicing", + "mollit", + "consectetur", + "dolor", + "consectetur" + ], + "friends": [ + { + "id": 0, + "name": "Bradley Dunn" + }, + { + "id": 1, + "name": "Griffith Mathis" + }, + { + "id": 2, + "name": "Eliza Sykes" + } + ], + "greeting": "Hello, Alma Cantrell! You have 2 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5a384030e97cade91", + "index": 52, + "guid": "77c21bae-a235-4604-bc0a-99c24ea18715", + "isActive": true, + "balance": "$3,365.66", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "green", + "name": "Christi Goodman", + "gender": "female", + "company": "INRT", + "email": "christigoodman@inrt.com", + "phone": "+1 (988) 524-2396", + "address": "771 Harman Street, Cannondale, Nebraska, 7033", + "about": "Quis eiusmod laborum labore dolore Lorem id deserunt qui commodo ad ipsum. Do exercitation commodo minim ipsum reprehenderit consectetur duis incididunt ea laborum et commodo occaecat tempor. Ipsum aliquip deserunt anim in. Voluptate ex qui nulla consequat ad occaecat voluptate id mollit est esse.\r\n", + "registered": "2018-12-15T07:15:02 -01:00", + "latitude": 79.208702, + "longitude": 120.663466, + "tags": [ + "fugiat", + "fugiat", + "voluptate", + "duis", + "nisi", + "ut", + "id" + ], + "friends": [ + { + "id": 0, + "name": "Matthews Gibbs" + }, + { + "id": 1, + "name": "Avery Buck" + }, + { + "id": 2, + "name": "Melinda Gill" + } + ], + "greeting": "Hello, Christi Goodman! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee50db39859ed9f88cc", + "index": 53, + "guid": "80fe502a-9afd-47b0-92ed-5192fec82bee", + "isActive": true, + "balance": "$1,928.18", + "picture": "http://placehold.it/32x32", + "age": 26, + "eyeColor": "brown", + "name": "Marietta Caldwell", + "gender": "female", + "company": "SPACEWAX", + "email": "mariettacaldwell@spacewax.com", + "phone": "+1 (945) 417-2530", + "address": "961 Stockholm Street, Greenfields, North Carolina, 7787", + "about": "Lorem cupidatat cillum aute cupidatat cupidatat. Dolore velit eiusmod ut magna ex proident ex eiusmod non sunt nostrud. Sunt sunt anim eiusmod cupidatat aliqua ut dolor. Est qui culpa sint eiusmod minim laborum consectetur cillum aute ipsum anim sit. Esse culpa officia laboris non excepteur. Id eiusmod fugiat veniam veniam. Excepteur minim occaecat excepteur amet quis nisi irure elit.\r\n", + "registered": "2015-12-08T07:15:30 -01:00", + "latitude": -70.547153, + "longitude": -172.745286, + "tags": [ + "ut", + "id", + "dolore", + "cupidatat", + "id", + "dolore", + "anim" + ], + "friends": [ + { + "id": 0, + "name": "Catherine Cook" + }, + { + "id": 1, + "name": "Sparks Chambers" + }, + { + "id": 2, + "name": "Casandra Donaldson" + } + ], + "greeting": "Hello, Marietta Caldwell! You have 10 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee56c53561dec7d9e97", + "index": 54, + "guid": "51801c1d-c0bc-41ad-9288-08b9cf8147fe", + "isActive": true, + "balance": "$3,438.20", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "brown", + "name": "Jolene Browning", + "gender": "female", + "company": "OVOLO", + "email": "jolenebrowning@ovolo.com", + "phone": "+1 (989) 416-2660", + "address": "678 Dahill Road, Spokane, California, 7793", + "about": "Deserunt amet Lorem sit irure. Amet enim officia elit irure quis. Pariatur laborum eiusmod mollit ea id esse aliqua sit deserunt sit nostrud dolore aliqua deserunt. Cupidatat voluptate consectetur duis commodo aliquip fugiat ut ullamco sunt id aliquip. Sit ad amet cupidatat veniam est cillum commodo aute ut.\r\n", + "registered": "2014-08-16T05:13:51 -02:00", + "latitude": -49.030484, + "longitude": -28.034224, + "tags": [ + "adipisicing", + "culpa", + "in", + "esse", + "tempor", + "nostrud", + "cillum" + ], + "friends": [ + { + "id": 0, + "name": "Ellis Tanner" + }, + { + "id": 1, + "name": "Sloan Meyers" + }, + { + "id": 2, + "name": "Cruz Huff" + } + ], + "greeting": "Hello, Jolene Browning! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5688dbd3bef42eca4", + "index": 55, + "guid": "a11d0cf2-6691-4ef8-ab6e-be0de1a44b7f", + "isActive": false, + "balance": "$1,298.41", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "green", + "name": "Meyer Brock", + "gender": "male", + "company": "KAGE", + "email": "meyerbrock@kage.com", + "phone": "+1 (943) 461-2183", + "address": "693 Highland Boulevard, Ryderwood, Virgin Islands, 7050", + "about": "Exercitation qui dolore amet magna in duis qui ut laboris sit consectetur in magna. Pariatur eu culpa aliqua irure culpa quis non aliqua. Fugiat do enim commodo ut ullamco ut aute officia. Culpa ullamco consectetur exercitation irure voluptate ullamco proident. Ea et velit duis ad anim excepteur voluptate ex commodo nulla laboris commodo labore consequat. Duis ea mollit amet ullamco in commodo et ea mollit labore quis consequat aute sunt.\r\n", + "registered": "2015-05-01T05:09:40 -02:00", + "latitude": 15.801415, + "longitude": 118.939294, + "tags": [ + "id", + "et", + "officia", + "aliqua", + "laborum", + "adipisicing", + "tempor" + ], + "friends": [ + { + "id": 0, + "name": "Velez Phillips" + }, + { + "id": 1, + "name": "Crystal Albert" + }, + { + "id": 2, + "name": "Riggs Mayo" + } + ], + "greeting": "Hello, Meyer Brock! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee55af4976e78f1c87c", + "index": 56, + "guid": "9e592b60-565e-4971-b067-e5c8933ff4a0", + "isActive": true, + "balance": "$2,744.17", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "blue", + "name": "Rivas Franklin", + "gender": "male", + "company": "KIGGLE", + "email": "rivasfranklin@kiggle.com", + "phone": "+1 (912) 449-3489", + "address": "777 Dorset Street, Welda, Kentucky, 3267", + "about": "Voluptate irure irure sunt officia nisi est non pariatur deserunt eu aute enim veniam enim. Non veniam incididunt ullamco nostrud qui sunt qui fugiat exercitation consectetur esse culpa sit. Esse ullamco cillum magna cillum cillum eu ipsum ea irure commodo Lorem ex sit. Ea minim ipsum culpa est aute nisi irure commodo.\r\n", + "registered": "2014-02-25T07:31:23 -01:00", + "latitude": -87.409714, + "longitude": 83.183101, + "tags": [ + "in", + "aliquip", + "duis", + "laborum", + "occaecat", + "nostrud", + "culpa" + ], + "friends": [ + { + "id": 0, + "name": "Debbie Wolf" + }, + { + "id": 1, + "name": "Alice Velez" + }, + { + "id": 2, + "name": "Earnestine Hall" + } + ], + "greeting": "Hello, Rivas Franklin! You have 8 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee598d94cb9e82df264", + "index": 57, + "guid": "83fa6573-1aaa-43ee-997b-67f83847b64d", + "isActive": true, + "balance": "$3,829.17", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "blue", + "name": "Lara Suarez", + "gender": "female", + "company": "TEMORAK", + "email": "larasuarez@temorak.com", + "phone": "+1 (863) 548-2380", + "address": "343 Highland Avenue, Idamay, Alabama, 9118", + "about": "Consequat nostrud excepteur incididunt amet culpa sunt cillum tempor commodo aute eiusmod. Lorem deserunt incididunt id aute ad Lorem velit. Adipisicing ad cupidatat eiusmod commodo cillum velit pariatur laborum do. Amet adipisicing mollit adipisicing ea cillum adipisicing duis mollit enim duis amet mollit. Id ut aliqua ipsum esse ex officia laborum exercitation consequat ad velit. Aliqua consectetur minim excepteur id do eu do excepteur. Ex consequat non elit consectetur et occaecat.\r\n", + "registered": "2020-07-23T10:23:47 -02:00", + "latitude": -31.975016, + "longitude": -127.408851, + "tags": [ + "est", + "tempor", + "do", + "ullamco", + "proident", + "consequat", + "ullamco" + ], + "friends": [ + { + "id": 0, + "name": "Sheri Ortega" + }, + { + "id": 1, + "name": "Fay Lynn" + }, + { + "id": 2, + "name": "Kasey Thomas" + } + ], + "greeting": "Hello, Lara Suarez! You have 2 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5661e5c7e9e95e239", + "index": 58, + "guid": "39be01c4-2eee-426b-992d-e088f764ae93", + "isActive": true, + "balance": "$3,437.69", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "green", + "name": "Imelda Mack", + "gender": "female", + "company": "GENMEX", + "email": "imeldamack@genmex.com", + "phone": "+1 (984) 576-3751", + "address": "747 Goodwin Place, Condon, Alaska, 5532", + "about": "Tempor culpa ullamco exercitation ex non pariatur deserunt cillum ex cillum incididunt laborum enim nulla. Lorem nostrud officia ipsum nulla elit velit nulla consequat quis minim mollit Lorem ut tempor. Ipsum exercitation tempor excepteur laborum adipisicing tempor consequat sit magna exercitation nisi.\r\n", + "registered": "2016-03-27T05:03:24 -02:00", + "latitude": -19.710835, + "longitude": 152.16424, + "tags": [ + "dolore", + "ad", + "fugiat", + "veniam", + "occaecat", + "sit", + "ea" + ], + "friends": [ + { + "id": 0, + "name": "Velma Rasmussen" + }, + { + "id": 1, + "name": "John Austin" + }, + { + "id": 2, + "name": "Meredith Mckee" + } + ], + "greeting": "Hello, Imelda Mack! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee56b8a2155ed38db7d", + "index": 59, + "guid": "e15fd3f0-17b8-4039-b5de-95a66eae9eb5", + "isActive": false, + "balance": "$2,947.08", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "blue", + "name": "Daniels Carver", + "gender": "male", + "company": "STELAECOR", + "email": "danielscarver@stelaecor.com", + "phone": "+1 (950) 599-2404", + "address": "448 Ash Street, Fresno, Missouri, 1774", + "about": "Pariatur quis eu aute quis. Ad veniam laboris ea ex nostrud Lorem consectetur anim nulla exercitation. Dolor nostrud do pariatur consectetur eu quis ex laboris pariatur incididunt irure aliqua. Id pariatur sint incididunt qui quis enim Lorem nostrud aliqua labore labore. Et magna veniam et ipsum occaecat cillum.\r\n", + "registered": "2014-05-09T07:22:48 -02:00", + "latitude": 31.070703, + "longitude": 68.089875, + "tags": [ + "sit", + "veniam", + "eiusmod", + "et", + "enim", + "magna", + "nisi" + ], + "friends": [ + { + "id": 0, + "name": "Maryann Brewer" + }, + { + "id": 1, + "name": "Amelia Mccarthy" + }, + { + "id": 2, + "name": "Campos Raymond" + } + ], + "greeting": "Hello, Daniels Carver! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5566bb4e1cdc50266", + "index": 60, + "guid": "980f9e93-01b2-4931-9083-5f2ee498b0c7", + "isActive": true, + "balance": "$2,524.10", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "green", + "name": "Erica Heath", + "gender": "female", + "company": "ZOGAK", + "email": "ericaheath@zogak.com", + "phone": "+1 (809) 511-3798", + "address": "682 Grove Place, Smock, Hawaii, 9605", + "about": "Sit aliquip proident officia sunt consequat anim ullamco cupidatat ipsum deserunt Lorem ea ullamco. Sunt aliquip eu velit do laboris tempor aliquip ut eu enim pariatur laborum occaecat. Consequat cillum id dolor culpa. Laboris adipisicing irure esse mollit. Labore proident ad consequat dolore veniam labore nostrud pariatur ex consectetur consequat veniam adipisicing enim.\r\n", + "registered": "2020-03-12T03:22:33 -01:00", + "latitude": -6.031862, + "longitude": -27.133879, + "tags": [ + "adipisicing", + "eu", + "aute", + "sunt", + "et", + "irure", + "quis" + ], + "friends": [ + { + "id": 0, + "name": "Ruby Morris" + }, + { + "id": 1, + "name": "Langley Espinoza" + }, + { + "id": 2, + "name": "Amber Knox" + } + ], + "greeting": "Hello, Erica Heath! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5c8ff9e56fd292de9", + "index": 61, + "guid": "0069850e-ef43-4445-a49e-bf8a43553e2c", + "isActive": true, + "balance": "$3,972.66", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "green", + "name": "Bush Quinn", + "gender": "male", + "company": "SKYPLEX", + "email": "bushquinn@skyplex.com", + "phone": "+1 (846) 551-3843", + "address": "304 Carroll Street, Dellview, Ohio, 640", + "about": "Ad id dolor occaecat enim voluptate ex esse cillum adipisicing mollit. Occaecat esse in anim adipisicing deserunt nulla voluptate laboris. Anim cupidatat ea ullamco labore mollit ad duis sunt fugiat proident sit occaecat. Veniam voluptate sunt anim sit laboris est cupidatat enim fugiat exercitation Lorem. Id laborum nulla do eu id ut pariatur quis veniam. Labore quis voluptate veniam sunt sunt esse anim quis eu minim deserunt consequat. Deserunt laborum eiusmod labore anim est in occaecat veniam dolore velit.\r\n", + "registered": "2018-03-16T10:35:26 -01:00", + "latitude": 81.278949, + "longitude": -135.73624, + "tags": [ + "dolore", + "velit", + "amet", + "consectetur", + "fugiat", + "deserunt", + "proident" + ], + "friends": [ + { + "id": 0, + "name": "Gillespie Mcconnell" + }, + { + "id": 1, + "name": "Tamra Warren" + }, + { + "id": 2, + "name": "Mueller Bates" + } + ], + "greeting": "Hello, Bush Quinn! You have 6 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee575e5ba14e6103202", + "index": 62, + "guid": "44dc32a2-c73c-4956-a826-fdf71c6058ea", + "isActive": false, + "balance": "$3,960.50", + "picture": "http://placehold.it/32x32", + "age": 26, + "eyeColor": "brown", + "name": "Melissa Snow", + "gender": "female", + "company": "ECRATER", + "email": "melissasnow@ecrater.com", + "phone": "+1 (828) 454-3847", + "address": "927 Lincoln Terrace, Ironton, Federated States Of Micronesia, 1637", + "about": "Consequat adipisicing fugiat id magna aute nulla magna consectetur pariatur aute irure adipisicing occaecat. Voluptate amet ex aliqua magna ullamco anim reprehenderit. Ipsum dolore laboris elit mollit. Anim officia fugiat enim excepteur minim in eu laborum cillum reprehenderit pariatur. Quis consectetur velit mollit et consectetur eiusmod adipisicing cillum sint.\r\n", + "registered": "2017-10-11T05:15:51 -02:00", + "latitude": -31.512761, + "longitude": 56.381299, + "tags": [ + "dolore", + "fugiat", + "sunt", + "in", + "reprehenderit", + "ullamco", + "voluptate" + ], + "friends": [ + { + "id": 0, + "name": "Kristina Lewis" + }, + { + "id": 1, + "name": "Patrick Greer" + }, + { + "id": 2, + "name": "Tessa Riley" + } + ], + "greeting": "Hello, Melissa Snow! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5a6348436d4b8e3aa", + "index": 63, + "guid": "accdd887-fb3f-4431-87d1-7e6fed5e3fc0", + "isActive": false, + "balance": "$1,645.44", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "green", + "name": "Berta Parsons", + "gender": "female", + "company": "BIOSPAN", + "email": "bertaparsons@biospan.com", + "phone": "+1 (930) 568-2991", + "address": "289 Willoughby Street, Barronett, New Hampshire, 6831", + "about": "Cupidatat dolor sunt commodo eiusmod veniam aliqua occaecat aliquip irure est culpa. Reprehenderit anim ut ad tempor. Ullamco ut dolor sint Lorem aliquip amet ea velit ullamco minim est commodo et. In occaecat nostrud voluptate aliqua sunt duis culpa aute. Exercitation ut eiusmod do incididunt anim cillum.\r\n", + "registered": "2017-05-19T10:26:14 -02:00", + "latitude": -8.706386, + "longitude": 34.863032, + "tags": [ + "aliquip", + "aliquip", + "aute", + "est", + "incididunt", + "dolor", + "quis" + ], + "friends": [ + { + "id": 0, + "name": "Figueroa Willis" + }, + { + "id": 1, + "name": "Ortega Chang" + }, + { + "id": 2, + "name": "Elena Leach" + } + ], + "greeting": "Hello, Berta Parsons! You have 8 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5a91304e4f0e3d4d0", + "index": 64, + "guid": "f3c85339-2374-4f53-98a8-522b1da48644", + "isActive": true, + "balance": "$3,712.36", + "picture": "http://placehold.it/32x32", + "age": 37, + "eyeColor": "green", + "name": "Delgado Vincent", + "gender": "male", + "company": "GRAINSPOT", + "email": "delgadovincent@grainspot.com", + "phone": "+1 (861) 486-2612", + "address": "846 Bokee Court, Springdale, Utah, 2407", + "about": "Occaecat irure irure nisi quis laboris nulla officia quis ullamco ad pariatur ut. Non sunt nisi do cupidatat in ex nulla ut veniam amet. Dolor officia aliquip sunt excepteur mollit magna tempor irure consequat. Cupidatat eiusmod incididunt magna esse id eu tempor. Exercitation non non eu ipsum mollit non elit. Nulla ea ipsum et quis.\r\n", + "registered": "2017-10-06T02:51:38 -02:00", + "latitude": -0.758576, + "longitude": -14.711748, + "tags": [ + "ipsum", + "enim", + "ipsum", + "qui", + "quis", + "nulla", + "quis" + ], + "friends": [ + { + "id": 0, + "name": "Rutledge Arnold" + }, + { + "id": 1, + "name": "Fulton Gilbert" + }, + { + "id": 2, + "name": "Letha Hughes" + } + ], + "greeting": "Hello, Delgado Vincent! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5b5199e5643998a3d", + "index": 65, + "guid": "f69b5d62-fd18-43de-97ad-587df7095c59", + "isActive": false, + "balance": "$1,912.60", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "blue", + "name": "Fisher Love", + "gender": "male", + "company": "GENMY", + "email": "fisherlove@genmy.com", + "phone": "+1 (904) 458-2710", + "address": "713 Java Street, Linwood, Pennsylvania, 7612", + "about": "Eu consequat minim ut enim esse aute cillum reprehenderit eu magna eu nisi do. Dolor nostrud in magna culpa ea aliquip. Tempor non ipsum aliquip quis aute deserunt consequat incididunt tempor qui culpa magna enim. Enim sit enim nisi ea sunt minim. Ad culpa consequat anim et. Minim excepteur sit fugiat pariatur nisi veniam sunt est aute. Eiusmod sint culpa ipsum sunt ipsum.\r\n", + "registered": "2016-11-09T12:00:26 -01:00", + "latitude": -9.245969, + "longitude": 85.988556, + "tags": [ + "est", + "incididunt", + "sunt", + "eiusmod", + "elit", + "sunt", + "ad" + ], + "friends": [ + { + "id": 0, + "name": "Hudson Slater" + }, + { + "id": 1, + "name": "Mullen Hernandez" + }, + { + "id": 2, + "name": "Mclean Alston" + } + ], + "greeting": "Hello, Fisher Love! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee50ae252fe1bf85e84", + "index": 66, + "guid": "bb5c8988-07ac-4f71-abda-cf2a7f409b3c", + "isActive": false, + "balance": "$3,549.60", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Jerri Leblanc", + "gender": "female", + "company": "BIOHAB", + "email": "jerrileblanc@biohab.com", + "phone": "+1 (898) 560-3924", + "address": "926 Stryker Court, Sparkill, North Dakota, 6900", + "about": "Pariatur ullamco consectetur in labore nisi qui nisi ea veniam amet deserunt do ea. Est Lorem fugiat incididunt dolore tempor labore. Anim excepteur ullamco aute esse laboris elit consectetur laborum do.\r\n", + "registered": "2016-05-05T10:51:22 -02:00", + "latitude": -11.414042, + "longitude": 12.354026, + "tags": [ + "eiusmod", + "veniam", + "consectetur", + "officia", + "ex", + "mollit", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Yvette Gutierrez" + }, + { + "id": 1, + "name": "Tammi Gallegos" + }, + { + "id": 2, + "name": "Drake Hale" + } + ], + "greeting": "Hello, Jerri Leblanc! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee54bbee9728857dfbe", + "index": 67, + "guid": "e310f814-983f-4dc9-b9fe-44002d66e577", + "isActive": true, + "balance": "$2,722.47", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "brown", + "name": "Myrtle Sellers", + "gender": "female", + "company": "AVIT", + "email": "myrtlesellers@avit.com", + "phone": "+1 (922) 529-3743", + "address": "577 Hendrix Street, Stollings, Delaware, 9800", + "about": "Anim incididunt occaecat minim dolor sunt sit eiusmod velit. Incididunt ea laboris consequat fugiat occaecat dolore veniam ullamco sunt. Irure excepteur reprehenderit consectetur est sint ullamco dolor culpa dolor occaecat. Labore ut reprehenderit incididunt nulla id nostrud nisi tempor esse. Elit occaecat adipisicing dolor fugiat minim amet cupidatat veniam do enim. Eu non adipisicing quis nulla ut culpa veniam eiusmod elit ea ea. Dolor enim ipsum ut dolor.\r\n", + "registered": "2017-09-25T05:56:16 -02:00", + "latitude": -55.474082, + "longitude": 152.176123, + "tags": [ + "ea", + "dolor", + "ex", + "nostrud", + "ullamco", + "nostrud", + "voluptate" + ], + "friends": [ + { + "id": 0, + "name": "Bird Christensen" + }, + { + "id": 1, + "name": "Roseann Franco" + }, + { + "id": 2, + "name": "Shepard Summers" + } + ], + "greeting": "Hello, Myrtle Sellers! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5488a7883e3795b64", + "index": 68, + "guid": "0d5240b7-609a-4121-b5c8-5d0826e73769", + "isActive": false, + "balance": "$3,109.32", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "blue", + "name": "Muriel Puckett", + "gender": "female", + "company": "VETRON", + "email": "murielpuckett@vetron.com", + "phone": "+1 (950) 494-2441", + "address": "265 Hegeman Avenue, Brenton, Nevada, 964", + "about": "Non nulla enim velit occaecat velit reprehenderit sit esse fugiat elit nulla elit cupidatat amet. Culpa amet dolor reprehenderit Lorem voluptate quis esse nostrud sint nostrud amet. Labore proident amet esse aute in veniam laborum cupidatat nostrud in nisi in. Labore quis aliquip duis non voluptate cillum commodo consectetur. Adipisicing do tempor exercitation pariatur excepteur irure consequat duis. Fugiat officia aliquip fugiat voluptate duis eiusmod enim proident occaecat reprehenderit duis officia.\r\n", + "registered": "2020-06-29T12:54:13 -02:00", + "latitude": -49.834776, + "longitude": -34.116946, + "tags": [ + "anim", + "sit", + "deserunt", + "amet", + "cupidatat", + "fugiat", + "sint" + ], + "friends": [ + { + "id": 0, + "name": "Maureen Mueller" + }, + { + "id": 1, + "name": "Merle Parrish" + }, + { + "id": 2, + "name": "Brewer Garza" + } + ], + "greeting": "Hello, Muriel Puckett! You have 4 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee51cd9bee0b10046f7", + "index": 69, + "guid": "247fc5d6-ec87-4264-9dba-2cb8fa205893", + "isActive": false, + "balance": "$3,414.00", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "brown", + "name": "Marshall Whitney", + "gender": "male", + "company": "FLYBOYZ", + "email": "marshallwhitney@flyboyz.com", + "phone": "+1 (837) 448-3769", + "address": "336 Dewitt Avenue, Ballico, Montana, 285", + "about": "Aute irure irure dolore enim dolor qui deserunt irure amet. Magna dolore consequat nulla ea amet dolor voluptate officia nisi et. Voluptate nostrud veniam et cillum proident deserunt.\r\n", + "registered": "2015-08-18T06:31:54 -02:00", + "latitude": -36.503593, + "longitude": -4.989295, + "tags": [ + "nostrud", + "id", + "proident", + "aute", + "non", + "nisi", + "aute" + ], + "friends": [ + { + "id": 0, + "name": "Katelyn Glass" + }, + { + "id": 1, + "name": "Jill Todd" + }, + { + "id": 2, + "name": "Horton Savage" + } + ], + "greeting": "Hello, Marshall Whitney! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5e4cd9807868e1e5a", + "index": 70, + "guid": "683e4a85-9822-46f6-81f2-f42d4d23b1ab", + "isActive": true, + "balance": "$2,481.34", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "blue", + "name": "Bonita Bowers", + "gender": "female", + "company": "GONKLE", + "email": "bonitabowers@gonkle.com", + "phone": "+1 (845) 538-2621", + "address": "916 Beaver Street, Yogaville, Arizona, 3599", + "about": "Tempor eu non Lorem officia nostrud eu esse. Sint commodo qui dolore ullamco non duis sunt dolore proident officia Lorem. Excepteur adipisicing fugiat mollit sit mollit ullamco nostrud esse consectetur. Labore adipisicing anim in cupidatat tempor incididunt pariatur anim. Ad minim elit amet ex ullamco pariatur incididunt esse labore duis. Do irure consectetur consectetur commodo commodo deserunt mollit cupidatat sint anim et irure.\r\n", + "registered": "2018-01-06T08:36:22 -01:00", + "latitude": 42.190219, + "longitude": 73.222527, + "tags": [ + "ut", + "exercitation", + "sunt", + "cupidatat", + "veniam", + "magna", + "enim" + ], + "friends": [ + { + "id": 0, + "name": "Kayla Graham" + }, + { + "id": 1, + "name": "Douglas Bullock" + }, + { + "id": 2, + "name": "Leanne Snyder" + } + ], + "greeting": "Hello, Bonita Bowers! You have 7 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5e5e5856723ee6c92", + "index": 71, + "guid": "1acbaf68-1c32-4485-8658-44f04b6d0e94", + "isActive": false, + "balance": "$2,195.76", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "blue", + "name": "Chang Frank", + "gender": "male", + "company": "QOT", + "email": "changfrank@qot.com", + "phone": "+1 (988) 488-2931", + "address": "989 Newport Street, Coldiron, Massachusetts, 7981", + "about": "Do aliquip occaecat do duis veniam proident consequat ad et voluptate reprehenderit nulla. Aliquip ad elit velit excepteur nisi sunt. Adipisicing laborum reprehenderit in proident. Dolore in sit occaecat consequat velit. Culpa proident ex enim fugiat eiusmod consequat pariatur cillum nulla irure do sunt.\r\n", + "registered": "2016-09-26T05:49:23 -02:00", + "latitude": -85.52177, + "longitude": -102.815192, + "tags": [ + "nulla", + "ea", + "culpa", + "non", + "nisi", + "nostrud", + "elit" + ], + "friends": [ + { + "id": 0, + "name": "French Gillespie" + }, + { + "id": 1, + "name": "Valenzuela Horne" + }, + { + "id": 2, + "name": "Lyons Smith" + } + ], + "greeting": "Hello, Chang Frank! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee54de6173856f76449", + "index": 72, + "guid": "596244b0-2cd9-46c9-ba71-1b3b41bf97b8", + "isActive": false, + "balance": "$3,746.97", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "blue", + "name": "April Schmidt", + "gender": "female", + "company": "DEVILTOE", + "email": "aprilschmidt@deviltoe.com", + "phone": "+1 (948) 453-2579", + "address": "979 Campus Place, Orason, Maryland, 401", + "about": "Velit incididunt labore nulla nostrud eu non cillum velit. Cupidatat aute Lorem nisi adipisicing qui mollit dolor nostrud sunt aute sit. Voluptate aliquip esse Lorem labore ex velit aliquip irure pariatur consequat nostrud aute id eiusmod.\r\n", + "registered": "2015-05-08T03:59:24 -02:00", + "latitude": -39.956306, + "longitude": -16.730671, + "tags": [ + "laborum", + "nostrud", + "do", + "Lorem", + "id", + "dolor", + "nulla" + ], + "friends": [ + { + "id": 0, + "name": "Elba Robinson" + }, + { + "id": 1, + "name": "Lottie Nicholson" + }, + { + "id": 2, + "name": "Mable Durham" + } + ], + "greeting": "Hello, April Schmidt! You have 5 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee58a16e0b97deba3e0", + "index": 73, + "guid": "d0099fb6-5552-4a3c-8e28-6a4a1b2e7e5c", + "isActive": true, + "balance": "$1,205.48", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "blue", + "name": "Nieves Brady", + "gender": "male", + "company": "GUSHKOOL", + "email": "nievesbrady@gushkool.com", + "phone": "+1 (810) 592-2550", + "address": "550 Lake Place, Morningside, Florida, 6574", + "about": "Do Lorem minim anim esse in duis labore ullamco incididunt. Minim qui dolor laborum do sint sunt nisi cillum enim. Ullamco ad ea sit ex laborum excepteur nulla laboris dolore et. Proident do ex elit anim ullamco eu consectetur duis cupidatat fugiat. Mollit cupidatat ea esse esse excepteur ipsum irure eiusmod tempor excepteur irure cillum consectetur ea. Enim irure id et ipsum tempor. Veniam dolore velit non eiusmod dolor do adipisicing nostrud.\r\n", + "registered": "2017-02-22T05:23:29 -01:00", + "latitude": -17.780885, + "longitude": 109.581405, + "tags": [ + "non", + "ad", + "consectetur", + "incididunt", + "fugiat", + "minim", + "deserunt" + ], + "friends": [ + { + "id": 0, + "name": "Roberta Martinez" + }, + { + "id": 1, + "name": "Cameron Stafford" + }, + { + "id": 2, + "name": "Sanford Wong" + } + ], + "greeting": "Hello, Nieves Brady! You have 10 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5e42408a624f51aa5", + "index": 74, + "guid": "b6622f51-5632-4b61-9c25-d0c00faef236", + "isActive": false, + "balance": "$3,187.05", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "green", + "name": "Simon Benjamin", + "gender": "male", + "company": "XANIDE", + "email": "simonbenjamin@xanide.com", + "phone": "+1 (828) 526-2879", + "address": "440 Krier Place, Lookingglass, Washington, 2248", + "about": "Dolore consequat voluptate exercitation tempor. Aute amet labore ut occaecat aliquip elit sunt officia Lorem officia et amet proident. Mollit ea excepteur consequat aliqua. Excepteur duis aliqua magna veniam occaecat mollit culpa ex ipsum enim do et. Amet ullamco consequat velit ipsum proident sint aliquip eu elit dolore fugiat.\r\n", + "registered": "2019-06-26T06:58:26 -02:00", + "latitude": 47.27387, + "longitude": 93.247992, + "tags": [ + "esse", + "adipisicing", + "labore", + "ad", + "tempor", + "aliquip", + "est" + ], + "friends": [ + { + "id": 0, + "name": "Olsen Price" + }, + { + "id": 1, + "name": "Sanders Odonnell" + }, + { + "id": 2, + "name": "Jimenez Castaneda" + } + ], + "greeting": "Hello, Simon Benjamin! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee56fcd74e494e45c1c", + "index": 75, + "guid": "4f2feabb-380a-464b-8401-d045ab85ef79", + "isActive": true, + "balance": "$3,927.33", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "blue", + "name": "Fox Harding", + "gender": "male", + "company": "MONDICIL", + "email": "foxharding@mondicil.com", + "phone": "+1 (882) 473-3031", + "address": "215 Pioneer Street, Kirk, Virginia, 6835", + "about": "Laborum eiusmod ex sit esse fugiat pariatur dolor tempor aliquip. Non culpa sit occaecat cillum eu amet velit cillum dolore nisi adipisicing labore pariatur. Esse consectetur ullamco aute esse.\r\n", + "registered": "2021-09-15T05:35:33 -02:00", + "latitude": 35.706083, + "longitude": -130.293843, + "tags": [ + "Lorem", + "eu", + "ex", + "aliquip", + "aliquip", + "incididunt", + "adipisicing" + ], + "friends": [ + { + "id": 0, + "name": "Strickland Walker" + }, + { + "id": 1, + "name": "Jordan Ellison" + }, + { + "id": 2, + "name": "Kimberly Chaney" + } + ], + "greeting": "Hello, Fox Harding! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee59f219a3f643812d1", + "index": 76, + "guid": "ee011715-e9c5-41ec-a293-cf9cc1646a5a", + "isActive": false, + "balance": "$3,780.73", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Medina Contreras", + "gender": "male", + "company": "ISOLOGICS", + "email": "medinacontreras@isologics.com", + "phone": "+1 (877) 457-2039", + "address": "532 Brigham Street, Utting, Oklahoma, 5493", + "about": "Voluptate ullamco proident labore esse mollit eu commodo id fugiat veniam sunt proident sunt. Et voluptate commodo amet elit esse amet exercitation ea. Enim ad labore reprehenderit est occaecat id culpa deserunt incididunt deserunt ex non Lorem laboris. Sunt nulla exercitation ex occaecat elit dolor laboris occaecat.\r\n", + "registered": "2018-01-30T02:13:15 -01:00", + "latitude": 10.048385, + "longitude": -3.787903, + "tags": [ + "ex", + "esse", + "velit", + "esse", + "proident", + "ullamco", + "minim" + ], + "friends": [ + { + "id": 0, + "name": "Cheri Burns" + }, + { + "id": 1, + "name": "Workman Gallagher" + }, + { + "id": 2, + "name": "Knight Long" + } + ], + "greeting": "Hello, Medina Contreras! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee55b417adf49c0624d", + "index": 77, + "guid": "afb34e70-1dd9-4c0d-a6ac-6a619d59fd19", + "isActive": false, + "balance": "$1,291.65", + "picture": "http://placehold.it/32x32", + "age": 34, + "eyeColor": "blue", + "name": "Bernice Lancaster", + "gender": "female", + "company": "EYEWAX", + "email": "bernicelancaster@eyewax.com", + "phone": "+1 (831) 533-2075", + "address": "242 Grattan Street, Thornport, Mississippi, 6895", + "about": "Enim deserunt eu nostrud minim nostrud ad amet et nostrud mollit elit. Magna occaecat amet magna veniam consectetur ullamco consectetur. Qui duis dolor adipisicing occaecat duis velit nulla consequat. Tempor incididunt deserunt cillum laboris occaecat minim id. Labore Lorem labore esse exercitation ullamco exercitation eu eu.\r\n", + "registered": "2017-10-06T12:38:57 -02:00", + "latitude": -17.721689, + "longitude": -129.444642, + "tags": [ + "velit", + "in", + "voluptate", + "nisi", + "adipisicing", + "cupidatat", + "id" + ], + "friends": [ + { + "id": 0, + "name": "Young Wooten" + }, + { + "id": 1, + "name": "Kris Stark" + }, + { + "id": 2, + "name": "Gregory Avery" + } + ], + "greeting": "Hello, Bernice Lancaster! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5c57dca9e8bcb4b3c", + "index": 78, + "guid": "9cf2f752-420c-4df6-9e5b-863de6f6ce12", + "isActive": false, + "balance": "$1,974.70", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "green", + "name": "Weaver Beasley", + "gender": "male", + "company": "TELEQUIET", + "email": "weaverbeasley@telequiet.com", + "phone": "+1 (976) 426-2956", + "address": "492 Lott Street, Snowville, Wisconsin, 3924", + "about": "Magna pariatur exercitation laborum cillum occaecat velit deserunt. Dolore nulla eu nulla ea pariatur non culpa eiusmod fugiat dolor laborum. Et sunt ad deserunt et aute laborum voluptate velit quis cupidatat nisi aliqua. Culpa ad sit est consequat ad excepteur anim.\r\n", + "registered": "2018-08-18T09:29:43 -02:00", + "latitude": 89.801313, + "longitude": 152.979749, + "tags": [ + "dolore", + "non", + "incididunt", + "sint", + "incididunt", + "aute", + "adipisicing" + ], + "friends": [ + { + "id": 0, + "name": "Rosales Salinas" + }, + { + "id": 1, + "name": "Williamson Haley" + }, + { + "id": 2, + "name": "Angeline Klein" + } + ], + "greeting": "Hello, Weaver Beasley! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee58745a42fafd7da82", + "index": 79, + "guid": "3f63c05f-b732-4e0a-9897-92368eef4fa6", + "isActive": true, + "balance": "$3,325.06", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "green", + "name": "Judy Montgomery", + "gender": "female", + "company": "PERKLE", + "email": "judymontgomery@perkle.com", + "phone": "+1 (941) 492-3110", + "address": "403 Sands Street, Greensburg, South Dakota, 8782", + "about": "Dolor officia non id nulla exercitation fugiat nostrud. Incididunt ea eiusmod minim qui nostrud fugiat cillum labore id occaecat. Incididunt deserunt id et fugiat anim.\r\n", + "registered": "2015-05-26T06:05:56 -02:00", + "latitude": 56.199209, + "longitude": 168.124642, + "tags": [ + "occaecat", + "id", + "exercitation", + "culpa", + "consectetur", + "sit", + "enim" + ], + "friends": [ + { + "id": 0, + "name": "Owen Mclaughlin" + }, + { + "id": 1, + "name": "Mcfadden Bowen" + }, + { + "id": 2, + "name": "Page Leon" + } + ], + "greeting": "Hello, Judy Montgomery! You have 4 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5a7640d651ba0e2c6", + "index": 80, + "guid": "46c7961e-8157-4f03-9b6a-25d9ea0b3247", + "isActive": false, + "balance": "$1,478.12", + "picture": "http://placehold.it/32x32", + "age": 26, + "eyeColor": "brown", + "name": "Georgina Shaffer", + "gender": "female", + "company": "MOLTONIC", + "email": "georginashaffer@moltonic.com", + "phone": "+1 (889) 570-2861", + "address": "444 Hale Avenue, Weogufka, Georgia, 8315", + "about": "Veniam mollit esse mollit do non labore aute labore. Duis cillum duis aliqua do. Pariatur irure sit veniam laborum amet duis adipisicing sunt do id aute minim aliquip. Eiusmod ut pariatur id minim ea et dolor aliqua. Nostrud ad qui ad fugiat dolor tempor duis nisi ullamco labore sint Lorem. Consectetur id laborum proident enim incididunt excepteur aliqua esse voluptate tempor. Excepteur dolore nostrud irure officia pariatur eu nostrud ex et.\r\n", + "registered": "2021-03-03T07:43:43 -01:00", + "latitude": -34.619149, + "longitude": 100.204642, + "tags": [ + "proident", + "anim", + "laboris", + "culpa", + "anim", + "esse", + "consequat" + ], + "friends": [ + { + "id": 0, + "name": "Johanna Richard" + }, + { + "id": 1, + "name": "Herman Casey" + }, + { + "id": 2, + "name": "Small Erickson" + } + ], + "greeting": "Hello, Georgina Shaffer! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5fff9a59515fe658d", + "index": 81, + "guid": "c9598dd8-28bc-4a13-bcec-08b2a36d0dd3", + "isActive": true, + "balance": "$2,060.91", + "picture": "http://placehold.it/32x32", + "age": 26, + "eyeColor": "green", + "name": "Faye Winters", + "gender": "female", + "company": "CENTREXIN", + "email": "fayewinters@centrexin.com", + "phone": "+1 (980) 450-3689", + "address": "532 Albee Square, Orick, Connecticut, 8869", + "about": "Eu et est non ut voluptate cillum occaecat ipsum occaecat consequat adipisicing ipsum dolor. Cupidatat labore ad quis elit minim cillum laborum ea. Reprehenderit labore magna magna culpa amet ullamco nostrud veniam cillum mollit Lorem ullamco ut enim. Do incididunt nulla proident elit esse occaecat. Laboris ea occaecat anim dolore. Sunt deserunt ad occaecat reprehenderit occaecat incididunt velit amet esse. Qui deserunt tempor consectetur esse dolor enim nulla.\r\n", + "registered": "2014-07-06T08:30:31 -02:00", + "latitude": -28.703521, + "longitude": 83.875078, + "tags": [ + "dolore", + "in", + "proident", + "consequat", + "ipsum", + "veniam", + "et" + ], + "friends": [ + { + "id": 0, + "name": "Catalina Weaver" + }, + { + "id": 1, + "name": "Neva George" + }, + { + "id": 2, + "name": "Bryant Coleman" + } + ], + "greeting": "Hello, Faye Winters! You have 10 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5de6257ee1a5d39c8", + "index": 82, + "guid": "fe7ba2a2-1006-45c9-9266-74cf48ff96a8", + "isActive": true, + "balance": "$2,599.20", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "brown", + "name": "Cohen Knight", + "gender": "male", + "company": "ACUMENTOR", + "email": "cohenknight@acumentor.com", + "phone": "+1 (952) 538-2105", + "address": "558 Canton Court, Winchester, West Virginia, 9458", + "about": "Commodo occaecat ad sunt laborum laboris duis ipsum elit dolore irure. Tempor nisi ex amet aliqua elit enim cillum magna magna laboris. Nisi esse in et sunt duis irure enim. Ad mollit fugiat ex sit occaecat duis in veniam. Adipisicing voluptate deserunt tempor deserunt voluptate. Sint dolor enim eiusmod qui commodo mollit elit magna dolore velit.\r\n", + "registered": "2017-06-09T03:09:55 -02:00", + "latitude": -22.960099, + "longitude": 116.764669, + "tags": [ + "fugiat", + "sint", + "commodo", + "dolor", + "est", + "ut", + "pariatur" + ], + "friends": [ + { + "id": 0, + "name": "Webb Morrison" + }, + { + "id": 1, + "name": "Walton Mccray" + }, + { + "id": 2, + "name": "Green Russell" + } + ], + "greeting": "Hello, Cohen Knight! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee59413e1010491ee60", + "index": 83, + "guid": "e779fe8b-9bd1-4e9b-9c6e-12643d921609", + "isActive": false, + "balance": "$2,511.90", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "blue", + "name": "Barrera Madden", + "gender": "male", + "company": "SARASONIC", + "email": "barreramadden@sarasonic.com", + "phone": "+1 (804) 430-3819", + "address": "266 Ralph Avenue, Ernstville, Marshall Islands, 3976", + "about": "Eu reprehenderit quis laboris elit culpa culpa reprehenderit occaecat. Pariatur esse do proident nulla Lorem dolore eiusmod non eiusmod adipisicing. Ullamco voluptate ipsum aliqua officia commodo nostrud irure. In aliqua incididunt excepteur nostrud voluptate aliqua proident deserunt reprehenderit minim ex quis veniam. Consequat ea adipisicing nulla magna do minim consequat ad.\r\n", + "registered": "2016-12-19T06:20:02 -01:00", + "latitude": -53.604349, + "longitude": 18.920039, + "tags": [ + "veniam", + "consectetur", + "laborum", + "laboris", + "adipisicing", + "velit", + "ipsum" + ], + "friends": [ + { + "id": 0, + "name": "William Burton" + }, + { + "id": 1, + "name": "Mcknight Hickman" + }, + { + "id": 2, + "name": "Hamilton Flores" + } + ], + "greeting": "Hello, Barrera Madden! You have 1 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5601516e45042a486", + "index": 84, + "guid": "2d67cf5b-871d-41a1-990b-4eb3529f7acc", + "isActive": true, + "balance": "$2,056.88", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "blue", + "name": "Letitia Gomez", + "gender": "female", + "company": "MEDALERT", + "email": "letitiagomez@medalert.com", + "phone": "+1 (987) 479-3111", + "address": "608 Williamsburg Street, Kipp, Arkansas, 4908", + "about": "Reprehenderit est deserunt pariatur ut exercitation nulla proident qui incididunt exercitation magna aliquip. Adipisicing magna ipsum sit consequat occaecat ut eu eu ullamco velit commodo nostrud. Officia tempor Lorem ipsum pariatur non velit labore incididunt fugiat qui quis. Esse labore ipsum veniam commodo dolore aliquip non elit consectetur adipisicing voluptate magna aliquip elit.\r\n", + "registered": "2015-10-25T04:07:20 -01:00", + "latitude": -80.11144, + "longitude": 46.031795, + "tags": [ + "quis", + "enim", + "aliqua", + "aliquip", + "tempor", + "consectetur", + "irure" + ], + "friends": [ + { + "id": 0, + "name": "Hahn Head" + }, + { + "id": 1, + "name": "Edwina Logan" + }, + { + "id": 2, + "name": "Jennings Le" + } + ], + "greeting": "Hello, Letitia Gomez! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee53c18157c9e254e9e", + "index": 85, + "guid": "fb798a9c-64c9-48bd-97c5-c9ea3e059797", + "isActive": false, + "balance": "$2,736.39", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "brown", + "name": "Kane Mcintyre", + "gender": "male", + "company": "CALCULA", + "email": "kanemcintyre@calcula.com", + "phone": "+1 (859) 435-3999", + "address": "563 Manhattan Court, Bellamy, Oregon, 9957", + "about": "Quis esse dolore fugiat sint officia. Est cupidatat aliquip mollit elit id amet sit. Mollit quis Lorem elit nostrud esse esse enim est eu irure adipisicing incididunt. Est exercitation officia occaecat do laborum ex amet proident duis amet ea ad. Do est officia eu amet velit magna do ut do.\r\n", + "registered": "2014-05-27T02:39:52 -02:00", + "latitude": -46.804805, + "longitude": 132.115786, + "tags": [ + "cupidatat", + "voluptate", + "mollit", + "ad", + "excepteur", + "consectetur", + "id" + ], + "friends": [ + { + "id": 0, + "name": "Ilene Conway" + }, + { + "id": 1, + "name": "Tucker Weber" + }, + { + "id": 2, + "name": "Leola Preston" + } + ], + "greeting": "Hello, Kane Mcintyre! You have 4 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5c61a52d4a9df7c4b", + "index": 86, + "guid": "e44b6c5b-ec64-4346-8892-544df046ad57", + "isActive": true, + "balance": "$3,886.52", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "green", + "name": "Witt Cooper", + "gender": "male", + "company": "RUBADUB", + "email": "wittcooper@rubadub.com", + "phone": "+1 (822) 524-3659", + "address": "651 Oriental Court, Gorst, Puerto Rico, 1547", + "about": "Velit laborum nostrud sint cupidatat pariatur labore sint proident. Est anim ex est dolore dolor. Deserunt sunt sit enim velit anim proident veniam enim reprehenderit pariatur consequat culpa. Lorem exercitation anim incididunt duis exercitation anim minim ipsum dolore id sunt ad enim. Laboris officia enim sint incididunt exercitation pariatur cupidatat aute Lorem Lorem pariatur. Ut non aliqua commodo dolor anim. Nisi deserunt eu eiusmod nisi nulla occaecat dolore commodo qui reprehenderit laboris.\r\n", + "registered": "2017-06-12T06:44:17 -02:00", + "latitude": 48.003669, + "longitude": 82.759369, + "tags": [ + "ullamco", + "eiusmod", + "elit", + "aliqua", + "id", + "aute", + "aliquip" + ], + "friends": [ + { + "id": 0, + "name": "Patty Santos" + }, + { + "id": 1, + "name": "Ward Diaz" + }, + { + "id": 2, + "name": "Lacy Acosta" + } + ], + "greeting": "Hello, Witt Cooper! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee50ae03f090be506ec", + "index": 87, + "guid": "63b4465e-291c-4f02-ae82-d385cbac9a83", + "isActive": false, + "balance": "$3,324.57", + "picture": "http://placehold.it/32x32", + "age": 32, + "eyeColor": "brown", + "name": "Rosetta Dominguez", + "gender": "female", + "company": "ZIALACTIC", + "email": "rosettadominguez@zialactic.com", + "phone": "+1 (815) 463-2658", + "address": "255 Neptune Court, Worton, Idaho, 8506", + "about": "Consectetur ipsum voluptate sint aliqua. Ea do do ut eiusmod minim laborum nostrud aliquip dolore quis. Proident irure aliqua veniam magna in Lorem adipisicing sunt nisi ut aliquip nostrud cillum. Deserunt deserunt ut laborum id deserunt ea velit ad velit. Aliquip aute eu excepteur commodo pariatur velit ad culpa eu ut veniam nulla. Dolore magna in aliquip fugiat nisi ullamco quis.\r\n", + "registered": "2016-02-04T06:03:44 -01:00", + "latitude": -50.23274, + "longitude": 5.595989, + "tags": [ + "nostrud", + "velit", + "dolor", + "aute", + "enim", + "dolore", + "tempor" + ], + "friends": [ + { + "id": 0, + "name": "Nora Strickland" + }, + { + "id": 1, + "name": "Avila Vinson" + }, + { + "id": 2, + "name": "Yates Jimenez" + } + ], + "greeting": "Hello, Rosetta Dominguez! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee51f2cf2d86c839226", + "index": 88, + "guid": "fff4d7f6-c98e-4ea7-81c8-fa78cce883a3", + "isActive": false, + "balance": "$1,135.65", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "green", + "name": "Sanchez Dejesus", + "gender": "male", + "company": "MAGNAFONE", + "email": "sanchezdejesus@magnafone.com", + "phone": "+1 (996) 442-2836", + "address": "274 Sackman Street, Grantville, New Mexico, 2719", + "about": "Cupidatat tempor adipisicing ea amet elit nulla. Laboris pariatur excepteur adipisicing in in esse Lorem cillum magna adipisicing occaecat sint do excepteur. Velit ex laboris reprehenderit nostrud qui nulla quis et magna dolore Lorem. Occaecat voluptate quis est est qui eiusmod cillum mollit nisi.\r\n", + "registered": "2020-07-18T07:07:56 -02:00", + "latitude": -52.386326, + "longitude": 77.613358, + "tags": [ + "tempor", + "nisi", + "non", + "ea", + "pariatur", + "deserunt", + "excepteur" + ], + "friends": [ + { + "id": 0, + "name": "Newman Lowery" + }, + { + "id": 1, + "name": "Sherrie Moses" + }, + { + "id": 2, + "name": "Schmidt Humphrey" + } + ], + "greeting": "Hello, Sanchez Dejesus! You have 6 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5fbf395f69add3b2a", + "index": 89, + "guid": "9197a8fb-4edf-4c30-836e-4a6d9259e2d3", + "isActive": true, + "balance": "$2,386.91", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "blue", + "name": "Zimmerman Barnett", + "gender": "male", + "company": "COGENTRY", + "email": "zimmermanbarnett@cogentry.com", + "phone": "+1 (973) 479-2787", + "address": "720 Adelphi Street, Evergreen, Minnesota, 3195", + "about": "Exercitation magna cillum aliqua ipsum non eiusmod sit amet consequat. Dolor adipisicing reprehenderit ad elit nulla elit cupidatat esse. Nostrud est esse eu aliqua.\r\n", + "registered": "2015-02-04T12:00:42 -01:00", + "latitude": -54.731182, + "longitude": 73.839997, + "tags": [ + "consectetur", + "esse", + "laborum", + "eu", + "mollit", + "pariatur", + "pariatur" + ], + "friends": [ + { + "id": 0, + "name": "Evans Bartlett" + }, + { + "id": 1, + "name": "Graciela Sutton" + }, + { + "id": 2, + "name": "Manuela Buckley" + } + ], + "greeting": "Hello, Zimmerman Barnett! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee59fbc0b26a9772d9d", + "index": 90, + "guid": "b49ee567-0dcb-404b-aef5-11778393d05c", + "isActive": true, + "balance": "$1,128.60", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "brown", + "name": "Burt Griffith", + "gender": "male", + "company": "NAVIR", + "email": "burtgriffith@navir.com", + "phone": "+1 (895) 405-3234", + "address": "445 Broome Street, Newry, Iowa, 9577", + "about": "Ex nisi nostrud irure sint anim aliquip irure ullamco labore nisi enim. Ipsum ea exercitation reprehenderit officia non reprehenderit esse reprehenderit. Excepteur consectetur do occaecat voluptate nulla excepteur aute ipsum sit occaecat veniam est culpa. Voluptate labore adipisicing aliqua ipsum ex velit ex. Laborum eiusmod elit est deserunt proident do cillum magna nisi. Irure esse exercitation cillum commodo exercitation incididunt. Quis duis amet reprehenderit exercitation ea proident magna aliqua culpa.\r\n", + "registered": "2016-07-21T09:32:28 -02:00", + "latitude": 38.804136, + "longitude": -43.085181, + "tags": [ + "aute", + "id", + "nulla", + "minim", + "in", + "cillum", + "cupidatat" + ], + "friends": [ + { + "id": 0, + "name": "Weiss Parks" + }, + { + "id": 1, + "name": "Mills Tillman" + }, + { + "id": 2, + "name": "Frank Battle" + } + ], + "greeting": "Hello, Burt Griffith! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee575c9138dcef6cc81", + "index": 91, + "guid": "6563360e-e81d-4584-8355-5d3053ac3705", + "isActive": true, + "balance": "$3,159.26", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "brown", + "name": "Guy Hull", + "gender": "male", + "company": "CENTREE", + "email": "guyhull@centree.com", + "phone": "+1 (991) 420-3183", + "address": "376 Meserole Avenue, Lindisfarne, Maine, 7382", + "about": "Cupidatat id aute Lorem culpa qui aute tempor velit. Lorem nostrud ad nisi est elit occaecat sint commodo enim pariatur adipisicing est cupidatat do. Eu voluptate quis nulla culpa minim ex elit amet in fugiat. Qui anim qui culpa id excepteur voluptate quis aliquip exercitation duis nulla reprehenderit esse. Incididunt exercitation veniam reprehenderit minim.\r\n", + "registered": "2018-12-19T03:20:32 -01:00", + "latitude": -19.844991, + "longitude": 81.78538, + "tags": [ + "culpa", + "occaecat", + "exercitation", + "do", + "qui", + "laboris", + "aliquip" + ], + "friends": [ + { + "id": 0, + "name": "Donna Webster" + }, + { + "id": 1, + "name": "Doris Haney" + }, + { + "id": 2, + "name": "Callahan Russo" + } + ], + "greeting": "Hello, Guy Hull! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee504e9fcff8c70b60e", + "index": 92, + "guid": "fd6af655-6657-406b-a23d-53110c9cf95d", + "isActive": true, + "balance": "$3,014.49", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "blue", + "name": "Hanson Collier", + "gender": "male", + "company": "DIGIGENE", + "email": "hansoncollier@digigene.com", + "phone": "+1 (923) 430-2739", + "address": "770 Jerome Street, Bourg, Tennessee, 3339", + "about": "Consectetur et eiusmod tempor dolore et do enim dolor irure non nisi laborum commodo. Labore laborum sunt labore laborum quis anim in. Nostrud commodo sit ullamco labore laborum ea sit ea dolor nulla. Nostrud tempor enim eu eu excepteur commodo deserunt pariatur non ullamco.\r\n", + "registered": "2017-05-09T08:43:25 -02:00", + "latitude": -33.003299, + "longitude": 152.665408, + "tags": [ + "nulla", + "eiusmod", + "occaecat", + "elit", + "tempor", + "velit", + "nostrud" + ], + "friends": [ + { + "id": 0, + "name": "Ewing Sims" + }, + { + "id": 1, + "name": "Best Wells" + }, + { + "id": 2, + "name": "Elma Bentley" + } + ], + "greeting": "Hello, Hanson Collier! You have 9 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5896c587582655f0f", + "index": 93, + "guid": "5ad8579b-1c09-4bba-b3fa-e32d66e873bc", + "isActive": false, + "balance": "$3,147.76", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "brown", + "name": "Celeste Valencia", + "gender": "female", + "company": "INTERODEO", + "email": "celestevalencia@interodeo.com", + "phone": "+1 (920) 502-3800", + "address": "705 Cumberland Walk, Galesville, Palau, 6893", + "about": "Ullamco sunt nisi cupidatat exercitation dolor consequat voluptate do quis reprehenderit veniam. Voluptate amet laboris aliqua ad. Consequat ullamco nostrud do commodo. Est veniam laboris labore aute adipisicing nostrud anim tempor cillum tempor amet.\r\n", + "registered": "2016-05-23T10:27:52 -02:00", + "latitude": 5.941732, + "longitude": 40.384341, + "tags": [ + "ex", + "anim", + "in", + "consequat", + "sit", + "amet", + "incididunt" + ], + "friends": [ + { + "id": 0, + "name": "Foley Maxwell" + }, + { + "id": 1, + "name": "Hardin Carney" + }, + { + "id": 2, + "name": "Imogene Larsen" + } + ], + "greeting": "Hello, Celeste Valencia! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee592e5ec83c83124c5", + "index": 94, + "guid": "34e0221b-f9d3-48bc-b531-d74f4e93cd1d", + "isActive": false, + "balance": "$2,024.37", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "green", + "name": "Harvey Branch", + "gender": "male", + "company": "ENDIPIN", + "email": "harveybranch@endipin.com", + "phone": "+1 (818) 482-2914", + "address": "481 Carlton Avenue, Dubois, Kansas, 4340", + "about": "Dolore adipisicing cupidatat deserunt irure eu. Ad quis magna aliquip ad amet eiusmod cillum. Tempor culpa non laborum id tempor ea mollit fugiat ullamco. Sunt enim aute incididunt et tempor ex sit elit cillum anim magna aliquip elit irure. Nisi labore culpa dolor proident cupidatat dolore do reprehenderit et esse in. Ipsum magna esse consectetur cupidatat exercitation. Incididunt sint veniam excepteur aliqua enim quis nisi magna aliqua exercitation in ut nisi mollit.\r\n", + "registered": "2014-06-21T05:14:50 -02:00", + "latitude": 77.561294, + "longitude": 112.942251, + "tags": [ + "sint", + "dolor", + "aliquip", + "ullamco", + "Lorem", + "veniam", + "amet" + ], + "friends": [ + { + "id": 0, + "name": "Patricia Herman" + }, + { + "id": 1, + "name": "Violet Woodard" + }, + { + "id": 2, + "name": "Aguilar Bean" + } + ], + "greeting": "Hello, Harvey Branch! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5324676ddff7be548", + "index": 95, + "guid": "f7a97aa9-df39-409d-a4d1-ec3114a8542d", + "isActive": false, + "balance": "$1,259.84", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "blue", + "name": "Huber Woods", + "gender": "male", + "company": "BEZAL", + "email": "huberwoods@bezal.com", + "phone": "+1 (896) 448-2629", + "address": "266 Karweg Place, Comptche, American Samoa, 4929", + "about": "Id ex non magna deserunt consequat enim ea ea ipsum laborum et et sunt enim. Voluptate mollit reprehenderit nisi ullamco labore officia eiusmod dolor mollit. Excepteur exercitation et exercitation ullamco nulla dolore esse. Est nulla dolore ipsum eiusmod nostrud. Consequat duis adipisicing elit incididunt deserunt non.\r\n", + "registered": "2016-01-12T06:16:46 -01:00", + "latitude": 51.474235, + "longitude": -80.500097, + "tags": [ + "magna", + "sunt", + "ex", + "ullamco", + "nulla", + "proident", + "velit" + ], + "friends": [ + { + "id": 0, + "name": "Juana Montoya" + }, + { + "id": 1, + "name": "Judith Day" + }, + { + "id": 2, + "name": "Franks Ramsey" + } + ], + "greeting": "Hello, Huber Woods! You have 2 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee56b7bc7cbb0baafd5", + "index": 96, + "guid": "bbd56fca-faf5-4f4a-9360-3454afae5c74", + "isActive": true, + "balance": "$3,122.67", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "brown", + "name": "Susanne Simmons", + "gender": "female", + "company": "QUAILCOM", + "email": "susannesimmons@quailcom.com", + "phone": "+1 (825) 410-2659", + "address": "305 Bridge Street, Gila, South Carolina, 6751", + "about": "Veniam ut dolore sit aliquip et minim qui aliqua mollit ut. Tempor tempor esse sit magna laborum irure quis ad ad fugiat duis ea nulla. Ea ex et ullamco aliquip id amet anim consectetur incididunt irure sunt. Sit adipisicing duis ea nulla nisi excepteur reprehenderit consectetur laboris nisi duis exercitation laboris. Magna elit cupidatat occaecat ad.\r\n", + "registered": "2021-09-09T05:19:15 -02:00", + "latitude": -85.449409, + "longitude": 77.309044, + "tags": [ + "voluptate", + "ipsum", + "sunt", + "cupidatat", + "consectetur", + "est", + "non" + ], + "friends": [ + { + "id": 0, + "name": "Chan Underwood" + }, + { + "id": 1, + "name": "Mcclure Callahan" + }, + { + "id": 2, + "name": "Miranda Joyce" + } + ], + "greeting": "Hello, Susanne Simmons! You have 4 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee579be768295851f70", + "index": 97, + "guid": "e9a2b0fe-8f62-433d-bd41-1da1935c7a59", + "isActive": true, + "balance": "$3,573.15", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "green", + "name": "Felicia Shields", + "gender": "female", + "company": "SCENTY", + "email": "feliciashields@scenty.com", + "phone": "+1 (935) 547-2066", + "address": "347 Dennett Place, Oneida, Indiana, 7023", + "about": "Quis exercitation nulla minim anim eu. Voluptate commodo officia ad magna commodo sunt incididunt incididunt in ex pariatur. Lorem laborum dolore deserunt amet ea non minim laborum. Pariatur consectetur elit labore pariatur aute esse veniam anim qui culpa consectetur veniam. Dolore minim aliqua ex anim dolor. Nostrud ex reprehenderit officia sit et esse nostrud exercitation.\r\n", + "registered": "2016-01-10T12:31:35 -01:00", + "latitude": 26.281283, + "longitude": 113.533668, + "tags": [ + "velit", + "et", + "eiusmod", + "do", + "laborum", + "fugiat", + "enim" + ], + "friends": [ + { + "id": 0, + "name": "Cleveland Mcneil" + }, + { + "id": 1, + "name": "Curtis Gamble" + }, + { + "id": 2, + "name": "Morales Martin" + } + ], + "greeting": "Hello, Felicia Shields! You have 9 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee53e5dd235e8053c37", + "index": 98, + "guid": "8e221fd2-c515-4284-9fd4-a7775df1f2b4", + "isActive": true, + "balance": "$2,692.55", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "brown", + "name": "Mann Olsen", + "gender": "male", + "company": "COMTEST", + "email": "mannolsen@comtest.com", + "phone": "+1 (999) 536-3881", + "address": "532 Underhill Avenue, Layhill, District Of Columbia, 4860", + "about": "Duis enim voluptate ea minim occaecat tempor non non dolore eiusmod nisi magna. Tempor labore minim consequat esse nostrud qui nisi deserunt dolore nostrud aute ut proident. Aliqua quis mollit non consequat mollit fugiat mollit officia sunt.\r\n", + "registered": "2017-10-08T01:26:57 -02:00", + "latitude": 75.253375, + "longitude": -3.856333, + "tags": [ + "exercitation", + "dolor", + "mollit", + "ipsum", + "ullamco", + "consequat", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Lane Cote" + }, + { + "id": 1, + "name": "Day Shelton" + }, + { + "id": 2, + "name": "Mcfarland Vang" + } + ], + "greeting": "Hello, Mann Olsen! You have 1 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee59e9d3672b44a73c9", + "index": 99, + "guid": "aab2ebbf-b55b-49aa-9b09-2bcf008cc4a3", + "isActive": false, + "balance": "$3,809.99", + "picture": "http://placehold.it/32x32", + "age": 33, + "eyeColor": "blue", + "name": "Moore Charles", + "gender": "male", + "company": "LINGOAGE", + "email": "moorecharles@lingoage.com", + "phone": "+1 (928) 515-3795", + "address": "679 Falmouth Street, Sattley, Wyoming, 5050", + "about": "Amet eiusmod minim sit sunt nisi ex adipisicing duis id adipisicing sint. Irure qui dolor officia adipisicing laborum enim et eiusmod proident quis nisi eiusmod in irure. Esse voluptate proident labore sunt deserunt occaecat laboris non veniam qui irure minim elit.\r\n", + "registered": "2020-06-22T05:09:59 -02:00", + "latitude": -78.970897, + "longitude": 156.447467, + "tags": [ + "sint", + "magna", + "nostrud", + "duis", + "velit", + "nulla", + "consequat" + ], + "friends": [ + { + "id": 0, + "name": "Greer Workman" + }, + { + "id": 1, + "name": "Thomas Mclean" + }, + { + "id": 2, + "name": "Faith Morrow" + } + ], + "greeting": "Hello, Moore Charles! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee542c1a13a9a5bd8a4", + "index": 100, + "guid": "2e9f9a53-5cb0-48f7-95e6-2ee8c714b01e", + "isActive": false, + "balance": "$3,211.40", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "blue", + "name": "Fanny Hooper", + "gender": "female", + "company": "EXOSWITCH", + "email": "fannyhooper@exoswitch.com", + "phone": "+1 (805) 443-2141", + "address": "800 Diamond Street, Dunlo, Texas, 6239", + "about": "Sit amet velit adipisicing irure do culpa exercitation ipsum consectetur ut ullamco sint dolore do. Pariatur nostrud duis reprehenderit deserunt est tempor mollit. Labore nisi sit consequat esse Lorem elit sit voluptate irure est sit. Tempor dolor consequat non aliquip cillum excepteur nisi laboris.\r\n", + "registered": "2014-12-11T11:58:48 -01:00", + "latitude": -18.659487, + "longitude": -169.077468, + "tags": [ + "veniam", + "nostrud", + "ipsum", + "est", + "in", + "qui", + "fugiat" + ], + "friends": [ + { + "id": 0, + "name": "Waller Guerra" + }, + { + "id": 1, + "name": "Susana Sears" + }, + { + "id": 2, + "name": "Augusta Hardy" + } + ], + "greeting": "Hello, Fanny Hooper! You have 6 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5fe75862454c9af36", + "index": 101, + "guid": "43f72c32-48f0-4c56-ab4e-ca9e6d365954", + "isActive": false, + "balance": "$2,862.90", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "brown", + "name": "Burns Doyle", + "gender": "male", + "company": "ACCIDENCY", + "email": "burnsdoyle@accidency.com", + "phone": "+1 (872) 505-2075", + "address": "518 Vine Street, Day, Rhode Island, 9169", + "about": "Veniam ut deserunt sit aliquip fugiat sunt velit id pariatur eiusmod adipisicing ut deserunt. Laboris quis do ad ad ex nulla. Aliquip commodo id velit elit reprehenderit ad Lorem adipisicing aliquip anim incididunt anim Lorem. Reprehenderit minim enim est velit ad nulla eu est quis adipisicing ex irure sint. Nulla dolore consequat fugiat qui pariatur est in cillum amet id esse. Voluptate et ex nisi aliqua.\r\n", + "registered": "2018-07-24T01:37:19 -02:00", + "latitude": 63.416847, + "longitude": 168.31002, + "tags": [ + "ipsum", + "voluptate", + "est", + "nisi", + "Lorem", + "cupidatat", + "irure" + ], + "friends": [ + { + "id": 0, + "name": "Warner Cannon" + }, + { + "id": 1, + "name": "Diann Hamilton" + }, + { + "id": 2, + "name": "Cassie Brennan" + } + ], + "greeting": "Hello, Burns Doyle! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5ff778e41a61cb3c2", + "index": 102, + "guid": "53c08287-83e5-446f-82be-e1f15c36c33c", + "isActive": true, + "balance": "$1,762.98", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "brown", + "name": "Kristen Cruz", + "gender": "female", + "company": "EMOLTRA", + "email": "kristencruz@emoltra.com", + "phone": "+1 (811) 503-3184", + "address": "460 Seba Avenue, Craig, Louisiana, 6458", + "about": "Aute nulla incididunt aute non culpa tempor. Officia cillum incididunt enim quis qui minim non laborum ad. Ad excepteur pariatur in in adipisicing nisi esse. Duis consequat ipsum velit sint consectetur non do ad velit duis. Ad laboris sit sint qui ad duis.\r\n", + "registered": "2018-09-22T03:23:54 -02:00", + "latitude": -3.598782, + "longitude": -157.623, + "tags": [ + "adipisicing", + "incididunt", + "Lorem", + "ad", + "consequat", + "excepteur", + "esse" + ], + "friends": [ + { + "id": 0, + "name": "Colon Cabrera" + }, + { + "id": 1, + "name": "Reilly Hogan" + }, + { + "id": 2, + "name": "Baxter Pitts" + } + ], + "greeting": "Hello, Kristen Cruz! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee58978c913fd05de17", + "index": 103, + "guid": "56ce0615-4cb0-4fbf-b1fb-3dc253fa84ef", + "isActive": true, + "balance": "$3,448.36", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "blue", + "name": "Carmen Merritt", + "gender": "female", + "company": "NEWCUBE", + "email": "carmenmerritt@newcube.com", + "phone": "+1 (947) 497-3698", + "address": "732 Pilling Street, Macdona, Illinois, 7468", + "about": "Aute non cillum ad sunt qui incididunt nulla et mollit mollit. Nostrud officia laborum tempor quis deserunt aute duis nostrud cillum consectetur. Aute magna officia magna minim dolor ipsum non est Lorem dolore. Labore dolore laboris qui officia. Proident irure aliqua occaecat eu nisi cupidatat excepteur dolor amet nostrud sint consectetur quis.\r\n", + "registered": "2017-11-28T04:52:57 -01:00", + "latitude": 36.670108, + "longitude": -173.405707, + "tags": [ + "ex", + "tempor", + "labore", + "nostrud", + "ex", + "occaecat", + "ut" + ], + "friends": [ + { + "id": 0, + "name": "Rios Davenport" + }, + { + "id": 1, + "name": "Berg Burks" + }, + { + "id": 2, + "name": "Jennifer Roberts" + } + ], + "greeting": "Hello, Carmen Merritt! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5fee688c4e4c84984", + "index": 104, + "guid": "048dcbfa-6a51-40e1-85fd-8705b6641a10", + "isActive": true, + "balance": "$3,726.61", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "green", + "name": "Sarah Mccarty", + "gender": "female", + "company": "ENOMEN", + "email": "sarahmccarty@enomen.com", + "phone": "+1 (816) 595-3452", + "address": "861 Tech Place, Allensworth, Guam, 2509", + "about": "Velit aute est sit nisi quis excepteur consectetur sint elit veniam ad anim. Nulla sint ut est tempor velit dolor. Voluptate magna quis ut id excepteur deserunt excepteur id officia.\r\n", + "registered": "2016-07-17T07:11:27 -02:00", + "latitude": 31.270807, + "longitude": 106.572456, + "tags": [ + "aliquip", + "voluptate", + "deserunt", + "eiusmod", + "officia", + "sunt", + "est" + ], + "friends": [ + { + "id": 0, + "name": "Helene Delacruz" + }, + { + "id": 1, + "name": "Lang Vega" + }, + { + "id": 2, + "name": "Nichols Jarvis" + } + ], + "greeting": "Hello, Sarah Mccarty! You have 4 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5b24846b1bfddb800", + "index": 105, + "guid": "ead72d6a-52ff-452f-8ebb-5d732ccf53ff", + "isActive": false, + "balance": "$1,796.53", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "brown", + "name": "Albert Singleton", + "gender": "male", + "company": "JASPER", + "email": "albertsingleton@jasper.com", + "phone": "+1 (944) 442-2620", + "address": "281 Utica Avenue, Concho, New York, 5728", + "about": "Amet tempor culpa aute nisi nisi et ad enim minim tempor excepteur quis dolore. Non commodo nisi mollit occaecat. Et in nostrud eiusmod anim magna magna ex in nostrud nostrud sint. Consequat incididunt cillum proident sunt. Duis fugiat reprehenderit labore laborum proident exercitation consectetur tempor elit culpa nulla consequat voluptate proident. Eiusmod cillum fugiat tempor irure voluptate minim culpa labore mollit ex nostrud veniam sunt.\r\n", + "registered": "2019-06-16T10:41:09 -02:00", + "latitude": -56.50538, + "longitude": 123.835799, + "tags": [ + "pariatur", + "velit", + "qui", + "veniam", + "occaecat", + "deserunt", + "deserunt" + ], + "friends": [ + { + "id": 0, + "name": "Angelique Williamson" + }, + { + "id": 1, + "name": "Rollins Allen" + }, + { + "id": 2, + "name": "Eunice Roberson" + } + ], + "greeting": "Hello, Albert Singleton! You have 6 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5a512597622f8405c", + "index": 106, + "guid": "29bd21fe-bb3e-42f0-82e8-1a4cc8eb4782", + "isActive": false, + "balance": "$2,399.49", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "blue", + "name": "Darla Cummings", + "gender": "female", + "company": "EXOPLODE", + "email": "darlacummings@exoplode.com", + "phone": "+1 (809) 466-2125", + "address": "355 Morton Street, Florence, Colorado, 7993", + "about": "Cillum eu aliqua in sunt pariatur aute est culpa cupidatat aliquip amet et et ad. Minim non ipsum Lorem occaecat mollit ad deserunt in. Ad aute veniam nulla ut fugiat nisi ex adipisicing.\r\n", + "registered": "2017-02-20T12:58:33 -01:00", + "latitude": -50.399431, + "longitude": 1.746477, + "tags": [ + "culpa", + "nostrud", + "reprehenderit", + "voluptate", + "qui", + "ex", + "quis" + ], + "friends": [ + { + "id": 0, + "name": "Lourdes Sandoval" + }, + { + "id": 1, + "name": "Teresa Bender" + }, + { + "id": 2, + "name": "House Guy" + } + ], + "greeting": "Hello, Darla Cummings! You have 10 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5646a712e42e42d54", + "index": 107, + "guid": "8ed48af3-9867-42da-9f11-6e71b9fcdfc7", + "isActive": true, + "balance": "$1,877.89", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Mayo Chavez", + "gender": "male", + "company": "IMAGEFLOW", + "email": "mayochavez@imageflow.com", + "phone": "+1 (897) 517-3214", + "address": "524 Garden Street, Elliston, Michigan, 5221", + "about": "Ad veniam veniam aliqua officia minim magna. Ullamco minim labore in consequat aliquip aute consequat do ex enim est minim quis Lorem. Ea nostrud proident incididunt labore ut. Sit esse ad nostrud exercitation consectetur et exercitation nisi do nostrud. Nisi fugiat sint sunt eu sit. Sint adipisicing reprehenderit do sit commodo quis duis qui nisi anim elit.\r\n", + "registered": "2018-01-14T05:52:16 -01:00", + "latitude": -73.533217, + "longitude": 83.232772, + "tags": [ + "ullamco", + "quis", + "veniam", + "non", + "anim", + "laborum", + "cupidatat" + ], + "friends": [ + { + "id": 0, + "name": "Therese Knapp" + }, + { + "id": 1, + "name": "York Randall" + }, + { + "id": 2, + "name": "Agnes Perez" + } + ], + "greeting": "Hello, Mayo Chavez! You have 10 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5f4e4b3ca1015a2e6", + "index": 108, + "guid": "0f187167-29f8-41a7-9da9-701e4b75007f", + "isActive": false, + "balance": "$2,346.21", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Moon Grimes", + "gender": "male", + "company": "EVENTEX", + "email": "moongrimes@eventex.com", + "phone": "+1 (878) 427-2258", + "address": "400 Hamilton Walk, Caroline, Vermont, 6144", + "about": "Officia ut laboris ipsum qui officia laborum. Incididunt ex ad nulla consectetur deserunt. Ea fugiat adipisicing sint ea irure ad voluptate dolor qui dolore commodo labore. Enim elit cillum ut esse do sunt. Dolore laboris cillum ut aliqua id in id non officia in consequat anim duis. Et sit incididunt nostrud enim aute proident amet occaecat officia Lorem aute aute pariatur.\r\n", + "registered": "2021-06-04T05:52:41 -02:00", + "latitude": -16.977217, + "longitude": 90.202875, + "tags": [ + "cupidatat", + "aute", + "laboris", + "proident", + "excepteur", + "elit", + "aliqua" + ], + "friends": [ + { + "id": 0, + "name": "Jasmine Mccullough" + }, + { + "id": 1, + "name": "Della Campos" + }, + { + "id": 2, + "name": "Savage Burnett" + } + ], + "greeting": "Hello, Moon Grimes! You have 9 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5dc91e2cd0ccd66c6", + "index": 109, + "guid": "738ae92a-28cb-4f10-8dcb-a036cfac0d9e", + "isActive": false, + "balance": "$2,367.15", + "picture": "http://placehold.it/32x32", + "age": 26, + "eyeColor": "brown", + "name": "Griffin Richardson", + "gender": "male", + "company": "ARTIQ", + "email": "griffinrichardson@artiq.com", + "phone": "+1 (896) 501-2597", + "address": "552 Celeste Court, Limestone, New Jersey, 282", + "about": "Ea officia quis aliqua dolor. Voluptate dolor qui tempor quis esse veniam non aliquip sunt mollit aute tempor. Non Lorem occaecat amet excepteur ipsum officia ipsum fugiat ad incididunt occaecat reprehenderit et. Do in id tempor consequat.\r\n", + "registered": "2021-04-27T08:03:39 -02:00", + "latitude": -19.972379, + "longitude": 20.444188, + "tags": [ + "in", + "magna", + "amet", + "consequat", + "amet", + "exercitation", + "qui" + ], + "friends": [ + { + "id": 0, + "name": "Peggy Santana" + }, + { + "id": 1, + "name": "Stella Bond" + }, + { + "id": 2, + "name": "Serena Tran" + } + ], + "greeting": "Hello, Griffin Richardson! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee56ba17ed837db4866", + "index": 110, + "guid": "f789eb81-63a5-4229-8c09-aff43d65ee29", + "isActive": true, + "balance": "$1,639.00", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "green", + "name": "Carlene Evans", + "gender": "female", + "company": "BALOOBA", + "email": "carleneevans@balooba.com", + "phone": "+1 (801) 479-2236", + "address": "219 Kenmore Terrace, Dawn, Nebraska, 3489", + "about": "Ipsum magna laborum incididunt consequat laborum aute anim magna id aliquip Lorem pariatur pariatur. Ad deserunt ipsum tempor ut dolore deserunt ad aute cupidatat minim enim mollit veniam. In sit ut reprehenderit ad id ut in enim qui. Nisi ea tempor id pariatur ullamco.\r\n", + "registered": "2015-02-07T03:57:54 -01:00", + "latitude": -14.520093, + "longitude": 67.229928, + "tags": [ + "excepteur", + "do", + "laborum", + "minim", + "aliquip", + "qui", + "sint" + ], + "friends": [ + { + "id": 0, + "name": "Harrison Hinton" + }, + { + "id": 1, + "name": "Sasha Mcclure" + }, + { + "id": 2, + "name": "May Oneill" + } + ], + "greeting": "Hello, Carlene Evans! You have 8 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5693fc5bb2e3e9102", + "index": 111, + "guid": "a8256fbc-0c8d-4a63-8a06-d424a4531dbc", + "isActive": false, + "balance": "$1,770.66", + "picture": "http://placehold.it/32x32", + "age": 32, + "eyeColor": "green", + "name": "Tracey Goodwin", + "gender": "female", + "company": "ANARCO", + "email": "traceygoodwin@anarco.com", + "phone": "+1 (895) 506-3994", + "address": "852 Bath Avenue, Neahkahnie, North Carolina, 546", + "about": "Aute aliqua reprehenderit exercitation non commodo nostrud nostrud nisi magna. Adipisicing amet esse magna aliquip sit dolor eu. Incididunt est dolor exercitation nostrud do aliqua veniam commodo minim. Enim officia reprehenderit ut sunt. Dolore nulla mollit nostrud cupidatat amet do culpa pariatur dolor dolore deserunt cupidatat.\r\n", + "registered": "2020-01-24T12:09:40 -01:00", + "latitude": -8.860506, + "longitude": -124.993792, + "tags": [ + "adipisicing", + "et", + "proident", + "cillum", + "duis", + "mollit", + "non" + ], + "friends": [ + { + "id": 0, + "name": "Lucas Eaton" + }, + { + "id": 1, + "name": "Christy Shepherd" + }, + { + "id": 2, + "name": "Brittany Ware" + } + ], + "greeting": "Hello, Tracey Goodwin! You have 7 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee598277596428abcaa", + "index": 112, + "guid": "5fe8db13-a665-4a85-893f-9f7949761da9", + "isActive": false, + "balance": "$1,381.51", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "brown", + "name": "Concetta Talley", + "gender": "female", + "company": "PRIMORDIA", + "email": "concettatalley@primordia.com", + "phone": "+1 (833) 464-3057", + "address": "708 Verona Place, Rosewood, California, 9664", + "about": "Deserunt sit ea consectetur sunt voluptate eiusmod sit do magna in magna. Aliquip consequat proident dolor enim. Anim excepteur laboris velit aliqua aute sit. Culpa mollit Lorem deserunt amet ut duis nulla velit ea. Duis voluptate labore exercitation occaecat. Aliqua nisi cillum velit ut eu in.\r\n", + "registered": "2016-06-11T01:52:50 -02:00", + "latitude": 2.891685, + "longitude": -146.243358, + "tags": [ + "laboris", + "ullamco", + "consectetur", + "ipsum", + "ex", + "do", + "cillum" + ], + "friends": [ + { + "id": 0, + "name": "England Howard" + }, + { + "id": 1, + "name": "Kathleen Matthews" + }, + { + "id": 2, + "name": "Herminia Cleveland" + } + ], + "greeting": "Hello, Concetta Talley! You have 6 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5a308124c877dd354", + "index": 113, + "guid": "6e965ad6-ae69-4570-adfc-76b12a7061e6", + "isActive": true, + "balance": "$2,182.02", + "picture": "http://placehold.it/32x32", + "age": 37, + "eyeColor": "blue", + "name": "Misty Nieves", + "gender": "female", + "company": "KNOWLYSIS", + "email": "mistynieves@knowlysis.com", + "phone": "+1 (973) 426-2333", + "address": "284 Seaview Court, Coalmont, Virgin Islands, 4581", + "about": "Ullamco nisi tempor veniam nulla tempor irure incididunt voluptate Lorem labore et duis sit id. Aute adipisicing consectetur deserunt magna anim enim non non dolor non in irure. Consectetur irure officia culpa laboris. Magna sint aliquip velit magna ad.\r\n", + "registered": "2017-04-07T05:20:24 -02:00", + "latitude": -89.27099, + "longitude": -51.65054, + "tags": [ + "Lorem", + "veniam", + "labore", + "commodo", + "eiusmod", + "aliqua", + "pariatur" + ], + "friends": [ + { + "id": 0, + "name": "Mayra Yang" + }, + { + "id": 1, + "name": "Kristie Trujillo" + }, + { + "id": 2, + "name": "Melton Bruce" + } + ], + "greeting": "Hello, Misty Nieves! You have 10 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5a7c3133806960204", + "index": 114, + "guid": "402ab5d2-3ce9-43e0-9090-2faed8749301", + "isActive": false, + "balance": "$1,154.54", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "green", + "name": "Jana Hurst", + "gender": "female", + "company": "CUIZINE", + "email": "janahurst@cuizine.com", + "phone": "+1 (828) 537-3567", + "address": "965 Baltic Street, Kempton, Kentucky, 3125", + "about": "Occaecat ea duis proident commodo nostrud tempor anim. Ad cillum magna esse cillum ut nostrud veniam id elit cillum quis occaecat. Sit fugiat dolore Lorem minim nisi occaecat. Ad ea esse labore ut veniam dolor dolore tempor amet incididunt fugiat fugiat nulla. Veniam do consequat excepteur sint reprehenderit magna do sint ad commodo irure laboris sunt. Ut ut Lorem id consectetur ut in nisi ex Lorem. Laborum mollit fugiat laboris magna culpa eu reprehenderit ex commodo eu irure dolore irure.\r\n", + "registered": "2014-03-04T08:49:46 -01:00", + "latitude": -2.153494, + "longitude": 28.964035, + "tags": [ + "ea", + "cupidatat", + "dolor", + "labore", + "et", + "officia", + "esse" + ], + "friends": [ + { + "id": 0, + "name": "Pollard Williams" + }, + { + "id": 1, + "name": "Noemi Bailey" + }, + { + "id": 2, + "name": "Crane Gould" + } + ], + "greeting": "Hello, Jana Hurst! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee58419e33a2e4071c6", + "index": 115, + "guid": "15cb2af5-013a-4c3e-8cb5-e00ec62d6b23", + "isActive": false, + "balance": "$2,929.10", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "brown", + "name": "Davenport Jacobs", + "gender": "male", + "company": "VIASIA", + "email": "davenportjacobs@viasia.com", + "phone": "+1 (834) 426-2243", + "address": "807 Croton Loop, Chumuckla, Alabama, 9359", + "about": "Elit Lorem nulla consequat do ex ipsum culpa ut aute mollit veniam magna in laborum. Ipsum elit in eiusmod cillum. Ex voluptate aliqua Lorem minim est dolor nisi aute ad anim officia Lorem consequat. Laborum velit velit adipisicing nostrud amet aliquip velit. Fugiat enim ipsum qui velit non laborum quis minim aute qui veniam.\r\n", + "registered": "2016-03-30T10:16:18 -02:00", + "latitude": 45.568938, + "longitude": 151.524098, + "tags": [ + "deserunt", + "non", + "quis", + "nisi", + "id", + "ut", + "ad" + ], + "friends": [ + { + "id": 0, + "name": "Kaufman Meadows" + }, + { + "id": 1, + "name": "Sherman Townsend" + }, + { + "id": 2, + "name": "Jeanie Walton" + } + ], + "greeting": "Hello, Davenport Jacobs! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee57297824b72767410", + "index": 116, + "guid": "012ab9cc-2a05-46f9-8066-c6b5261135e9", + "isActive": true, + "balance": "$2,075.74", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "green", + "name": "Villarreal Watson", + "gender": "male", + "company": "SKINSERVE", + "email": "villarrealwatson@skinserve.com", + "phone": "+1 (988) 545-2746", + "address": "204 Butler Street, Seymour, Alaska, 8598", + "about": "Reprehenderit ipsum dolor eu do aliquip esse duis sit. Sit excepteur anim ea laborum occaecat sunt minim ut. Nisi fugiat ullamco et eiusmod aute ipsum duis ipsum non qui. Officia nulla id laborum et ex exercitation. Ut Lorem voluptate id exercitation ad dolore.\r\n", + "registered": "2019-10-29T08:13:49 -01:00", + "latitude": 66.95015, + "longitude": -110.723078, + "tags": [ + "Lorem", + "irure", + "veniam", + "minim", + "deserunt", + "consectetur", + "ea" + ], + "friends": [ + { + "id": 0, + "name": "Whitfield Pacheco" + }, + { + "id": 1, + "name": "Ava Hendrix" + }, + { + "id": 2, + "name": "Pansy Armstrong" + } + ], + "greeting": "Hello, Villarreal Watson! You have 2 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5a1804e5cf5c8a2da", + "index": 117, + "guid": "7d96956e-8021-4805-83af-f46eae774ed8", + "isActive": false, + "balance": "$3,506.71", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "brown", + "name": "Key Witt", + "gender": "male", + "company": "RETRACK", + "email": "keywitt@retrack.com", + "phone": "+1 (997) 549-3121", + "address": "560 Howard Place, Naomi, Missouri, 1851", + "about": "Tempor dolor adipisicing elit anim ipsum pariatur excepteur minim magna ut ea eiusmod enim et. Commodo sunt minim eu tempor in pariatur do sit sit ea voluptate duis nisi anim. Commodo magna voluptate enim duis enim pariatur sunt Lorem ea amet reprehenderit velit. Esse in consectetur anim nostrud deserunt.\r\n", + "registered": "2021-08-14T05:58:02 -02:00", + "latitude": 84.717684, + "longitude": 58.624277, + "tags": [ + "ut", + "velit", + "dolore", + "nulla", + "veniam", + "est", + "incididunt" + ], + "friends": [ + { + "id": 0, + "name": "Benson Atkinson" + }, + { + "id": 1, + "name": "Mooney Justice" + }, + { + "id": 2, + "name": "Madeline Simpson" + } + ], + "greeting": "Hello, Key Witt! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee523f1a061a19a746a", + "index": 118, + "guid": "8c0f8ef4-1252-41fa-b2ca-43cfc3faecb4", + "isActive": true, + "balance": "$3,394.22", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "brown", + "name": "Reyna Hess", + "gender": "female", + "company": "SENMAO", + "email": "reynahess@senmao.com", + "phone": "+1 (968) 556-2373", + "address": "464 Bliss Terrace, Rose, Hawaii, 5301", + "about": "Velit qui commodo in ad eu nostrud. Et proident ipsum esse minim ut labore id laboris non. Exercitation dolor ex in aute aute voluptate laboris non. Dolor duis id enim veniam duis enim adipisicing quis esse. Occaecat elit veniam nisi id labore.\r\n", + "registered": "2016-01-13T04:22:55 -01:00", + "latitude": 89.970629, + "longitude": -73.826497, + "tags": [ + "ex", + "aliqua", + "occaecat", + "mollit", + "tempor", + "deserunt", + "aliqua" + ], + "friends": [ + { + "id": 0, + "name": "Bessie Blankenship" + }, + { + "id": 1, + "name": "Price Wynn" + }, + { + "id": 2, + "name": "Pate Mcdonald" + } + ], + "greeting": "Hello, Reyna Hess! You have 5 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee51204288e04108b36", + "index": 119, + "guid": "8f68e29f-b1ca-4a72-9ced-b3bb765c940e", + "isActive": false, + "balance": "$3,703.63", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "brown", + "name": "Little Harris", + "gender": "male", + "company": "ASSISTIA", + "email": "littleharris@assistia.com", + "phone": "+1 (855) 410-3519", + "address": "860 Monroe Street, Brazos, Ohio, 9182", + "about": "Sunt cillum non Lorem irure dolor commodo duis aliquip velit. Dolor consequat laboris id tempor pariatur eu aute Lorem laborum eiusmod ipsum. Et nisi esse sit velit incididunt est non aute officia esse cupidatat sint aliquip. Pariatur laborum proident exercitation veniam est velit irure reprehenderit magna anim fugiat. Incididunt occaecat ex ex id laboris Lorem laborum ipsum enim aute nulla. Fugiat qui aute consectetur magna ea exercitation. Id sunt ex elit eiusmod reprehenderit sunt voluptate labore occaecat esse magna cupidatat amet.\r\n", + "registered": "2017-07-21T12:07:11 -02:00", + "latitude": -14.944496, + "longitude": 69.076653, + "tags": [ + "in", + "duis", + "in", + "aliqua", + "ullamco", + "aliqua", + "tempor" + ], + "friends": [ + { + "id": 0, + "name": "Mcdaniel Drake" + }, + { + "id": 1, + "name": "Glass Odom" + }, + { + "id": 2, + "name": "Greta Henry" + } + ], + "greeting": "Hello, Little Harris! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5368f1985841bd63e", + "index": 120, + "guid": "6be4dcaf-3903-416d-b30e-7433e5e18f87", + "isActive": true, + "balance": "$2,863.43", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "brown", + "name": "Burch Sargent", + "gender": "male", + "company": "LYRICHORD", + "email": "burchsargent@lyrichord.com", + "phone": "+1 (832) 421-2723", + "address": "651 Logan Street, Cherokee, Federated States Of Micronesia, 7175", + "about": "Sit et aliquip ad nostrud amet eiusmod. Voluptate nisi commodo consectetur nulla pariatur laborum Lorem quis ea. Minim consectetur sint enim mollit eu eu esse incididunt labore dolor ad. Tempor commodo officia magna eu elit dolor ipsum adipisicing veniam. Laborum qui cupidatat tempor eu adipisicing Lorem ullamco officia do nulla. Ut nulla irure veniam minim ad enim irure aliquip amet nostrud. Veniam ex cupidatat do minim sint.\r\n", + "registered": "2021-04-19T12:03:54 -02:00", + "latitude": 24.397213, + "longitude": 128.277616, + "tags": [ + "aliqua", + "laboris", + "culpa", + "commodo", + "id", + "veniam", + "exercitation" + ], + "friends": [ + { + "id": 0, + "name": "Magdalena Dodson" + }, + { + "id": 1, + "name": "Louisa Mcbride" + }, + { + "id": 2, + "name": "Marjorie Douglas" + } + ], + "greeting": "Hello, Burch Sargent! You have 8 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5f1c5804b47fdd710", + "index": 121, + "guid": "f88f3284-015f-4d80-baf8-3601efa9603a", + "isActive": false, + "balance": "$1,727.12", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "green", + "name": "Shanna Jennings", + "gender": "female", + "company": "DANJA", + "email": "shannajennings@danja.com", + "phone": "+1 (998) 567-3816", + "address": "736 Harrison Avenue, Ferney, New Hampshire, 6444", + "about": "Aliquip cillum et irure excepteur mollit amet excepteur voluptate enim sit. Dolore commodo minim incididunt occaecat non. Enim pariatur qui aute quis commodo mollit exercitation labore consequat. Veniam Lorem do deserunt enim in excepteur. Excepteur magna non et in et consectetur irure cillum.\r\n", + "registered": "2016-03-21T08:56:43 -01:00", + "latitude": -33.174549, + "longitude": 175.502597, + "tags": [ + "excepteur", + "aute", + "ea", + "non", + "ut", + "culpa", + "enim" + ], + "friends": [ + { + "id": 0, + "name": "Glenna Mcguire" + }, + { + "id": 1, + "name": "Bruce Ayers" + }, + { + "id": 2, + "name": "Loraine Rutledge" + } + ], + "greeting": "Hello, Shanna Jennings! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee55b8d496ef84e3b49", + "index": 122, + "guid": "6f8c48b8-fcf7-4ea2-b131-ba6c215b1b9d", + "isActive": false, + "balance": "$3,478.45", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "green", + "name": "Hull Gay", + "gender": "male", + "company": "GOKO", + "email": "hullgay@goko.com", + "phone": "+1 (960) 515-2406", + "address": "154 Catherine Street, Gouglersville, Utah, 3057", + "about": "Anim dolore id enim ipsum laboris pariatur cupidatat. Velit dolor fugiat commodo nisi eu enim eiusmod cupidatat ex est eu consequat labore. Ex cillum nostrud dolor officia qui.\r\n", + "registered": "2015-01-18T06:51:50 -01:00", + "latitude": -3.326571, + "longitude": 6.706675, + "tags": [ + "veniam", + "amet", + "ea", + "ullamco", + "officia", + "proident", + "nulla" + ], + "friends": [ + { + "id": 0, + "name": "Oneill Webb" + }, + { + "id": 1, + "name": "Goff Moss" + }, + { + "id": 2, + "name": "Lois Bowman" + } + ], + "greeting": "Hello, Hull Gay! You have 10 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee50bc2862d3a72074d", + "index": 123, + "guid": "39e76b7d-cf55-46c2-987b-41d36de59cac", + "isActive": true, + "balance": "$1,046.69", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "blue", + "name": "Lancaster Langley", + "gender": "male", + "company": "ESCHOIR", + "email": "lancasterlangley@eschoir.com", + "phone": "+1 (802) 454-3255", + "address": "673 Woods Place, Waterloo, Pennsylvania, 6059", + "about": "Ex tempor do culpa ut ullamco enim laborum esse nostrud consectetur. Duis culpa ea commodo enim. Aliqua exercitation velit nisi do culpa sunt quis labore laboris dolore qui sit labore cillum. Anim fugiat laborum reprehenderit mollit tempor pariatur irure elit incididunt esse do. Duis enim consequat eu aliqua commodo pariatur officia et. Aute sint do in deserunt ex reprehenderit.\r\n", + "registered": "2020-03-06T01:51:07 -01:00", + "latitude": 61.468845, + "longitude": 79.399766, + "tags": [ + "officia", + "fugiat", + "aute", + "voluptate", + "incididunt", + "laboris", + "duis" + ], + "friends": [ + { + "id": 0, + "name": "Vargas Marshall" + }, + { + "id": 1, + "name": "Ayers Frazier" + }, + { + "id": 2, + "name": "Harding Farrell" + } + ], + "greeting": "Hello, Lancaster Langley! You have 3 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5d357af8dfbf142d8", + "index": 124, + "guid": "f0e805b1-a888-4d21-b19c-414bd4395ef7", + "isActive": false, + "balance": "$2,441.11", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "brown", + "name": "Brady Jensen", + "gender": "male", + "company": "ASSURITY", + "email": "bradyjensen@assurity.com", + "phone": "+1 (991) 443-3956", + "address": "421 Norwood Avenue, Katonah, North Dakota, 7158", + "about": "Dolore sit nulla cillum ipsum labore eiusmod ullamco irure dolor velit. Voluptate fugiat ex quis ex magna est amet do veniam laboris eiusmod nulla. Veniam eiusmod ea et magna duis Lorem minim. Officia cillum laborum enim anim ea dolore veniam cupidatat amet culpa. Laborum minim eu qui elit elit officia id. Dolore elit et magna est laboris pariatur. Nisi dolore ea nostrud fugiat do cupidatat ullamco fugiat.\r\n", + "registered": "2020-10-30T12:18:37 -01:00", + "latitude": 84.411873, + "longitude": 45.44738, + "tags": [ + "esse", + "nulla", + "anim", + "culpa", + "dolore", + "nisi", + "sunt" + ], + "friends": [ + { + "id": 0, + "name": "Kelli Nolan" + }, + { + "id": 1, + "name": "Soto Oconnor" + }, + { + "id": 2, + "name": "Dale Watts" + } + ], + "greeting": "Hello, Brady Jensen! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5345a52e9c6029fbe", + "index": 125, + "guid": "7e20f6b3-5f35-4447-a15f-aaed93bf70cc", + "isActive": false, + "balance": "$2,543.84", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "green", + "name": "Suzette Prince", + "gender": "female", + "company": "OPTIQUE", + "email": "suzetteprince@optique.com", + "phone": "+1 (912) 466-3676", + "address": "276 Lloyd Street, Rivers, Delaware, 7210", + "about": "Laborum ipsum nostrud ea id enim et veniam ex fugiat. Anim do enim irure aliqua anim adipisicing occaecat ea laboris duis ea. Aliquip anim voluptate tempor magna irure laboris culpa aliqua duis et aliqua sunt veniam cupidatat. Quis consectetur cupidatat in mollit velit ad quis incididunt velit culpa qui nisi proident culpa. Nostrud mollit ullamco consequat labore laboris laborum duis elit do id elit. Commodo cupidatat id officia adipisicing anim. Voluptate nisi elit proident nostrud aliqua quis eiusmod do nulla aliqua.\r\n", + "registered": "2017-07-08T12:06:37 -02:00", + "latitude": -27.095244, + "longitude": -2.456461, + "tags": [ + "aute", + "do", + "est", + "occaecat", + "occaecat", + "nulla", + "excepteur" + ], + "friends": [ + { + "id": 0, + "name": "Chapman Burris" + }, + { + "id": 1, + "name": "Nona Frye" + }, + { + "id": 2, + "name": "Moody Bush" + } + ], + "greeting": "Hello, Suzette Prince! You have 10 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5916a7939844201f9", + "index": 126, + "guid": "00c8baba-608b-4483-bb86-a0cad75db673", + "isActive": false, + "balance": "$3,274.41", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "brown", + "name": "Carey Best", + "gender": "female", + "company": "FROSNEX", + "email": "careybest@frosnex.com", + "phone": "+1 (944) 545-3332", + "address": "582 Schenck Place, Hasty, Nevada, 6195", + "about": "Consectetur enim magna dolore aliquip excepteur sint. Eu dolore do laboris dolor occaecat culpa. Adipisicing exercitation nulla officia esse nulla. Adipisicing voluptate cupidatat cupidatat id. Aliquip eu ad amet dolor aute pariatur mollit irure tempor anim ipsum duis occaecat. Duis excepteur adipisicing occaecat sit sit qui dolor labore commodo cupidatat duis.\r\n", + "registered": "2017-07-26T06:37:33 -02:00", + "latitude": 11.191285, + "longitude": -47.664887, + "tags": [ + "culpa", + "nulla", + "veniam", + "exercitation", + "ea", + "proident", + "occaecat" + ], + "friends": [ + { + "id": 0, + "name": "Kenya Ferrell" + }, + { + "id": 1, + "name": "Nancy White" + }, + { + "id": 2, + "name": "Debora Floyd" + } + ], + "greeting": "Hello, Carey Best! You have 2 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5a0bdc2880cf01ee9", + "index": 127, + "guid": "765f484b-8e73-4731-a05e-1bc8d05eeba3", + "isActive": true, + "balance": "$2,645.68", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "green", + "name": "Dixon Baxter", + "gender": "male", + "company": "LUNCHPAD", + "email": "dixonbaxter@lunchpad.com", + "phone": "+1 (954) 413-2958", + "address": "757 Oceanview Avenue, Tuskahoma, Montana, 4014", + "about": "Eu tempor minim nisi veniam adipisicing pariatur adipisicing reprehenderit non. Pariatur aliqua nostrud aliqua aliquip aliqua officia deserunt fugiat quis laborum dolore. Duis mollit cupidatat reprehenderit fugiat voluptate cillum anim consequat consectetur nisi eiusmod. Ad in et nisi exercitation enim pariatur ullamco.\r\n", + "registered": "2017-09-09T05:38:33 -02:00", + "latitude": -57.733934, + "longitude": 118.386419, + "tags": [ + "do", + "eu", + "laborum", + "adipisicing", + "eiusmod", + "aliqua", + "enim" + ], + "friends": [ + { + "id": 0, + "name": "Evangeline Conrad" + }, + { + "id": 1, + "name": "Stone House" + }, + { + "id": 2, + "name": "Charlene Hoffman" + } + ], + "greeting": "Hello, Dixon Baxter! You have 4 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee55caa11f9ec247384", + "index": 128, + "guid": "ceb44e85-56ca-474e-96a6-689002201e18", + "isActive": true, + "balance": "$2,132.56", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "green", + "name": "Blankenship Nash", + "gender": "male", + "company": "ANDRYX", + "email": "blankenshipnash@andryx.com", + "phone": "+1 (831) 572-2357", + "address": "277 Caton Avenue, Salix, Arizona, 3182", + "about": "Elit ipsum proident cillum aliqua dolor aute dolore aliquip. Consectetur officia amet dolore aute. Dolore deserunt ipsum non do occaecat pariatur ipsum excepteur eu nulla.\r\n", + "registered": "2019-11-11T09:37:57 -01:00", + "latitude": -42.029524, + "longitude": -14.476765, + "tags": [ + "labore", + "magna", + "anim", + "ex", + "commodo", + "do", + "fugiat" + ], + "friends": [ + { + "id": 0, + "name": "Marquita Michael" + }, + { + "id": 1, + "name": "Nicholson Fields" + }, + { + "id": 2, + "name": "Bailey Green" + } + ], + "greeting": "Hello, Blankenship Nash! You have 7 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5329d0ced30c84919", + "index": 129, + "guid": "aca5c979-6e75-4e8b-a638-3979e5f5be78", + "isActive": false, + "balance": "$1,664.09", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "green", + "name": "Whitehead Craft", + "gender": "male", + "company": "PODUNK", + "email": "whiteheadcraft@podunk.com", + "phone": "+1 (884) 449-3303", + "address": "368 Batchelder Street, Grahamtown, Massachusetts, 8975", + "about": "Magna magna mollit voluptate sint in quis ut. Ad ea aute anim deserunt nulla ut exercitation reprehenderit aute. Tempor deserunt aute non sit proident pariatur et ullamco commodo incididunt ipsum nostrud laboris minim. Aliquip fugiat laboris cupidatat ad deserunt aliqua incididunt. Magna eiusmod excepteur dolor culpa laborum fugiat deserunt. Ex anim enim consectetur ut cillum do. Ex dolore Lorem magna aliqua.\r\n", + "registered": "2020-12-19T10:37:45 -01:00", + "latitude": -71.80012, + "longitude": -81.217559, + "tags": [ + "pariatur", + "ad", + "aute", + "excepteur", + "non", + "incididunt", + "elit" + ], + "friends": [ + { + "id": 0, + "name": "Jewell Alvarez" + }, + { + "id": 1, + "name": "Leonor Beck" + }, + { + "id": 2, + "name": "Tanisha Dixon" + } + ], + "greeting": "Hello, Whitehead Craft! You have 10 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee52eadb551f73a8c39", + "index": 130, + "guid": "3942aab1-dafa-4e54-a1bc-c4c0c864c5d5", + "isActive": true, + "balance": "$1,251.20", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "green", + "name": "Sonya Mays", + "gender": "female", + "company": "QIAO", + "email": "sonyamays@qiao.com", + "phone": "+1 (991) 430-3418", + "address": "216 Beekman Place, Tivoli, Maryland, 9536", + "about": "Ex adipisicing elit id nostrud voluptate id. Duis consectetur dolor ullamco magna sint eiusmod velit id laborum consectetur veniam sunt sint. Nulla ad quis fugiat amet. Esse deserunt non eu in excepteur et exercitation duis ut. Excepteur excepteur aute quis ipsum aliqua ea consectetur laborum.\r\n", + "registered": "2017-09-18T09:31:43 -02:00", + "latitude": 76.178321, + "longitude": 101.490556, + "tags": [ + "voluptate", + "qui", + "ullamco", + "proident", + "duis", + "qui", + "velit" + ], + "friends": [ + { + "id": 0, + "name": "Lawrence Munoz" + }, + { + "id": 1, + "name": "Salas Blevins" + }, + { + "id": 2, + "name": "Spencer Peterson" + } + ], + "greeting": "Hello, Sonya Mays! You have 8 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5273a8945ceafaac5", + "index": 131, + "guid": "ce07f84e-46c5-47b1-bd76-41058feec972", + "isActive": true, + "balance": "$2,224.07", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "brown", + "name": "Daniel Molina", + "gender": "male", + "company": "KAGGLE", + "email": "danielmolina@kaggle.com", + "phone": "+1 (878) 567-2850", + "address": "668 Gunther Place, Moscow, Florida, 9909", + "about": "Non duis ullamco veniam tempor ea aliquip elit elit dolore voluptate. Nostrud adipisicing aliqua cupidatat consectetur velit. Et occaecat cillum commodo nisi duis minim elit. Enim ea ut irure nulla Lorem aliqua duis. Sint magna non pariatur qui voluptate id anim mollit.\r\n", + "registered": "2020-07-10T07:52:41 -02:00", + "latitude": -32.009865, + "longitude": -115.605585, + "tags": [ + "irure", + "voluptate", + "mollit", + "elit", + "laborum", + "id", + "duis" + ], + "friends": [ + { + "id": 0, + "name": "Gay Weeks" + }, + { + "id": 1, + "name": "Richard Park" + }, + { + "id": 2, + "name": "Saundra Davis" + } + ], + "greeting": "Hello, Daniel Molina! You have 7 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5e0fdd021cad6ca87", + "index": 132, + "guid": "abc13b82-fff6-42c9-9197-f726d2189af4", + "isActive": false, + "balance": "$3,341.78", + "picture": "http://placehold.it/32x32", + "age": 33, + "eyeColor": "blue", + "name": "Dianne Vaughn", + "gender": "female", + "company": "OLUCORE", + "email": "diannevaughn@olucore.com", + "phone": "+1 (829) 551-2838", + "address": "908 Gaylord Drive, Morriston, Washington, 6753", + "about": "Laborum incididunt enim Lorem officia qui pariatur nulla velit incididunt dolore sunt. Deserunt duis adipisicing deserunt laborum consequat et adipisicing ex amet ut nostrud. Mollit exercitation nisi dolor occaecat sit et ut deserunt aliqua ea nulla. Incididunt ullamco incididunt est dolor proident nostrud officia non excepteur duis est tempor velit adipisicing. Ipsum anim Lorem aliquip cillum culpa. Eiusmod ea sit culpa veniam pariatur exercitation consequat proident enim ea deserunt velit nulla voluptate. In veniam enim ex commodo esse ullamco.\r\n", + "registered": "2014-01-23T12:52:01 -01:00", + "latitude": -54.84605, + "longitude": 96.85212, + "tags": [ + "nulla", + "cillum", + "non", + "excepteur", + "labore", + "voluptate", + "excepteur" + ], + "friends": [ + { + "id": 0, + "name": "Elaine Pope" + }, + { + "id": 1, + "name": "Fern York" + }, + { + "id": 2, + "name": "Snyder Kidd" + } + ], + "greeting": "Hello, Dianne Vaughn! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5cd56ed53be10231c", + "index": 133, + "guid": "46d08cb1-76eb-4a31-ba15-e8acab5d34a9", + "isActive": true, + "balance": "$1,395.71", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "green", + "name": "Jackson Terrell", + "gender": "male", + "company": "GEEKETRON", + "email": "jacksonterrell@geeketron.com", + "phone": "+1 (855) 597-3544", + "address": "150 Navy Walk, Hayden, Virginia, 6685", + "about": "Esse irure adipisicing deserunt cupidatat consequat consectetur minim magna cupidatat exercitation veniam. Irure quis adipisicing esse tempor est nostrud aute consequat quis commodo. Dolor duis labore labore tempor ea. Nostrud consectetur laboris elit cupidatat. Aliqua laborum Lorem ipsum voluptate aute tempor velit consequat id eu exercitation. Anim cillum consequat excepteur aute amet ea ex eu amet aliqua ad. Laboris irure ipsum duis id velit commodo duis.\r\n", + "registered": "2017-09-08T06:13:19 -02:00", + "latitude": -51.412111, + "longitude": 97.093973, + "tags": [ + "duis", + "minim", + "nisi", + "officia", + "id", + "sunt", + "magna" + ], + "friends": [ + { + "id": 0, + "name": "Garza Hudson" + }, + { + "id": 1, + "name": "Marisol Sweeney" + }, + { + "id": 2, + "name": "Leila Hines" + } + ], + "greeting": "Hello, Jackson Terrell! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee50d70020e8c3059bf", + "index": 134, + "guid": "71800905-d84f-4ea5-b149-24c79bca0e1f", + "isActive": false, + "balance": "$1,276.62", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "brown", + "name": "Hutchinson Bird", + "gender": "male", + "company": "BOVIS", + "email": "hutchinsonbird@bovis.com", + "phone": "+1 (801) 502-2174", + "address": "957 Hanson Place, Urie, Oklahoma, 4672", + "about": "Culpa exercitation Lorem ipsum fugiat dolore quis nostrud occaecat voluptate ea ut consequat sint. Incididunt nulla ad fugiat commodo et minim sit adipisicing minim dolor consequat adipisicing. Aliquip quis aute irure nostrud occaecat deserunt duis excepteur consequat occaecat. Proident mollit anim nostrud incididunt aliquip non occaecat magna ullamco ullamco exercitation tempor.\r\n", + "registered": "2014-06-23T02:46:14 -02:00", + "latitude": 24.063605, + "longitude": 74.892816, + "tags": [ + "consectetur", + "Lorem", + "et", + "ea", + "consequat", + "amet", + "occaecat" + ], + "friends": [ + { + "id": 0, + "name": "Hester Swanson" + }, + { + "id": 1, + "name": "Wanda Hammond" + }, + { + "id": 2, + "name": "Hansen Becker" + } + ], + "greeting": "Hello, Hutchinson Bird! You have 6 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee50b0bd5558ff54bc0", + "index": 135, + "guid": "77a64389-6f3c-43d0-a67c-4dfc4a81193f", + "isActive": false, + "balance": "$3,708.44", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "green", + "name": "Tina Mayer", + "gender": "female", + "company": "GLASSTEP", + "email": "tinamayer@glasstep.com", + "phone": "+1 (827) 581-3004", + "address": "734 Forest Place, Curtice, Mississippi, 5989", + "about": "Proident excepteur laboris veniam fugiat sunt. Occaecat et esse ut ullamco nostrud consectetur. Tempor eu sunt ipsum aliquip ullamco ullamco veniam. Tempor occaecat in elit velit aute dolor excepteur sint Lorem commodo Lorem. Occaecat veniam velit labore laborum amet non. Consequat aliquip labore esse elit non sint magna Lorem. Laborum ut deserunt Lorem voluptate nostrud commodo ex.\r\n", + "registered": "2015-04-30T03:44:32 -02:00", + "latitude": -6.471737, + "longitude": 165.607896, + "tags": [ + "in", + "ullamco", + "cillum", + "est", + "et", + "exercitation", + "nostrud" + ], + "friends": [ + { + "id": 0, + "name": "Lidia Combs" + }, + { + "id": 1, + "name": "Wheeler Mason" + }, + { + "id": 2, + "name": "Meadows Clark" + } + ], + "greeting": "Hello, Tina Mayer! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee511869f2129f874d9", + "index": 136, + "guid": "445544ae-4227-4282-9565-e1ad0bcec2b7", + "isActive": true, + "balance": "$1,980.14", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "green", + "name": "Bradshaw Orr", + "gender": "male", + "company": "LUNCHPOD", + "email": "bradshaworr@lunchpod.com", + "phone": "+1 (947) 478-2346", + "address": "393 Schweikerts Walk, Leland, Wisconsin, 2277", + "about": "Sint anim incididunt dolor qui ea labore sint sit labore eu magna do ad id. Deserunt fugiat consectetur culpa Lorem ea. Consequat exercitation ex excepteur sint esse adipisicing est ad officia laborum culpa. Sit incididunt aute aute pariatur excepteur amet ut. Id nulla quis magna amet. Eu esse nulla excepteur id voluptate labore.\r\n", + "registered": "2020-03-10T06:45:52 -01:00", + "latitude": -42.041629, + "longitude": 7.181755, + "tags": [ + "et", + "fugiat", + "consequat", + "nulla", + "aliqua", + "exercitation", + "culpa" + ], + "friends": [ + { + "id": 0, + "name": "Alvarez Wall" + }, + { + "id": 1, + "name": "Hopper Noble" + }, + { + "id": 2, + "name": "Bowen Jacobson" + } + ], + "greeting": "Hello, Bradshaw Orr! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee55896739b8d8c208b", + "index": 137, + "guid": "52b38cbd-f26a-4834-9495-a0585aaed600", + "isActive": true, + "balance": "$2,624.49", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "green", + "name": "Mclaughlin Payne", + "gender": "male", + "company": "POLARIUM", + "email": "mclaughlinpayne@polarium.com", + "phone": "+1 (852) 577-2298", + "address": "560 Huntington Street, Kenmar, South Dakota, 7453", + "about": "Ad exercitation nostrud nostrud incididunt duis ea fugiat ut. Aliqua laboris reprehenderit laboris ullamco aute ipsum do mollit dolor mollit. Ipsum exercitation Lorem officia est.\r\n", + "registered": "2018-08-04T06:59:01 -02:00", + "latitude": -87.070733, + "longitude": 171.921934, + "tags": [ + "nulla", + "dolor", + "incididunt", + "fugiat", + "occaecat", + "sint", + "veniam" + ], + "friends": [ + { + "id": 0, + "name": "Rosalind Fischer" + }, + { + "id": 1, + "name": "Gonzales Pena" + }, + { + "id": 2, + "name": "Holly Cooley" + } + ], + "greeting": "Hello, Mclaughlin Payne! You have 1 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5d4c95273cd532c67", + "index": 138, + "guid": "1306b585-c6e2-4ea5-b8db-6a9cbba6c2a9", + "isActive": false, + "balance": "$2,554.00", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "blue", + "name": "Joan Patel", + "gender": "female", + "company": "ZOARERE", + "email": "joanpatel@zoarere.com", + "phone": "+1 (878) 493-2911", + "address": "699 Tampa Court, Lowgap, Georgia, 3085", + "about": "Est pariatur excepteur elit qui aute. Fugiat dolore fugiat eu est exercitation incididunt culpa in anim cupidatat. Consectetur anim laborum est in pariatur laborum quis ea qui. Duis incididunt aliqua cupidatat amet irure irure. Deserunt culpa adipisicing do do sint aliquip esse sit mollit consequat eu aute.\r\n", + "registered": "2017-04-05T03:38:03 -02:00", + "latitude": 80.685279, + "longitude": 121.95229, + "tags": [ + "aliqua", + "minim", + "excepteur", + "non", + "quis", + "proident", + "nulla" + ], + "friends": [ + { + "id": 0, + "name": "Knapp Huber" + }, + { + "id": 1, + "name": "Summers Norman" + }, + { + "id": 2, + "name": "Hilary Cobb" + } + ], + "greeting": "Hello, Joan Patel! You have 6 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5e4a64e411764d9fc", + "index": 139, + "guid": "3bb63a04-2fa0-42d8-83ec-3da66984e4b6", + "isActive": true, + "balance": "$3,500.73", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "brown", + "name": "Angelia Ayala", + "gender": "female", + "company": "UNDERTAP", + "email": "angeliaayala@undertap.com", + "phone": "+1 (825) 534-3045", + "address": "642 Williams Avenue, Levant, Connecticut, 7915", + "about": "Incididunt cupidatat amet sit deserunt cillum eu id ut aliquip veniam ex. Ex dolore aute voluptate pariatur ullamco sit ex culpa sunt quis eu Lorem quis cillum. Deserunt est Lorem fugiat consequat ex. Quis irure dolore amet ea.\r\n", + "registered": "2020-03-30T11:38:00 -02:00", + "latitude": 47.572523, + "longitude": -17.213238, + "tags": [ + "aute", + "mollit", + "est", + "pariatur", + "mollit", + "sit", + "ad" + ], + "friends": [ + { + "id": 0, + "name": "Rice Saunders" + }, + { + "id": 1, + "name": "Morrow Kerr" + }, + { + "id": 2, + "name": "Graves Ferguson" + } + ], + "greeting": "Hello, Angelia Ayala! You have 3 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee568f5e18c55dd729d", + "index": 140, + "guid": "abba673d-8e92-4d2f-a477-8a16733762f0", + "isActive": false, + "balance": "$1,772.98", + "picture": "http://placehold.it/32x32", + "age": 33, + "eyeColor": "green", + "name": "Julie Gregory", + "gender": "female", + "company": "BARKARAMA", + "email": "juliegregory@barkarama.com", + "phone": "+1 (933) 526-3060", + "address": "676 Jamison Lane, Logan, West Virginia, 1580", + "about": "Aute occaecat consectetur est ea adipisicing Lorem enim nulla esse. Lorem velit aliqua aliqua officia qui ut cupidatat magna aliqua laboris do. Incididunt veniam sunt ipsum fugiat nostrud voluptate aliquip ut consectetur est nulla laborum. Mollit ex ipsum tempor ea sint cillum velit excepteur laboris laborum. Cupidatat et ullamco qui nulla anim est deserunt officia incididunt adipisicing. Ipsum esse magna non minim eiusmod pariatur quis in deserunt ea officia anim.\r\n", + "registered": "2020-01-19T05:25:09 -01:00", + "latitude": 86.222509, + "longitude": -75.637503, + "tags": [ + "ut", + "in", + "irure", + "cupidatat", + "labore", + "deserunt", + "eu" + ], + "friends": [ + { + "id": 0, + "name": "Maura Dalton" + }, + { + "id": 1, + "name": "English Duncan" + }, + { + "id": 2, + "name": "Erickson Harrison" + } + ], + "greeting": "Hello, Julie Gregory! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee59006e4721facc8e6", + "index": 141, + "guid": "4a902a14-3a79-41c7-8382-3a185ad8856b", + "isActive": false, + "balance": "$3,222.41", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "brown", + "name": "Whitney Hopkins", + "gender": "male", + "company": "KNEEDLES", + "email": "whitneyhopkins@kneedles.com", + "phone": "+1 (835) 502-3489", + "address": "524 Opal Court, Lydia, Marshall Islands, 6384", + "about": "Exercitation commodo mollit elit ex nisi Lorem. Cupidatat amet ea nostrud ut nulla amet enim id veniam. Aute dolore eu officia eiusmod exercitation.\r\n", + "registered": "2021-07-20T08:11:24 -02:00", + "latitude": 56.887021, + "longitude": -67.375011, + "tags": [ + "nulla", + "occaecat", + "amet", + "non", + "anim", + "pariatur", + "qui" + ], + "friends": [ + { + "id": 0, + "name": "Meghan Andrews" + }, + { + "id": 1, + "name": "Rivera Mendez" + }, + { + "id": 2, + "name": "Osborn Clarke" + } + ], + "greeting": "Hello, Whitney Hopkins! You have 9 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5de17996ed3b91c83", + "index": 142, + "guid": "0fa08791-166e-4d9e-9745-c7478fcf2dfa", + "isActive": false, + "balance": "$2,058.93", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "green", + "name": "Stefanie Keller", + "gender": "female", + "company": "GEOLOGIX", + "email": "stefaniekeller@geologix.com", + "phone": "+1 (913) 457-2079", + "address": "679 Fiske Place, Roeville, Arkansas, 681", + "about": "Aliqua minim est fugiat reprehenderit culpa mollit duis exercitation nisi ipsum duis elit. Nisi commodo reprehenderit veniam Lorem ea ea ad in magna. Aliquip enim velit officia et adipisicing dolore esse dolor culpa excepteur consequat.\r\n", + "registered": "2015-07-22T01:24:30 -02:00", + "latitude": 5.157128, + "longitude": 145.674648, + "tags": [ + "minim", + "nostrud", + "occaecat", + "in", + "elit", + "deserunt", + "deserunt" + ], + "friends": [ + { + "id": 0, + "name": "Gonzalez Alexander" + }, + { + "id": 1, + "name": "Wilder Tyson" + }, + { + "id": 2, + "name": "May Oneal" + } + ], + "greeting": "Hello, Stefanie Keller! You have 7 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5c89ad8ce70bbc058", + "index": 143, + "guid": "39dd474d-e0f7-4b73-a55a-496396b15907", + "isActive": false, + "balance": "$1,108.27", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "green", + "name": "Mejia Chandler", + "gender": "male", + "company": "ROBOID", + "email": "mejiachandler@roboid.com", + "phone": "+1 (889) 554-2646", + "address": "934 Borinquen Pl, Lorraine, Oregon, 4077", + "about": "Quis qui deserunt occaecat sit ullamco amet aute. Minim tempor do magna consequat duis sit est. Elit ea reprehenderit sint cupidatat sint. Eu officia dolor nisi duis velit duis. Occaecat in anim magna non cupidatat.\r\n", + "registered": "2017-12-21T07:30:32 -01:00", + "latitude": -1.703122, + "longitude": 60.029912, + "tags": [ + "laboris", + "Lorem", + "nulla", + "ut", + "ipsum", + "pariatur", + "sint" + ], + "friends": [ + { + "id": 0, + "name": "Massey Hyde" + }, + { + "id": 1, + "name": "Dejesus Carrillo" + }, + { + "id": 2, + "name": "Townsend Bernard" + } + ], + "greeting": "Hello, Mejia Chandler! You have 4 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5ce3254b3ba192b75", + "index": 144, + "guid": "6e85d355-2ae9-4f93-8e18-e84a3170c4d4", + "isActive": true, + "balance": "$2,402.41", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "brown", + "name": "Mcbride Grant", + "gender": "male", + "company": "EXIAND", + "email": "mcbridegrant@exiand.com", + "phone": "+1 (903) 429-2310", + "address": "348 Love Lane, Emerald, Puerto Rico, 8170", + "about": "Ad adipisicing pariatur ad mollit officia ullamco. Nisi voluptate consectetur proident pariatur elit magna amet id anim laborum consequat Lorem exercitation. Fugiat cillum ea qui irure ullamco. Reprehenderit nulla ad fugiat qui id ut officia. Esse in nostrud ad anim ea duis aliquip sint non deserunt do labore.\r\n", + "registered": "2015-07-12T04:33:10 -02:00", + "latitude": 16.862902, + "longitude": 99.406674, + "tags": [ + "laboris", + "dolore", + "eiusmod", + "aute", + "duis", + "mollit", + "amet" + ], + "friends": [ + { + "id": 0, + "name": "Shauna Neal" + }, + { + "id": 1, + "name": "Stephenson Bolton" + }, + { + "id": 2, + "name": "Boyle Sharp" + } + ], + "greeting": "Hello, Mcbride Grant! You have 10 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee563739ff83dd1e7b9", + "index": 145, + "guid": "962de10d-1f51-424d-a954-7ed1c9a79503", + "isActive": true, + "balance": "$3,244.25", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "blue", + "name": "Cortez Jordan", + "gender": "male", + "company": "STRALUM", + "email": "cortezjordan@stralum.com", + "phone": "+1 (946) 572-2308", + "address": "101 Eastern Parkway, Vale, Idaho, 4685", + "about": "Commodo reprehenderit aliqua in officia magna in velit laborum velit esse ex ex velit ut. Mollit voluptate ipsum incididunt pariatur esse quis. Sit minim aute deserunt duis et veniam enim sunt ea anim. Cupidatat sint pariatur cupidatat officia sit ullamco dolor do incididunt veniam sint. Esse labore ex in quis dolore aliquip do excepteur consequat fugiat veniam consectetur. Occaecat aliquip aliquip ut adipisicing.\r\n", + "registered": "2021-07-24T03:01:06 -02:00", + "latitude": -63.499608, + "longitude": -55.554063, + "tags": [ + "excepteur", + "sint", + "sit", + "ad", + "eiusmod", + "commodo", + "cillum" + ], + "friends": [ + { + "id": 0, + "name": "Gena Barrera" + }, + { + "id": 1, + "name": "Cantrell Dennis" + }, + { + "id": 2, + "name": "Leah Vance" + } + ], + "greeting": "Hello, Cortez Jordan! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5bbaa13e4fd7b7234", + "index": 146, + "guid": "5120a479-4579-49db-b82d-edecca11244e", + "isActive": true, + "balance": "$1,183.79", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "blue", + "name": "Charmaine Galloway", + "gender": "female", + "company": "COMCUR", + "email": "charmainegalloway@comcur.com", + "phone": "+1 (999) 430-3192", + "address": "633 Anthony Street, Woodlands, New Mexico, 2548", + "about": "Laboris quis fugiat voluptate velit ut sunt amet proident pariatur officia. Ex mollit quis adipisicing exercitation veniam duis incididunt commodo duis. Aliquip consequat consequat do aliqua aliquip labore minim dolore voluptate laborum. Officia incididunt sunt laboris cupidatat culpa ea. Aute mollit mollit aute ea pariatur non occaecat adipisicing anim. Adipisicing eu proident irure ea pariatur irure magna Lorem cupidatat.\r\n", + "registered": "2015-09-23T11:21:35 -02:00", + "latitude": -55.427803, + "longitude": 42.686073, + "tags": [ + "elit", + "minim", + "pariatur", + "non", + "ex", + "eiusmod", + "aliqua" + ], + "friends": [ + { + "id": 0, + "name": "Navarro Whitley" + }, + { + "id": 1, + "name": "Tillman Rogers" + }, + { + "id": 2, + "name": "Ida Miranda" + } + ], + "greeting": "Hello, Charmaine Galloway! You have 1 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee59e5a2485138b15a7", + "index": 147, + "guid": "5690e9d2-9bb5-47a0-803e-8cdf7862293e", + "isActive": false, + "balance": "$3,227.62", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "brown", + "name": "Tabatha Blanchard", + "gender": "female", + "company": "PANZENT", + "email": "tabathablanchard@panzent.com", + "phone": "+1 (919) 517-3855", + "address": "902 Erasmus Street, Gulf, Minnesota, 7789", + "about": "Aliquip qui qui irure esse ea deserunt eu officia dolor. Ipsum ea reprehenderit est labore excepteur occaecat ex quis do. Qui commodo magna adipisicing pariatur ea excepteur dolor reprehenderit proident aliqua elit eu enim. Nostrud consequat pariatur sunt cupidatat in duis nulla aute incididunt sint aliquip sunt. Sit irure consequat laborum elit adipisicing ea. Aliqua est fugiat nostrud veniam adipisicing ex ad cillum exercitation sit magna. Velit dolore labore aute pariatur tempor cillum anim.\r\n", + "registered": "2020-03-13T08:59:20 -01:00", + "latitude": 72.599314, + "longitude": -53.05635, + "tags": [ + "voluptate", + "eu", + "elit", + "Lorem", + "reprehenderit", + "cillum", + "qui" + ], + "friends": [ + { + "id": 0, + "name": "Katharine Gonzalez" + }, + { + "id": 1, + "name": "Justine Mccormick" + }, + { + "id": 2, + "name": "Lauri Wilkinson" + } + ], + "greeting": "Hello, Tabatha Blanchard! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee534a3cf4ebc973f69", + "index": 148, + "guid": "f2bb7b5a-c27a-4159-9beb-33c737794637", + "isActive": false, + "balance": "$2,106.74", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "blue", + "name": "Stafford Lara", + "gender": "male", + "company": "HOTCAKES", + "email": "staffordlara@hotcakes.com", + "phone": "+1 (840) 412-2196", + "address": "808 Fenimore Street, Lupton, Iowa, 1852", + "about": "Proident nisi excepteur ad anim eu voluptate adipisicing. Amet sit magna id pariatur esse enim deserunt commodo voluptate est incididunt ea velit. Consequat do quis incididunt aute magna duis aliqua id nulla voluptate mollit reprehenderit voluptate id. Ad excepteur id incididunt aute elit sunt occaecat proident laboris anim occaecat ut. In do sit est et. Lorem ex mollit voluptate aliqua.\r\n", + "registered": "2018-08-23T09:47:29 -02:00", + "latitude": -6.492601, + "longitude": -133.833141, + "tags": [ + "ea", + "nisi", + "ipsum", + "non", + "incididunt", + "magna", + "laboris" + ], + "friends": [ + { + "id": 0, + "name": "Grace Strong" + }, + { + "id": 1, + "name": "Christian Carson" + }, + { + "id": 2, + "name": "Mercado Nichols" + } + ], + "greeting": "Hello, Stafford Lara! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee56828aca8860ebea9", + "index": 149, + "guid": "d013b34a-f79d-49a4-94a6-20a66eec6b57", + "isActive": true, + "balance": "$1,893.56", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "green", + "name": "Booker Abbott", + "gender": "male", + "company": "BITTOR", + "email": "bookerabbott@bittor.com", + "phone": "+1 (864) 530-3193", + "address": "443 Cooper Street, Fredericktown, Maine, 4345", + "about": "Labore consectetur magna commodo anim proident enim sunt culpa amet proident pariatur incididunt in. Pariatur cillum nostrud cupidatat magna esse anim id anim sunt. Irure ullamco cillum officia aute occaecat est ipsum sint laboris duis incididunt mollit consectetur. Ea laboris sint dolor sint sint nulla reprehenderit nisi pariatur. Incididunt cillum consequat nulla est voluptate ipsum duis labore minim irure enim nulla nisi.\r\n", + "registered": "2015-04-26T08:21:07 -02:00", + "latitude": 79.003769, + "longitude": 118.973225, + "tags": [ + "excepteur", + "excepteur", + "ut", + "sint", + "enim", + "ad", + "adipisicing" + ], + "friends": [ + { + "id": 0, + "name": "Beverley Sharpe" + }, + { + "id": 1, + "name": "Farrell Reilly" + }, + { + "id": 2, + "name": "Rachel Ball" + } + ], + "greeting": "Hello, Booker Abbott! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5c7615228af5d4ae6", + "index": 150, + "guid": "dd3e5f83-10a1-4af5-ab05-4cb1f1641fb2", + "isActive": true, + "balance": "$2,205.43", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "green", + "name": "Ray Daniels", + "gender": "male", + "company": "RECRITUBE", + "email": "raydaniels@recritube.com", + "phone": "+1 (812) 567-3470", + "address": "143 Perry Terrace, Tedrow, Tennessee, 9587", + "about": "Ut consectetur consectetur in consectetur nostrud cupidatat aute sunt ut est. Officia pariatur adipisicing culpa dolor. Ipsum culpa in tempor ipsum occaecat aliquip qui ut sint qui est Lorem dolor. Et ut nostrud tempor sit consectetur labore duis. Ad amet aliquip est est.\r\n", + "registered": "2017-07-06T05:39:55 -02:00", + "latitude": -19.375801, + "longitude": 42.704824, + "tags": [ + "dolor", + "eiusmod", + "consequat", + "dolore", + "ea", + "voluptate", + "nisi" + ], + "friends": [ + { + "id": 0, + "name": "Briggs Larson" + }, + { + "id": 1, + "name": "Maggie Fox" + }, + { + "id": 2, + "name": "Lenore Giles" + } + ], + "greeting": "Hello, Ray Daniels! You have 6 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee544b08024347a2af5", + "index": 151, + "guid": "75dc9a80-3f0c-4e9e-83ef-344c9f20e848", + "isActive": true, + "balance": "$3,739.95", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Wolfe Gilmore", + "gender": "male", + "company": "PROFLEX", + "email": "wolfegilmore@proflex.com", + "phone": "+1 (987) 459-2290", + "address": "663 Albemarle Terrace, Loveland, Palau, 6629", + "about": "Consequat laboris reprehenderit elit veniam laboris adipisicing elit amet. Sint magna minim laboris aliqua. Veniam amet consequat excepteur est labore culpa ea veniam. Et voluptate reprehenderit sit sunt. Occaecat elit cillum elit et elit magna consectetur cupidatat mollit consequat excepteur incididunt.\r\n", + "registered": "2020-02-23T08:48:58 -01:00", + "latitude": -50.156098, + "longitude": 126.585424, + "tags": [ + "non", + "mollit", + "minim", + "ipsum", + "non", + "ut", + "adipisicing" + ], + "friends": [ + { + "id": 0, + "name": "Karen Powers" + }, + { + "id": 1, + "name": "Hatfield Moon" + }, + { + "id": 2, + "name": "Angela Osborne" + } + ], + "greeting": "Hello, Wolfe Gilmore! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5deb9985bd13c7fe3", + "index": 152, + "guid": "13e88d2e-6295-46ee-b640-7e7f985745fa", + "isActive": true, + "balance": "$1,643.71", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "green", + "name": "Lesley Bright", + "gender": "female", + "company": "LUDAK", + "email": "lesleybright@ludak.com", + "phone": "+1 (984) 594-2201", + "address": "446 Commerce Street, Blairstown, Kansas, 5802", + "about": "Eiusmod ea pariatur nostrud adipisicing tempor amet voluptate. Occaecat non dolor et aute labore pariatur officia pariatur cupidatat velit laboris veniam esse reprehenderit. Duis sint velit qui velit reprehenderit enim magna deserunt pariatur pariatur. Velit aliqua velit ad elit veniam aute sint aliquip duis officia ullamco non sunt. Commodo labore culpa veniam ipsum.\r\n", + "registered": "2016-09-22T09:17:26 -02:00", + "latitude": -25.928367, + "longitude": -113.94637, + "tags": [ + "in", + "laborum", + "sunt", + "irure", + "fugiat", + "aliqua", + "dolor" + ], + "friends": [ + { + "id": 0, + "name": "Ines Stout" + }, + { + "id": 1, + "name": "Alba Hardin" + }, + { + "id": 2, + "name": "Rose Lindsey" + } + ], + "greeting": "Hello, Lesley Bright! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5f7c0939ef0f26379", + "index": 153, + "guid": "72a6e308-5694-4e6d-84a1-957cfe2d0a5d", + "isActive": true, + "balance": "$1,963.83", + "picture": "http://placehold.it/32x32", + "age": 37, + "eyeColor": "brown", + "name": "Roy Hodges", + "gender": "male", + "company": "QUIZKA", + "email": "royhodges@quizka.com", + "phone": "+1 (939) 593-2568", + "address": "218 Veranda Place, Columbus, American Samoa, 6702", + "about": "Do amet officia ex enim veniam aliqua ex laborum sunt. Ex ipsum aliqua ex id. Et commodo adipisicing deserunt culpa nulla consequat id dolore.\r\n", + "registered": "2019-11-24T02:00:58 -01:00", + "latitude": 86.760482, + "longitude": -52.686767, + "tags": [ + "id", + "aliqua", + "commodo", + "tempor", + "aliquip", + "magna", + "aliquip" + ], + "friends": [ + { + "id": 0, + "name": "Camille Cross" + }, + { + "id": 1, + "name": "Walls Bass" + }, + { + "id": 2, + "name": "Finch Booth" + } + ], + "greeting": "Hello, Roy Hodges! You have 9 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee54d3bdfa4044157b6", + "index": 154, + "guid": "f84e0bd8-8474-4e6d-b19c-4e08321863da", + "isActive": true, + "balance": "$3,424.59", + "picture": "http://placehold.it/32x32", + "age": 28, + "eyeColor": "brown", + "name": "Shelton Dale", + "gender": "male", + "company": "OPTICON", + "email": "sheltondale@opticon.com", + "phone": "+1 (886) 578-2696", + "address": "706 Hausman Street, Elrama, South Carolina, 5946", + "about": "Aliqua mollit do consequat veniam sunt est aute aliquip do Lorem eiusmod aliquip mollit in. Anim elit est esse id culpa nisi laboris. Magna ea mollit fugiat nostrud ex pariatur commodo proident dolore. Adipisicing nostrud velit eu sunt pariatur.\r\n", + "registered": "2014-02-12T02:22:15 -01:00", + "latitude": 64.193976, + "longitude": -155.392223, + "tags": [ + "ex", + "in", + "enim", + "consequat", + "dolor", + "commodo", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Murphy Richards" + }, + { + "id": 1, + "name": "Chen Knowles" + }, + { + "id": 2, + "name": "Horn Fowler" + } + ], + "greeting": "Hello, Shelton Dale! You have 7 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee568b7dd399a68be8f", + "index": 155, + "guid": "764c766d-bfb3-4bba-9ff5-c5dfa650b86c", + "isActive": false, + "balance": "$2,170.52", + "picture": "http://placehold.it/32x32", + "age": 32, + "eyeColor": "green", + "name": "Noelle Lawson", + "gender": "female", + "company": "PLUTORQUE", + "email": "noellelawson@plutorque.com", + "phone": "+1 (920) 537-3676", + "address": "995 Bassett Avenue, Delco, Indiana, 8632", + "about": "Minim commodo mollit ullamco cillum laboris eu do ex voluptate dolor ut sit. Et magna sit ea enim officia adipisicing sint sit consectetur et deserunt amet. Dolor consectetur incididunt nostrud cillum voluptate veniam sunt tempor dolor exercitation. Sint sint fugiat duis esse officia et exercitation Lorem aliquip. Laborum eu cupidatat eu duis deserunt eiusmod do amet in do nisi culpa consectetur duis. Consequat aliquip velit magna sunt.\r\n", + "registered": "2020-12-20T12:30:13 -01:00", + "latitude": 47.156984, + "longitude": 97.702827, + "tags": [ + "ullamco", + "aute", + "deserunt", + "incididunt", + "incididunt", + "ea", + "sint" + ], + "friends": [ + { + "id": 0, + "name": "Camacho Daugherty" + }, + { + "id": 1, + "name": "Naomi Hubbard" + }, + { + "id": 2, + "name": "Alford Curtis" + } + ], + "greeting": "Hello, Noelle Lawson! You have 9 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee585cd13143c464e5a", + "index": 156, + "guid": "97b242a7-b91c-49e0-a10c-5913ba32bc8e", + "isActive": true, + "balance": "$1,224.49", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "green", + "name": "Diana Ross", + "gender": "female", + "company": "BOLAX", + "email": "dianaross@bolax.com", + "phone": "+1 (953) 406-3048", + "address": "320 Sumpter Street, Frystown, District Of Columbia, 3971", + "about": "Nisi voluptate labore laborum nulla proident adipisicing pariatur consectetur qui minim nostrud adipisicing enim. Laboris commodo culpa sit enim do laborum ullamco in nostrud officia minim exercitation. Lorem officia irure deserunt Lorem ullamco laborum. Ullamco pariatur sint do qui proident commodo reprehenderit excepteur officia ad. Non ut reprehenderit id culpa non.\r\n", + "registered": "2016-09-11T04:00:33 -02:00", + "latitude": -87.832113, + "longitude": -114.083214, + "tags": [ + "et", + "cillum", + "cupidatat", + "esse", + "et", + "velit", + "excepteur" + ], + "friends": [ + { + "id": 0, + "name": "Natasha Washington" + }, + { + "id": 1, + "name": "Bianca Franks" + }, + { + "id": 2, + "name": "Cotton Mooney" + } + ], + "greeting": "Hello, Diana Ross! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5f7a84cd176af9561", + "index": 157, + "guid": "bab074ec-94fb-4ec9-8e51-69d7ac448bd5", + "isActive": true, + "balance": "$2,078.98", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "blue", + "name": "Dorothy Barber", + "gender": "female", + "company": "PAWNAGRA", + "email": "dorothybarber@pawnagra.com", + "phone": "+1 (806) 426-3153", + "address": "668 Hall Street, Blandburg, Wyoming, 6429", + "about": "Amet elit laboris mollit pariatur laborum laboris. Voluptate occaecat duis laboris sit voluptate elit commodo tempor labore qui sint. Pariatur mollit tempor qui enim Lorem nulla incididunt in est dolor.\r\n", + "registered": "2017-07-22T06:15:59 -02:00", + "latitude": -35.167258, + "longitude": -139.549021, + "tags": [ + "ullamco", + "eiusmod", + "occaecat", + "eu", + "officia", + "eu", + "do" + ], + "friends": [ + { + "id": 0, + "name": "Rhoda Livingston" + }, + { + "id": 1, + "name": "Freda Nielsen" + }, + { + "id": 2, + "name": "Lana Crosby" + } + ], + "greeting": "Hello, Dorothy Barber! You have 5 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee58d574b232cf827cb", + "index": 158, + "guid": "d9a2c7f5-178a-4de2-8aba-9ff429e8a38d", + "isActive": true, + "balance": "$2,412.25", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "brown", + "name": "Rebekah Boyer", + "gender": "female", + "company": "FRANSCENE", + "email": "rebekahboyer@franscene.com", + "phone": "+1 (976) 553-2552", + "address": "896 Dahlgreen Place, Waterview, Texas, 4309", + "about": "Cupidatat nisi culpa nulla non aute culpa sit laboris adipisicing sunt tempor. Ut laboris anim nulla incididunt cillum sint aute eiusmod dolor cillum. Culpa dolor est elit proident occaecat nisi sint veniam amet. Incididunt aliqua do ad nulla in anim cupidatat dolor voluptate non incididunt. Laborum cillum sint deserunt ipsum aliqua ad nulla non velit reprehenderit laborum. Est fugiat consectetur nulla Lorem aliqua Lorem est. Irure ea consectetur aliqua ex dolore aliqua Lorem sit ut fugiat.\r\n", + "registered": "2015-11-08T11:53:36 -01:00", + "latitude": 2.941026, + "longitude": 89.814006, + "tags": [ + "aute", + "quis", + "id", + "minim", + "anim", + "velit", + "tempor" + ], + "friends": [ + { + "id": 0, + "name": "Mcguire Pace" + }, + { + "id": 1, + "name": "Tiffany Davidson" + }, + { + "id": 2, + "name": "Toni Coffey" + } + ], + "greeting": "Hello, Rebekah Boyer! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee535c02f25600dbd83", + "index": 159, + "guid": "4bc995ae-f379-4a34-8f2f-d7804a90868d", + "isActive": true, + "balance": "$1,024.93", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "brown", + "name": "Macdonald Patrick", + "gender": "male", + "company": "BLUPLANET", + "email": "macdonaldpatrick@bluplanet.com", + "phone": "+1 (901) 422-2518", + "address": "536 Amboy Street, Carrizo, Rhode Island, 3229", + "about": "Excepteur tempor tempor veniam pariatur fugiat incididunt sint elit in aute commodo et magna ea. Esse labore officia ex ut excepteur deserunt duis nostrud ut dolore ipsum mollit Lorem. Irure laboris est occaecat tempor non nulla ipsum. Cillum eu quis esse incididunt exercitation laborum veniam sunt. Veniam anim fugiat consectetur excepteur ad id labore. Et fugiat tempor dolor cillum dolor amet sit fugiat et. Quis consectetur irure officia non sit elit.\r\n", + "registered": "2016-02-10T02:49:55 -01:00", + "latitude": 39.579377, + "longitude": -107.563672, + "tags": [ + "deserunt", + "culpa", + "Lorem", + "fugiat", + "mollit", + "irure", + "velit" + ], + "friends": [ + { + "id": 0, + "name": "Palmer Farley" + }, + { + "id": 1, + "name": "Wood Alvarado" + }, + { + "id": 2, + "name": "Wynn Stephens" + } + ], + "greeting": "Hello, Macdonald Patrick! You have 3 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee521aac761d4a370ac", + "index": 160, + "guid": "37c650f1-2dcc-4873-a7fd-fd6f447e366e", + "isActive": true, + "balance": "$1,529.76", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "green", + "name": "Carmella Foley", + "gender": "female", + "company": "ZENSOR", + "email": "carmellafoley@zensor.com", + "phone": "+1 (881) 481-3309", + "address": "125 Auburn Place, Islandia, Louisiana, 2331", + "about": "Cillum anim eu fugiat ut ex ipsum esse et culpa cupidatat voluptate id. Sit culpa nulla labore enim duis consequat adipisicing veniam. Fugiat non incididunt nostrud occaecat. Enim nulla incididunt magna culpa in est Lorem ullamco. Aliqua deserunt aliquip mollit nostrud dolor adipisicing cupidatat pariatur sint eiusmod quis. Occaecat cupidatat sit fugiat non consectetur pariatur consequat enim reprehenderit duis. Culpa officia pariatur eu pariatur cillum non pariatur quis culpa sint magna irure.\r\n", + "registered": "2020-12-25T01:30:53 -01:00", + "latitude": 55.689273, + "longitude": -145.256245, + "tags": [ + "laboris", + "Lorem", + "non", + "aute", + "occaecat", + "duis", + "cillum" + ], + "friends": [ + { + "id": 0, + "name": "Bridget Lambert" + }, + { + "id": 1, + "name": "Rowena Walsh" + }, + { + "id": 2, + "name": "Matilda Moran" + } + ], + "greeting": "Hello, Carmella Foley! You have 2 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5e1950f39972d92dc", + "index": 161, + "guid": "b7009167-7f1a-46ab-92f5-f3a9caa1fff6", + "isActive": false, + "balance": "$3,913.46", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "green", + "name": "James Dunlap", + "gender": "male", + "company": "ZILLAN", + "email": "jamesdunlap@zillan.com", + "phone": "+1 (865) 534-3153", + "address": "181 Tompkins Avenue, Wyoming, Illinois, 8889", + "about": "Laboris enim nulla reprehenderit mollit esse in. Pariatur ut nulla pariatur do esse culpa qui veniam ea est ad. Anim laboris veniam elit incididunt aliquip occaecat magna aliquip sunt voluptate. Adipisicing nostrud est amet quis reprehenderit ex esse pariatur. Ea consequat nisi deserunt adipisicing. Laboris anim in sint amet eiusmod incididunt cillum sint exercitation. Do aute quis in laborum qui commodo adipisicing occaecat.\r\n", + "registered": "2017-03-14T11:37:37 -01:00", + "latitude": 27.714567, + "longitude": -20.490501, + "tags": [ + "occaecat", + "eiusmod", + "mollit", + "Lorem", + "reprehenderit", + "eu", + "pariatur" + ], + "friends": [ + { + "id": 0, + "name": "Elise Solomon" + }, + { + "id": 1, + "name": "Marguerite Moore" + }, + { + "id": 2, + "name": "Ashley Buchanan" + } + ], + "greeting": "Hello, James Dunlap! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5c27c96ad56f126f1", + "index": 162, + "guid": "f7090d9e-083a-452a-a98d-13a43d5e0a56", + "isActive": false, + "balance": "$1,371.28", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "green", + "name": "Edwards Mathews", + "gender": "male", + "company": "EZENTIA", + "email": "edwardsmathews@ezentia.com", + "phone": "+1 (815) 445-3533", + "address": "696 Debevoise Street, Wollochet, Guam, 1752", + "about": "Deserunt commodo consectetur velit culpa velit enim nulla culpa. Sit ad cillum ipsum commodo enim esse labore nulla in sit cupidatat cupidatat proident. Eu non laboris cupidatat sint. Laborum qui commodo consequat in incididunt dolore occaecat voluptate non nisi est magna do. Exercitation ullamco adipisicing aliquip magna veniam et in laborum in cillum officia. In sunt eiusmod anim eu qui nostrud proident adipisicing qui tempor laboris ut laborum. Sunt elit Lorem amet mollit exercitation labore amet reprehenderit minim quis ullamco do in.\r\n", + "registered": "2017-09-17T11:16:52 -02:00", + "latitude": -49.841093, + "longitude": 179.143357, + "tags": [ + "veniam", + "quis", + "do", + "do", + "dolore", + "elit", + "cupidatat" + ], + "friends": [ + { + "id": 0, + "name": "Mckenzie Sparks" + }, + { + "id": 1, + "name": "Britt Hendricks" + }, + { + "id": 2, + "name": "Bradford Castro" + } + ], + "greeting": "Hello, Edwards Mathews! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee56cb6b0a8f6d1bed7", + "index": 163, + "guid": "80b59ece-1750-43e1-af48-c97fecea477c", + "isActive": true, + "balance": "$1,947.21", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "blue", + "name": "Olson Bell", + "gender": "male", + "company": "FIREWAX", + "email": "olsonbell@firewax.com", + "phone": "+1 (905) 464-3563", + "address": "861 Commercial Street, Leming, New York, 3414", + "about": "Sit esse sint Lorem sint nostrud quis in est. Qui nostrud ex velit sit commodo fugiat elit aliqua ad voluptate. Laborum enim eiusmod qui irure magna dolor aliqua deserunt.\r\n", + "registered": "2019-01-12T09:55:30 -01:00", + "latitude": 77.532459, + "longitude": 58.901133, + "tags": [ + "velit", + "laborum", + "exercitation", + "sit", + "ut", + "fugiat", + "eu" + ], + "friends": [ + { + "id": 0, + "name": "Dunlap Guerrero" + }, + { + "id": 1, + "name": "Haney Reyes" + }, + { + "id": 2, + "name": "Mccarthy Daniel" + } + ], + "greeting": "Hello, Olson Bell! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5a43ea1672e052b71", + "index": 164, + "guid": "70aa8322-8b1d-4b9b-9116-e6cf355f0ba9", + "isActive": false, + "balance": "$2,714.39", + "picture": "http://placehold.it/32x32", + "age": 34, + "eyeColor": "blue", + "name": "Guadalupe Hanson", + "gender": "female", + "company": "IDEGO", + "email": "guadalupehanson@idego.com", + "phone": "+1 (922) 420-2096", + "address": "985 Bayview Avenue, Haena, Colorado, 3841", + "about": "Reprehenderit qui nostrud consequat laborum minim qui et. Sunt magna in enim laboris. Laboris dolor elit duis aliqua. Ex occaecat ullamco laboris sint quis ullamco voluptate consectetur.\r\n", + "registered": "2018-08-03T06:20:50 -02:00", + "latitude": -50.279993, + "longitude": 99.11661, + "tags": [ + "mollit", + "officia", + "adipisicing", + "veniam", + "ullamco", + "irure", + "reprehenderit" + ], + "friends": [ + { + "id": 0, + "name": "Audra Travis" + }, + { + "id": 1, + "name": "Grimes Hampton" + }, + { + "id": 2, + "name": "Ingram Wiley" + } + ], + "greeting": "Hello, Guadalupe Hanson! You have 4 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee537ef82e78fa4f286", + "index": 165, + "guid": "043c1605-47b1-418d-a168-4a2546e8fe1f", + "isActive": true, + "balance": "$2,769.31", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "brown", + "name": "Mitzi Robles", + "gender": "female", + "company": "PORTICO", + "email": "mitzirobles@portico.com", + "phone": "+1 (979) 505-3161", + "address": "622 Henry Street, Leola, Michigan, 2464", + "about": "Id incididunt irure exercitation magna ut exercitation qui dolore cupidatat laborum eiusmod labore. Eu labore do mollit enim aliqua eu deserunt non proident nostrud cillum pariatur Lorem. Elit minim consequat sint sint. Ullamco exercitation dolor reprehenderit ad est adipisicing excepteur.\r\n", + "registered": "2016-04-03T09:39:14 -02:00", + "latitude": 41.121775, + "longitude": 48.537868, + "tags": [ + "minim", + "pariatur", + "et", + "aliqua", + "cupidatat", + "elit", + "magna" + ], + "friends": [ + { + "id": 0, + "name": "Luella Kane" + }, + { + "id": 1, + "name": "Barnett Holman" + }, + { + "id": 2, + "name": "Brooks Young" + } + ], + "greeting": "Hello, Mitzi Robles! You have 4 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5c78277888b039051", + "index": 166, + "guid": "f06f640c-a155-4ba9-9f74-149b4fca7046", + "isActive": true, + "balance": "$2,446.50", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "brown", + "name": "Flossie Steele", + "gender": "female", + "company": "NAXDIS", + "email": "flossiesteele@naxdis.com", + "phone": "+1 (868) 557-3107", + "address": "940 Ross Street, Nicholson, Vermont, 8668", + "about": "Quis amet anim officia nisi sit nulla excepteur minim magna commodo. Voluptate sunt cillum magna proident. Et officia nisi cupidatat quis voluptate ad labore velit irure eu.\r\n", + "registered": "2014-01-17T09:05:08 -01:00", + "latitude": -15.526407, + "longitude": -105.072326, + "tags": [ + "exercitation", + "occaecat", + "ad", + "commodo", + "voluptate", + "occaecat", + "voluptate" + ], + "friends": [ + { + "id": 0, + "name": "Rosemary Lott" + }, + { + "id": 1, + "name": "Carroll Flynn" + }, + { + "id": 2, + "name": "Salazar Glover" + } + ], + "greeting": "Hello, Flossie Steele! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee571243be34c02ee14", + "index": 167, + "guid": "3d25fce3-caf1-4cc2-ba33-9447d0cd0f2d", + "isActive": true, + "balance": "$1,011.36", + "picture": "http://placehold.it/32x32", + "age": 33, + "eyeColor": "blue", + "name": "Susie Bradford", + "gender": "female", + "company": "RADIANTIX", + "email": "susiebradford@radiantix.com", + "phone": "+1 (860) 513-3324", + "address": "975 Heyward Street, Websterville, New Jersey, 3172", + "about": "Sit aliquip eu aliquip dolor pariatur consectetur consequat eiusmod commodo nulla aliqua veniam. Mollit adipisicing consectetur sint veniam irure cillum ipsum esse occaecat. Dolore incididunt ea duis in non ea labore sunt. Ipsum irure ad reprehenderit anim nostrud velit. Ea duis proident sit laboris sunt anim sit. Officia labore culpa eiusmod non magna incididunt aliqua duis veniam et duis. Aliqua reprehenderit sint sit id mollit.\r\n", + "registered": "2018-12-25T02:18:38 -01:00", + "latitude": 88.659453, + "longitude": 121.981182, + "tags": [ + "cillum", + "deserunt", + "magna", + "nisi", + "esse", + "elit", + "pariatur" + ], + "friends": [ + { + "id": 0, + "name": "Emily Ratliff" + }, + { + "id": 1, + "name": "Rasmussen Nguyen" + }, + { + "id": 2, + "name": "Peters Serrano" + } + ], + "greeting": "Hello, Susie Bradford! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5475d05f9f106f335", + "index": 168, + "guid": "79e55e9e-1e49-4f2f-bfcb-15ce51e408a6", + "isActive": false, + "balance": "$2,513.42", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Hooper Huffman", + "gender": "male", + "company": "TERRASYS", + "email": "hooperhuffman@terrasys.com", + "phone": "+1 (948) 526-3104", + "address": "761 Hunts Lane, Herbster, Nebraska, 647", + "about": "Tempor excepteur aute do qui officia aute aliquip officia exercitation ullamco. Quis quis ad cupidatat aute. Mollit voluptate qui non exercitation officia nisi quis officia adipisicing cillum laboris ipsum culpa labore. Cillum ea minim mollit aliqua eiusmod.\r\n", + "registered": "2014-11-10T05:07:55 -01:00", + "latitude": 8.36954, + "longitude": 84.490621, + "tags": [ + "adipisicing", + "ad", + "et", + "non", + "laboris", + "ut", + "consectetur" + ], + "friends": [ + { + "id": 0, + "name": "Heath Stein" + }, + { + "id": 1, + "name": "Bonner Craig" + }, + { + "id": 2, + "name": "Hartman Poole" + } + ], + "greeting": "Hello, Hooper Huffman! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee51ecd0492051f3108", + "index": 169, + "guid": "b5abe7ac-552a-4bc5-a2d8-6c1485b86563", + "isActive": false, + "balance": "$2,531.67", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "green", + "name": "Duran Norris", + "gender": "male", + "company": "DIGIQUE", + "email": "durannorris@digique.com", + "phone": "+1 (848) 550-2430", + "address": "709 Nolans Lane, Austinburg, North Carolina, 6627", + "about": "Non excepteur Lorem id aliqua. Amet id dolore eiusmod commodo duis tempor consequat exercitation consequat aute laboris irure tempor. Cillum culpa est cillum ea deserunt incididunt nostrud dolore et magna excepteur nisi sunt. Proident consectetur non dolor commodo qui mollit do deserunt ipsum quis ullamco ullamco nisi. Nulla cillum sit ea minim qui eiusmod culpa ullamco excepteur adipisicing sit ea elit. Labore velit tempor consectetur officia anim.\r\n", + "registered": "2021-03-07T02:04:57 -01:00", + "latitude": 51.515949, + "longitude": 141.937642, + "tags": [ + "consectetur", + "eiusmod", + "ullamco", + "ullamco", + "consequat", + "qui", + "officia" + ], + "friends": [ + { + "id": 0, + "name": "Veronica Cash" + }, + { + "id": 1, + "name": "Robertson Cardenas" + }, + { + "id": 2, + "name": "Gallegos Hoover" + } + ], + "greeting": "Hello, Duran Norris! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee538ae4398f3a752e4", + "index": 170, + "guid": "c9b71c2f-9074-4d84-b518-44d113c24ba7", + "isActive": false, + "balance": "$2,485.82", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "brown", + "name": "Burnett Ray", + "gender": "male", + "company": "EWEVILLE", + "email": "burnettray@eweville.com", + "phone": "+1 (880) 571-2528", + "address": "252 Irvington Place, Connerton, California, 9809", + "about": "Laborum reprehenderit nisi laborum sint consectetur duis. Enim cillum occaecat reprehenderit deserunt id eu consequat ex tempor mollit pariatur eiusmod. Excepteur culpa in id non aliqua sunt anim officia minim cillum aliqua ut. Dolore est elit amet ea elit pariatur ullamco eu ea elit ut enim. Amet cupidatat ullamco ullamco consequat tempor tempor consectetur laborum cillum aliquip irure.\r\n", + "registered": "2021-07-20T03:36:54 -02:00", + "latitude": -67.490123, + "longitude": -25.91264, + "tags": [ + "anim", + "ad", + "in", + "exercitation", + "laboris", + "velit", + "deserunt" + ], + "friends": [ + { + "id": 0, + "name": "Elliott Pittman" + }, + { + "id": 1, + "name": "Ross Mcdowell" + }, + { + "id": 2, + "name": "Kidd Holloway" + } + ], + "greeting": "Hello, Burnett Ray! You have 2 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee526ff9d49277a1b51", + "index": 171, + "guid": "e8972060-6a5a-4472-bc70-7c511817fa84", + "isActive": true, + "balance": "$2,223.93", + "picture": "http://placehold.it/32x32", + "age": 37, + "eyeColor": "green", + "name": "Gallagher Taylor", + "gender": "male", + "company": "CONFERIA", + "email": "gallaghertaylor@conferia.com", + "phone": "+1 (909) 435-2081", + "address": "484 King Street, Eastvale, Virgin Islands, 5943", + "about": "Aute aliquip reprehenderit cillum consequat fugiat labore cupidatat elit ipsum culpa dolor mollit. Laborum aliqua esse sint aute magna amet consectetur. Consectetur aute sunt ullamco deserunt pariatur Lorem elit in aliqua mollit.\r\n", + "registered": "2015-06-23T08:57:48 -02:00", + "latitude": -26.979724, + "longitude": 8.410674, + "tags": [ + "eu", + "minim", + "aute", + "consequat", + "id", + "ex", + "reprehenderit" + ], + "friends": [ + { + "id": 0, + "name": "Patrice Rodriguez" + }, + { + "id": 1, + "name": "Lorene Rich" + }, + { + "id": 2, + "name": "Kerry Castillo" + } + ], + "greeting": "Hello, Gallagher Taylor! You have 6 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5f9a0cd83d22d336e", + "index": 172, + "guid": "07cd35da-ca68-4bcd-8c6b-050d69b28090", + "isActive": true, + "balance": "$3,724.58", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "blue", + "name": "Suzanne Gardner", + "gender": "female", + "company": "SOPRANO", + "email": "suzannegardner@soprano.com", + "phone": "+1 (926) 537-3588", + "address": "371 Montgomery Street, Escondida, Kentucky, 9992", + "about": "Sunt officia reprehenderit excepteur nisi. Dolor sint laborum enim ea velit sit mollit proident. Occaecat nisi velit officia irure ipsum. Nulla occaecat velit ullamco dolore. Esse elit irure irure commodo ipsum dolor nisi. Esse sunt commodo labore eiusmod enim adipisicing Lorem occaecat in aliquip nulla ipsum dolore.\r\n", + "registered": "2017-09-24T04:25:10 -02:00", + "latitude": 80.234674, + "longitude": -147.398861, + "tags": [ + "et", + "voluptate", + "consequat", + "amet", + "ea", + "ipsum", + "sunt" + ], + "friends": [ + { + "id": 0, + "name": "Bertha Shaw" + }, + { + "id": 1, + "name": "Le Emerson" + }, + { + "id": 2, + "name": "Nikki Harmon" + } + ], + "greeting": "Hello, Suzanne Gardner! You have 2 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5aeb3f04d95077025", + "index": 173, + "guid": "729de9a1-ea32-4b23-ba0a-497ead9af111", + "isActive": false, + "balance": "$1,093.72", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "green", + "name": "Ivy Romero", + "gender": "female", + "company": "ZENSUS", + "email": "ivyromero@zensus.com", + "phone": "+1 (959) 463-3847", + "address": "334 Metropolitan Avenue, Bowmansville, Alabama, 745", + "about": "Laboris consectetur cupidatat dolor laborum id consectetur exercitation ullamco aliquip anim Lorem. Velit exercitation fugiat irure et consectetur ad est id sint laborum sit laboris. Est voluptate cupidatat minim veniam cillum dolor. Irure pariatur velit nostrud esse aliqua quis aliquip fugiat nisi quis velit ullamco do.\r\n", + "registered": "2014-07-31T02:31:56 -02:00", + "latitude": -73.477096, + "longitude": 121.203782, + "tags": [ + "aliquip", + "elit", + "ipsum", + "deserunt", + "culpa", + "esse", + "nulla" + ], + "friends": [ + { + "id": 0, + "name": "Cunningham Silva" + }, + { + "id": 1, + "name": "Maryellen Walters" + }, + { + "id": 2, + "name": "Donovan Oneil" + } + ], + "greeting": "Hello, Ivy Romero! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5ac06dd071153999d", + "index": 174, + "guid": "33ea2930-9fe7-4fd9-8615-9c0f4b36c168", + "isActive": true, + "balance": "$3,363.20", + "picture": "http://placehold.it/32x32", + "age": 22, + "eyeColor": "blue", + "name": "Doyle Schultz", + "gender": "male", + "company": "COASH", + "email": "doyleschultz@coash.com", + "phone": "+1 (988) 483-3834", + "address": "840 Revere Place, Johnsonburg, Alaska, 1955", + "about": "Labore sint exercitation tempor enim laboris adipisicing elit ex deserunt ex sit. Nulla consequat incididunt mollit elit adipisicing voluptate elit mollit. Proident ullamco eiusmod enim tempor laborum et aliqua proident enim veniam magna ipsum occaecat Lorem. Ea reprehenderit minim tempor nisi ea eu occaecat Lorem veniam duis occaecat. Laborum voluptate dolor irure aliquip ut ipsum deserunt dolor fugiat adipisicing. Anim id eiusmod aute occaecat mollit aute ullamco ut in velit aliqua dolor commodo.\r\n", + "registered": "2015-12-17T03:08:39 -01:00", + "latitude": -59.007671, + "longitude": -92.012459, + "tags": [ + "reprehenderit", + "aliqua", + "laboris", + "aliquip", + "voluptate", + "et", + "ad" + ], + "friends": [ + { + "id": 0, + "name": "Mcmahon Levy" + }, + { + "id": 1, + "name": "Houston Bray" + }, + { + "id": 2, + "name": "Reynolds Ashley" + } + ], + "greeting": "Hello, Doyle Schultz! You have 8 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee514eabefa72035b92", + "index": 175, + "guid": "c09013d9-bfe2-4097-969a-eba9b533ac0d", + "isActive": false, + "balance": "$1,218.63", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "blue", + "name": "Billie Mcclain", + "gender": "female", + "company": "ZILLA", + "email": "billiemcclain@zilla.com", + "phone": "+1 (939) 441-3854", + "address": "778 Narrows Avenue, Westmoreland, Missouri, 9993", + "about": "Ea do irure elit in ad consequat id et culpa qui commodo. Laborum sint laborum exercitation in dolore ex excepteur incididunt quis. Exercitation elit qui duis cillum. Exercitation culpa consectetur elit ex elit ut. Est ut duis qui nisi.\r\n", + "registered": "2018-10-27T07:58:53 -02:00", + "latitude": -67.117324, + "longitude": -5.343014, + "tags": [ + "enim", + "dolor", + "irure", + "deserunt", + "in", + "duis", + "nostrud" + ], + "friends": [ + { + "id": 0, + "name": "Perez Wiggins" + }, + { + "id": 1, + "name": "Bernard Britt" + }, + { + "id": 2, + "name": "Kerri Goff" + } + ], + "greeting": "Hello, Billie Mcclain! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee50b1baebcdfe5b33b", + "index": 176, + "guid": "635d98fc-1c55-49d7-a039-11f6ae43c43a", + "isActive": true, + "balance": "$3,481.37", + "picture": "http://placehold.it/32x32", + "age": 23, + "eyeColor": "green", + "name": "Cynthia Blackwell", + "gender": "female", + "company": "ZIORE", + "email": "cynthiablackwell@ziore.com", + "phone": "+1 (822) 498-3944", + "address": "353 Rapelye Street, Swartzville, Hawaii, 2739", + "about": "Qui minim laboris dolor mollit ullamco nostrud eu ex dolore incididunt laborum dolor ex est. Non incididunt dolor voluptate ad eiusmod non esse do sint in laboris. Consectetur Lorem est cillum exercitation ad enim sint elit occaecat proident. Ullamco exercitation voluptate ipsum tempor do laboris fugiat fugiat. Esse ipsum nostrud qui laboris amet qui nulla et. Aliqua do nisi velit mollit. Nostrud reprehenderit eu laborum fugiat exercitation nulla consequat qui labore ad laboris.\r\n", + "registered": "2021-03-20T07:25:21 -01:00", + "latitude": 71.504273, + "longitude": -48.503466, + "tags": [ + "laboris", + "magna", + "pariatur", + "Lorem", + "excepteur", + "laborum", + "aute" + ], + "friends": [ + { + "id": 0, + "name": "Holden Sexton" + }, + { + "id": 1, + "name": "Josefina Padilla" + }, + { + "id": 2, + "name": "Minnie Benton" + } + ], + "greeting": "Hello, Cynthia Blackwell! You have 8 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5385828fcb8785678", + "index": 177, + "guid": "f0563d7b-952c-4ee4-9f0a-adea7806f90a", + "isActive": false, + "balance": "$2,476.24", + "picture": "http://placehold.it/32x32", + "age": 29, + "eyeColor": "brown", + "name": "Nolan Marks", + "gender": "male", + "company": "COSMETEX", + "email": "nolanmarks@cosmetex.com", + "phone": "+1 (871) 576-2760", + "address": "749 Melba Court, Coleville, Ohio, 2692", + "about": "Eu mollit fugiat commodo occaecat reprehenderit laborum aliqua. Officia dolor dolore fugiat adipisicing cillum. Laboris quis commodo fugiat consequat ipsum eiusmod. Ex labore incididunt proident cillum reprehenderit enim est ad cupidatat do do nostrud enim. Aute ex id Lorem excepteur officia culpa culpa in velit et cillum exercitation.\r\n", + "registered": "2015-01-01T12:33:58 -01:00", + "latitude": 15.751578, + "longitude": 161.774895, + "tags": [ + "id", + "culpa", + "duis", + "exercitation", + "culpa", + "duis", + "ipsum" + ], + "friends": [ + { + "id": 0, + "name": "Araceli Frederick" + }, + { + "id": 1, + "name": "Dominguez Shepard" + }, + { + "id": 2, + "name": "Heidi Navarro" + } + ], + "greeting": "Hello, Nolan Marks! You have 7 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5e370e9ac53105b94", + "index": 178, + "guid": "1a6b6cbd-fb10-4ef4-b8b7-b408625a0df3", + "isActive": true, + "balance": "$2,766.91", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "blue", + "name": "Freeman Cooke", + "gender": "male", + "company": "TROPOLIS", + "email": "freemancooke@tropolis.com", + "phone": "+1 (845) 432-3747", + "address": "425 Pacific Street, Innsbrook, Federated States Of Micronesia, 9072", + "about": "Elit mollit ipsum sit qui non. Culpa aute sint laborum esse est excepteur laborum sunt dolor sunt irure duis. Tempor officia reprehenderit aliquip ex eu ipsum culpa est tempor qui. Anim reprehenderit ex commodo consequat qui duis Lorem consectetur anim ad. Velit in excepteur voluptate excepteur magna veniam ullamco labore proident qui incididunt. Incididunt incididunt non enim cillum. Dolore elit commodo et deserunt laborum tempor veniam irure officia.\r\n", + "registered": "2021-01-30T08:50:33 -01:00", + "latitude": 28.412115, + "longitude": 79.74984, + "tags": [ + "consectetur", + "qui", + "amet", + "sint", + "culpa", + "est", + "aliqua" + ], + "friends": [ + { + "id": 0, + "name": "Robles Cherry" + }, + { + "id": 1, + "name": "Natalia Lawrence" + }, + { + "id": 2, + "name": "Cox Barr" + } + ], + "greeting": "Hello, Freeman Cooke! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee536f826534ccaf41f", + "index": 179, + "guid": "3375cf5d-3e40-46aa-8660-e8b74e4dbbda", + "isActive": true, + "balance": "$3,699.35", + "picture": "http://placehold.it/32x32", + "age": 34, + "eyeColor": "green", + "name": "Margret Burke", + "gender": "female", + "company": "XURBAN", + "email": "margretburke@xurban.com", + "phone": "+1 (969) 436-2690", + "address": "853 Brightwater Court, Grazierville, New Hampshire, 5404", + "about": "Laborum aute nulla occaecat nostrud laborum aliqua est minim ad esse est. Nostrud duis sint consequat cillum non duis commodo qui. Occaecat qui culpa anim aliqua quis ex voluptate et anim Lorem. Lorem est nostrud aliqua sint sint. Officia irure proident occaecat esse et consequat amet deserunt dolore cillum labore magna ullamco duis. Non excepteur est qui in excepteur Lorem non quis irure id do non.\r\n", + "registered": "2018-09-08T09:52:09 -02:00", + "latitude": 5.739404, + "longitude": 134.947077, + "tags": [ + "officia", + "commodo", + "deserunt", + "in", + "laboris", + "id", + "eu" + ], + "friends": [ + { + "id": 0, + "name": "Joseph Whitfield" + }, + { + "id": 1, + "name": "Ofelia Hewitt" + }, + { + "id": 2, + "name": "Alfreda Hurley" + } + ], + "greeting": "Hello, Margret Burke! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee51703591fd4b016b5", + "index": 180, + "guid": "0c99e474-1559-4ea7-9a0b-1bcd1bfc3c4c", + "isActive": true, + "balance": "$3,647.91", + "picture": "http://placehold.it/32x32", + "age": 34, + "eyeColor": "brown", + "name": "Rowland Key", + "gender": "male", + "company": "DAIDO", + "email": "rowlandkey@daido.com", + "phone": "+1 (949) 480-3748", + "address": "323 Brevoort Place, Sunriver, Utah, 124", + "about": "Cupidatat sit sunt ea cupidatat duis ut sunt elit minim sunt sunt amet. Nulla anim qui labore laborum et mollit nostrud laboris esse. Consequat consequat officia aliqua proident cillum id dolore quis deserunt nostrud ea. Laborum consequat incididunt anim irure velit minim ad anim magna officia fugiat officia. Laborum sit culpa deserunt minim adipisicing non excepteur mollit velit laborum cillum fugiat. Mollit cillum duis magna esse fugiat cillum duis minim velit dolor aliquip laborum.\r\n", + "registered": "2021-08-17T08:53:42 -02:00", + "latitude": 49.784989, + "longitude": 60.020825, + "tags": [ + "reprehenderit", + "anim", + "nostrud", + "laboris", + "eiusmod", + "Lorem", + "veniam" + ], + "friends": [ + { + "id": 0, + "name": "Lawson May" + }, + { + "id": 1, + "name": "Paula Dillard" + }, + { + "id": 2, + "name": "Juanita Jackson" + } + ], + "greeting": "Hello, Rowland Key! You have 10 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5c406f01543349201", + "index": 181, + "guid": "6eec5374-b78e-4026-b2b7-a36f60e8c1db", + "isActive": false, + "balance": "$1,462.75", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "brown", + "name": "Martin Adams", + "gender": "male", + "company": "CORPULSE", + "email": "martinadams@corpulse.com", + "phone": "+1 (928) 462-3937", + "address": "378 Rockwell Place, Brule, Pennsylvania, 6830", + "about": "Ipsum ea minim sunt culpa eu duis consectetur minim velit officia exercitation est culpa commodo. Magna eu veniam amet dolor enim. Cupidatat magna eiusmod enim duis non ea dolor velit. Dolore cupidatat qui velit aute ut irure eiusmod aute velit deserunt excepteur. Reprehenderit eiusmod ipsum proident sunt laborum incididunt Lorem exercitation id et excepteur dolor. Cupidatat deserunt nostrud duis fugiat amet sit fugiat. Id nisi est sint minim fugiat elit id duis aliquip laborum officia amet dolor qui.\r\n", + "registered": "2017-01-11T10:02:22 -01:00", + "latitude": 26.755958, + "longitude": -72.794358, + "tags": [ + "adipisicing", + "ut", + "aliquip", + "consequat", + "pariatur", + "eiusmod", + "ex" + ], + "friends": [ + { + "id": 0, + "name": "Caroline Reese" + }, + { + "id": 1, + "name": "Potter Weiss" + }, + { + "id": 2, + "name": "Beatriz Conner" + } + ], + "greeting": "Hello, Martin Adams! You have 8 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5d4416ad8cb407f09", + "index": 182, + "guid": "3da24f84-21e4-4155-aa2a-c35ccdded1c0", + "isActive": true, + "balance": "$2,610.71", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "brown", + "name": "Josie Tate", + "gender": "female", + "company": "GREEKER", + "email": "josietate@greeker.com", + "phone": "+1 (938) 447-2928", + "address": "346 Canal Avenue, Cutter, North Dakota, 1151", + "about": "Ex amet ad ex sint tempor occaecat. Voluptate sint nostrud qui aliquip amet. Aliqua velit voluptate laboris laboris occaecat officia. Proident minim eu elit ipsum labore incididunt.\r\n", + "registered": "2016-06-14T09:43:00 -02:00", + "latitude": 68.979018, + "longitude": 161.867892, + "tags": [ + "enim", + "consectetur", + "dolore", + "sunt", + "commodo", + "laborum", + "aliquip" + ], + "friends": [ + { + "id": 0, + "name": "Mcdowell Jones" + }, + { + "id": 1, + "name": "Sofia Finley" + }, + { + "id": 2, + "name": "Reid Byers" + } + ], + "greeting": "Hello, Josie Tate! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5a95a7f9102521b83", + "index": 183, + "guid": "d7df7483-d192-4da6-90c4-a871be3d1845", + "isActive": true, + "balance": "$3,599.04", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "brown", + "name": "Katie Mcfarland", + "gender": "female", + "company": "ZENSURE", + "email": "katiemcfarland@zensure.com", + "phone": "+1 (936) 480-3070", + "address": "635 Adams Street, Kenwood, Delaware, 2234", + "about": "Aliqua amet nulla aliquip fugiat velit irure culpa laboris. Velit veniam aliqua incididunt adipisicing in sunt enim anim culpa mollit. Officia dolor dolor eiusmod ex eu ea labore. Deserunt duis amet veniam ipsum anim incididunt qui laborum eiusmod laboris occaecat.\r\n", + "registered": "2021-09-28T07:52:55 -02:00", + "latitude": 79.716579, + "longitude": 114.161419, + "tags": [ + "qui", + "ut", + "Lorem", + "voluptate", + "incididunt", + "mollit", + "pariatur" + ], + "friends": [ + { + "id": 0, + "name": "Amie Pruitt" + }, + { + "id": 1, + "name": "Terry Gibson" + }, + { + "id": 2, + "name": "Maritza Perkins" + } + ], + "greeting": "Hello, Katie Mcfarland! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5479b2f9b515d61ae", + "index": 184, + "guid": "dd149989-31dd-4b6a-b319-38256fb87364", + "isActive": true, + "balance": "$1,948.15", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "brown", + "name": "Velasquez Herring", + "gender": "male", + "company": "QUILK", + "email": "velasquezherring@quilk.com", + "phone": "+1 (893) 405-3872", + "address": "318 Nevins Street, Abiquiu, Nevada, 5283", + "about": "Velit culpa ut officia id proident exercitation. Incididunt laborum esse sunt quis reprehenderit cillum adipisicing. Culpa sunt amet ex culpa consequat et labore incididunt esse est.\r\n", + "registered": "2015-01-09T10:43:24 -01:00", + "latitude": -42.638841, + "longitude": 50.378183, + "tags": [ + "proident", + "labore", + "aute", + "ut", + "sunt", + "eiusmod", + "et" + ], + "friends": [ + { + "id": 0, + "name": "Park Francis" + }, + { + "id": 1, + "name": "Phoebe Dickerson" + }, + { + "id": 2, + "name": "Barlow Pickett" + } + ], + "greeting": "Hello, Velasquez Herring! You have 3 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee55ec1c08bd5ea9d7e", + "index": 185, + "guid": "1bb73050-9d92-4090-a21b-fb07f14b8a94", + "isActive": false, + "balance": "$2,631.78", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "green", + "name": "Annabelle Forbes", + "gender": "female", + "company": "DIGIAL", + "email": "annabelleforbes@digial.com", + "phone": "+1 (961) 419-2904", + "address": "538 Oxford Street, Hanover, Montana, 2981", + "about": "Excepteur nulla deserunt est do non officia. Pariatur velit veniam sint exercitation laboris amet ipsum aute pariatur. Esse ad cupidatat deserunt amet ad aliquip veniam.\r\n", + "registered": "2017-05-03T05:48:08 -02:00", + "latitude": -32.506727, + "longitude": 73.237161, + "tags": [ + "sint", + "proident", + "nulla", + "nostrud", + "nostrud", + "deserunt", + "id" + ], + "friends": [ + { + "id": 0, + "name": "Barnes Mccall" + }, + { + "id": 1, + "name": "Sylvia Mccoy" + }, + { + "id": 2, + "name": "Murray Higgins" + } + ], + "greeting": "Hello, Annabelle Forbes! You have 6 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee519d3994fa42035b3", + "index": 186, + "guid": "216b152c-b290-403e-bd84-4f5dd6eaea85", + "isActive": false, + "balance": "$3,413.79", + "picture": "http://placehold.it/32x32", + "age": 35, + "eyeColor": "blue", + "name": "Underwood Mcleod", + "gender": "male", + "company": "NETILITY", + "email": "underwoodmcleod@netility.com", + "phone": "+1 (966) 595-3474", + "address": "687 Boardwalk , Sardis, Arizona, 157", + "about": "Reprehenderit veniam pariatur eiusmod dolore aliqua aliqua. Excepteur id aute officia esse ex. Irure aliqua dolore nulla id amet excepteur Lorem occaecat reprehenderit qui in nulla velit.\r\n", + "registered": "2020-04-23T06:13:25 -02:00", + "latitude": 69.512941, + "longitude": -24.381398, + "tags": [ + "nostrud", + "adipisicing", + "amet", + "eiusmod", + "ipsum", + "aute", + "incididunt" + ], + "friends": [ + { + "id": 0, + "name": "Rowe Everett" + }, + { + "id": 1, + "name": "Janelle Estes" + }, + { + "id": 2, + "name": "Farmer Valentine" + } + ], + "greeting": "Hello, Underwood Mcleod! You have 9 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee5480d27f6da7f9029", + "index": 187, + "guid": "9e70f44c-9794-4e92-9eae-10b3d469929e", + "isActive": false, + "balance": "$1,207.48", + "picture": "http://placehold.it/32x32", + "age": 40, + "eyeColor": "brown", + "name": "Weeks Marquez", + "gender": "male", + "company": "DIGIPRINT", + "email": "weeksmarquez@digiprint.com", + "phone": "+1 (998) 466-2001", + "address": "266 Ocean Avenue, Jeff, Massachusetts, 3696", + "about": "Excepteur dolor exercitation et amet sunt eiusmod duis consectetur adipisicing cupidatat labore. Amet veniam nisi qui adipisicing deserunt id reprehenderit quis. Aliquip et anim id eu elit consequat eiusmod dolor in culpa. Eiusmod nulla id voluptate velit qui exercitation qui proident exercitation incididunt ea excepteur. Labore consectetur ullamco sit nulla. Adipisicing ut fugiat ipsum nulla commodo cupidatat ex. Aliquip aute culpa duis elit.\r\n", + "registered": "2019-03-26T01:36:53 -01:00", + "latitude": 34.46401, + "longitude": -84.92845, + "tags": [ + "incididunt", + "qui", + "velit", + "commodo", + "cupidatat", + "laboris", + "sint" + ], + "friends": [ + { + "id": 0, + "name": "Talley Reed" + }, + { + "id": 1, + "name": "Preston David" + }, + { + "id": 2, + "name": "Alisha Tyler" + } + ], + "greeting": "Hello, Weeks Marquez! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5501571da92a9fb20", + "index": 188, + "guid": "f2ae4f60-45f9-47db-81bf-733aaa3cc0d2", + "isActive": false, + "balance": "$2,546.05", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "blue", + "name": "Freida Lowe", + "gender": "female", + "company": "PLASTO", + "email": "freidalowe@plasto.com", + "phone": "+1 (872) 410-3030", + "address": "810 Dunham Place, Emison, Maryland, 788", + "about": "Qui proident ea reprehenderit culpa aute sint et officia anim do adipisicing Lorem Lorem. Laboris reprehenderit quis laboris adipisicing. Minim id voluptate incididunt culpa eiusmod et laboris. Nisi amet in do proident sit incididunt tempor esse. Ut consectetur aliquip mollit consequat ex anim laboris. Pariatur duis cillum commodo voluptate nulla ea pariatur exercitation veniam. Excepteur cupidatat cillum Lorem dolor aute laboris.\r\n", + "registered": "2019-01-18T05:16:28 -01:00", + "latitude": -30.465874, + "longitude": 41.428646, + "tags": [ + "pariatur", + "proident", + "amet", + "do", + "quis", + "proident", + "officia" + ], + "friends": [ + { + "id": 0, + "name": "Watts Conley" + }, + { + "id": 1, + "name": "Frederick Whitehead" + }, + { + "id": 2, + "name": "Louella Booker" + } + ], + "greeting": "Hello, Freida Lowe! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee589ff52469cf1a971", + "index": 189, + "guid": "5f582990-d296-4a2d-8a44-be0bfd04492c", + "isActive": true, + "balance": "$3,548.74", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "blue", + "name": "Snow Buckner", + "gender": "male", + "company": "DIGIRANG", + "email": "snowbuckner@digirang.com", + "phone": "+1 (874) 447-3630", + "address": "142 Midwood Street, Abrams, Florida, 1957", + "about": "Reprehenderit anim eu sit nostrud ut labore ad esse exercitation nisi dolor sint commodo. Aliqua anim mollit tempor sit proident proident pariatur Lorem elit. Sint laborum aute duis minim. Nisi dolor esse est enim qui aute dolor. Est ad cupidatat culpa ex fugiat est consequat ad eiusmod. Duis voluptate occaecat ullamco sint. Dolor est reprehenderit nostrud anim elit laborum pariatur aute adipisicing cillum proident dolor.\r\n", + "registered": "2018-04-29T12:53:56 -02:00", + "latitude": -50.925581, + "longitude": -152.924382, + "tags": [ + "labore", + "irure", + "ullamco", + "labore", + "cillum", + "eiusmod", + "aliqua" + ], + "friends": [ + { + "id": 0, + "name": "Silvia Porter" + }, + { + "id": 1, + "name": "Thelma Rosales" + }, + { + "id": 2, + "name": "Tamika Morales" + } + ], + "greeting": "Hello, Snow Buckner! You have 7 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee519ce5a1c019e15a3", + "index": 190, + "guid": "f9d94d39-f17e-4201-adbc-60e2772d8ed7", + "isActive": false, + "balance": "$3,716.16", + "picture": "http://placehold.it/32x32", + "age": 32, + "eyeColor": "green", + "name": "Olive Wood", + "gender": "female", + "company": "SONIQUE", + "email": "olivewood@sonique.com", + "phone": "+1 (904) 445-3806", + "address": "118 Bainbridge Street, Newcastle, Washington, 5600", + "about": "Do nulla tempor dolore et excepteur anim tempor nostrud ipsum. Aute nostrud enim exercitation elit veniam aute Lorem. Sunt duis voluptate nisi elit mollit et do nostrud elit anim pariatur adipisicing incididunt. Eiusmod nulla nostrud consequat incididunt qui ad nulla dolore veniam sunt velit officia ad. Ad velit amet cupidatat in ad occaecat.\r\n", + "registered": "2014-07-16T06:21:27 -02:00", + "latitude": 57.237106, + "longitude": -79.252817, + "tags": [ + "occaecat", + "incididunt", + "do", + "sit", + "veniam", + "enim", + "est" + ], + "friends": [ + { + "id": 0, + "name": "Hughes Stevens" + }, + { + "id": 1, + "name": "Higgins Adkins" + }, + { + "id": 2, + "name": "Laura Mercer" + } + ], + "greeting": "Hello, Olive Wood! You have 7 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5dee040a602f428c1", + "index": 191, + "guid": "c3bf584f-ffb2-4f61-8f68-ae0ba14d9a2c", + "isActive": true, + "balance": "$1,770.68", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "brown", + "name": "Clark Obrien", + "gender": "male", + "company": "SLAX", + "email": "clarkobrien@slax.com", + "phone": "+1 (954) 457-3809", + "address": "969 Harbor Lane, Clay, Virginia, 180", + "about": "Amet esse sunt ex in nisi. Dolore dolore laborum culpa mollit culpa fugiat reprehenderit ex ea nulla elit. Commodo id deserunt cupidatat dolore aliqua nulla in culpa pariatur proident aute id minim culpa.\r\n", + "registered": "2018-02-02T12:35:06 -01:00", + "latitude": -17.229035, + "longitude": 99.502623, + "tags": [ + "consectetur", + "consectetur", + "ullamco", + "reprehenderit", + "non", + "pariatur", + "duis" + ], + "friends": [ + { + "id": 0, + "name": "Decker Tucker" + }, + { + "id": 1, + "name": "Laurel Little" + }, + { + "id": 2, + "name": "Angel Vazquez" + } + ], + "greeting": "Hello, Clark Obrien! You have 5 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee53eb3d612e8440c28", + "index": 192, + "guid": "4efe5f47-f152-425b-a4aa-c8ff402898b6", + "isActive": true, + "balance": "$1,160.16", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "green", + "name": "Petersen Landry", + "gender": "male", + "company": "BUNGA", + "email": "petersenlandry@bunga.com", + "phone": "+1 (948) 431-3897", + "address": "239 Mayfair Drive, Glendale, Oklahoma, 2717", + "about": "Proident mollit Lorem commodo fugiat duis officia anim sint ut velit occaecat esse aliqua. Incididunt ut non pariatur eu proident ea occaecat veniam excepteur. Non cillum non minim ullamco occaecat qui excepteur sint exercitation ut pariatur voluptate non. Dolore dolore esse non voluptate commodo sint non reprehenderit esse eu.\r\n", + "registered": "2020-09-08T03:16:07 -02:00", + "latitude": -20.682819, + "longitude": 146.076896, + "tags": [ + "aute", + "exercitation", + "non", + "eu", + "enim", + "qui", + "velit" + ], + "friends": [ + { + "id": 0, + "name": "Doreen Hutchinson" + }, + { + "id": 1, + "name": "Watson Barton" + }, + { + "id": 2, + "name": "Rita Mejia" + } + ], + "greeting": "Hello, Petersen Landry! You have 5 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5ad015538a90435d4", + "index": 193, + "guid": "987667ab-941b-49ab-a59a-e53da8c74ae7", + "isActive": true, + "balance": "$3,147.39", + "picture": "http://placehold.it/32x32", + "age": 25, + "eyeColor": "blue", + "name": "Adeline Patterson", + "gender": "female", + "company": "ENTALITY", + "email": "adelinepatterson@entality.com", + "phone": "+1 (887) 474-2539", + "address": "548 Benson Avenue, Malo, Mississippi, 8937", + "about": "Nulla sunt est qui aliquip ut eiusmod velit esse. Duis cupidatat qui nostrud sint mollit veniam nulla cillum laborum. Minim pariatur nisi ea consequat labore ipsum quis laboris fugiat. Aliquip commodo cillum laborum ex minim sunt sint commodo consequat ut sunt amet est occaecat. Occaecat non ut ad sit elit occaecat laboris culpa Lorem aute aliquip culpa in.\r\n", + "registered": "2019-07-04T07:31:49 -02:00", + "latitude": 25.737567, + "longitude": 150.633802, + "tags": [ + "quis", + "consequat", + "id", + "enim", + "occaecat", + "dolor", + "nisi" + ], + "friends": [ + { + "id": 0, + "name": "Cherry Stokes" + }, + { + "id": 1, + "name": "Madden Cotton" + }, + { + "id": 2, + "name": "Robin Dean" + } + ], + "greeting": "Hello, Adeline Patterson! You have 1 unread messages.", + "favoriteFruit": "strawberry" + }, + { + "_id": "616eeee516ccdfda4ab4c71b", + "index": 194, + "guid": "d275e7e4-fedc-4b60-ad16-95986230c7ee", + "isActive": true, + "balance": "$3,716.32", + "picture": "http://placehold.it/32x32", + "age": 34, + "eyeColor": "blue", + "name": "Sandoval Carter", + "gender": "male", + "company": "GEEKKO", + "email": "sandovalcarter@geekko.com", + "phone": "+1 (862) 532-3993", + "address": "375 Bergen Court, Lopezo, Wisconsin, 8079", + "about": "Magna enim est velit veniam reprehenderit esse cupidatat cupidatat ipsum ad. Pariatur commodo magna aliquip voluptate enim. Ex fugiat officia quis et. Cillum esse consectetur fugiat mollit cillum consectetur sint ex. Fugiat tempor id ullamco anim amet culpa id ea ut aute commodo dolore tempor eiusmod.\r\n", + "registered": "2019-01-31T03:02:07 -01:00", + "latitude": -89.254177, + "longitude": 57.507808, + "tags": [ + "velit", + "laborum", + "Lorem", + "Lorem", + "commodo", + "excepteur", + "duis" + ], + "friends": [ + { + "id": 0, + "name": "Kim Church" + }, + { + "id": 1, + "name": "Leticia Pugh" + }, + { + "id": 2, + "name": "Shirley Maynard" + } + ], + "greeting": "Hello, Sandoval Carter! You have 3 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee580731f0d0258baad", + "index": 195, + "guid": "6df94b5f-c7c6-46ed-9ee9-373916c7bdee", + "isActive": false, + "balance": "$2,970.18", + "picture": "http://placehold.it/32x32", + "age": 39, + "eyeColor": "green", + "name": "Clay Mcmillan", + "gender": "male", + "company": "STEELTAB", + "email": "claymcmillan@steeltab.com", + "phone": "+1 (832) 487-3960", + "address": "360 Junius Street, Mayfair, South Dakota, 6507", + "about": "Ea magna tempor nulla commodo. Deserunt ex eiusmod consectetur officia ipsum aliquip eu. Incididunt esse nostrud tempor tempor ullamco aliqua officia nulla cillum consequat nisi reprehenderit consectetur amet. Est labore anim reprehenderit nulla esse esse irure minim occaecat.\r\n", + "registered": "2014-10-04T06:02:07 -02:00", + "latitude": -58.892437, + "longitude": -141.808041, + "tags": [ + "velit", + "ex", + "sit", + "voluptate", + "pariatur", + "culpa", + "deserunt" + ], + "friends": [ + { + "id": 0, + "name": "Kathy Peck" + }, + { + "id": 1, + "name": "Middleton Joseph" + }, + { + "id": 2, + "name": "Shelley Fernandez" + } + ], + "greeting": "Hello, Clay Mcmillan! You have 1 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee50ba1e50a969e00b9", + "index": 196, + "guid": "4c34f739-c61a-442a-bb62-1da863649931", + "isActive": true, + "balance": "$3,077.59", + "picture": "http://placehold.it/32x32", + "age": 38, + "eyeColor": "green", + "name": "Branch Chase", + "gender": "male", + "company": "DIGINETIC", + "email": "branchchase@diginetic.com", + "phone": "+1 (843) 462-3629", + "address": "442 Newel Street, Tilden, Georgia, 1782", + "about": "Culpa consectetur duis dolore mollit proident velit ipsum ex id occaecat consequat. Anim est irure incididunt eu non dolor ea irure et. Aliqua voluptate officia sit amet voluptate ea incididunt culpa laboris adipisicing anim excepteur voluptate qui. Occaecat exercitation anim duis culpa et non dolor.\r\n", + "registered": "2015-03-08T04:58:20 -01:00", + "latitude": -0.692459, + "longitude": 11.851837, + "tags": [ + "do", + "et", + "aliquip", + "consequat", + "consequat", + "est", + "ut" + ], + "friends": [ + { + "id": 0, + "name": "Carole Compton" + }, + { + "id": 1, + "name": "Manning Rodriquez" + }, + { + "id": 2, + "name": "Deidre Hill" + } + ], + "greeting": "Hello, Branch Chase! You have 9 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee5468565b47781602b", + "index": 197, + "guid": "edba7486-da4f-4572-8c4e-1669eb6c48ff", + "isActive": true, + "balance": "$3,714.40", + "picture": "http://placehold.it/32x32", + "age": 30, + "eyeColor": "brown", + "name": "Noble Spencer", + "gender": "male", + "company": "BLANET", + "email": "noblespencer@blanet.com", + "phone": "+1 (991) 487-2284", + "address": "411 Applegate Court, Why, Connecticut, 7344", + "about": "Proident incididunt Lorem ipsum minim nisi culpa. Aute irure laboris incididunt eiusmod sit mollit nisi elit nulla. Ut excepteur ut laborum cupidatat. Non in exercitation laborum proident pariatur consectetur nostrud et officia. Id fugiat non sunt consequat tempor deserunt mollit laborum reprehenderit aute ex laborum dolor duis. Deserunt proident cupidatat dolore commodo culpa veniam ex nisi dolor do sunt pariatur aliqua. In ex ullamco sunt fugiat.\r\n", + "registered": "2019-06-01T09:11:37 -02:00", + "latitude": -6.339032, + "longitude": 7.267724, + "tags": [ + "magna", + "ut", + "do", + "ut", + "officia", + "esse", + "ea" + ], + "friends": [ + { + "id": 0, + "name": "Marie Gaines" + }, + { + "id": 1, + "name": "Janell Aguirre" + }, + { + "id": 2, + "name": "Alissa West" + } + ], + "greeting": "Hello, Noble Spencer! You have 4 unread messages.", + "favoriteFruit": "apple" + }, + { + "_id": "616eeee5a2d0077c4911f556", + "index": 198, + "guid": "dee72d60-4aab-4e07-ba22-9b26181b2c01", + "isActive": false, + "balance": "$1,199.25", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "blue", + "name": "Luisa Baker", + "gender": "female", + "company": "ZOSIS", + "email": "luisabaker@zosis.com", + "phone": "+1 (800) 474-2680", + "address": "317 Cozine Avenue, Laurelton, West Virginia, 2633", + "about": "Velit eu ex nisi laboris. Proident dolor cillum nulla tempor nisi voluptate mollit labore anim excepteur. Est occaecat cillum deserunt est aliquip elit ex consectetur labore. Commodo enim eu excepteur nostrud officia consequat aliqua quis sit proident sit cupidatat.\r\n", + "registered": "2015-10-06T07:18:36 -02:00", + "latitude": 6.395792, + "longitude": -133.28126, + "tags": [ + "adipisicing", + "do", + "consectetur", + "sit", + "aliquip", + "sint", + "deserunt" + ], + "friends": [ + { + "id": 0, + "name": "Jody Baldwin" + }, + { + "id": 1, + "name": "Deana Barry" + }, + { + "id": 2, + "name": "Jaclyn Anderson" + } + ], + "greeting": "Hello, Luisa Baker! You have 2 unread messages.", + "favoriteFruit": "banana" + }, + { + "_id": "616eeee55db3fd71d8fadcb8", + "index": 199, + "guid": "bc5950ea-01ab-4ab1-9e96-1771936b453a", + "isActive": true, + "balance": "$1,265.22", + "picture": "http://placehold.it/32x32", + "age": 27, + "eyeColor": "blue", + "name": "Kelly Golden", + "gender": "male", + "company": "MACRONAUT", + "email": "kellygolden@macronaut.com", + "phone": "+1 (914) 524-3436", + "address": "780 Pooles Lane, Maybell, Marshall Islands, 4481", + "about": "Fugiat pariatur sit magna mollit sunt. Incididunt consectetur magna irure anim. Commodo sunt do est sit in Lorem excepteur voluptate fugiat eiusmod duis aute esse. Fugiat nisi aliquip ea minim. Sunt eiusmod ex ex ipsum sit elit et laboris labore excepteur commodo.\r\n", + "registered": "2017-08-11T03:14:35 -02:00", + "latitude": -72.17515, + "longitude": 92.503238, + "tags": [ + "laborum", + "velit", + "est", + "elit", + "excepteur", + "et", + "nostrud" + ], + "friends": [ + { + "id": 0, + "name": "Becker Rollins" + }, + { + "id": 1, + "name": "Curry Mcfadden" + }, + { + "id": 2, + "name": "Henderson Delaney" + } + ], + "greeting": "Hello, Kelly Golden! You have 3 unread messages.", + "favoriteFruit": "apple" + } +] diff --git a/src/subprojects/packcc/benchmark/inputs/kotlin.kt b/src/subprojects/packcc/benchmark/inputs/kotlin.kt new file mode 100644 index 00000000..9c5e61f6 --- /dev/null +++ b/src/subprojects/packcc/benchmark/inputs/kotlin.kt @@ -0,0 +1,1175 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.renderer + +import org.jetbrains.kotlin.builtins.* +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotated +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject +import org.jetbrains.kotlin.resolve.constants.AnnotationValue +import org.jetbrains.kotlin.resolve.constants.ArrayValue +import org.jetbrains.kotlin.resolve.constants.ConstantValue +import org.jetbrains.kotlin.resolve.constants.KClassValue +import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass +import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.ErrorUtils.UninferredParameterTypeConstructor +import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE +import java.util.* + +internal class DescriptorRendererImpl( + val options: DescriptorRendererOptionsImpl +) : DescriptorRenderer(), DescriptorRendererOptions by options/* this gives access to options without qualifier */ { + init { + assert(options.isLocked) + } + + private val functionTypeAnnotationsRenderer: DescriptorRendererImpl by lazy { + withOptions { + excludedTypeAnnotationClasses += listOf(StandardNames.FqNames.extensionFunctionType) + annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.ALWAYS_PARENTHESIZED + } as DescriptorRendererImpl + } + + /* FORMATTING */ + private fun renderKeyword(keyword: String): String = when (textFormat) { + RenderingFormat.PLAIN -> keyword + RenderingFormat.HTML -> if (boldOnlyForNamesInHtml) keyword else "$keyword" + } + + private fun renderError(keyword: String): String = when (textFormat) { + RenderingFormat.PLAIN -> keyword + RenderingFormat.HTML -> "$keyword" + } + + private fun escape(string: String) = textFormat.escape(string) + + private fun lt() = escape("<") + private fun gt() = escape(">") + + private fun arrow(): String = when (textFormat) { + RenderingFormat.PLAIN -> escape("->") + RenderingFormat.HTML -> "→" + } + + override fun renderMessage(message: String): String = when (textFormat) { + RenderingFormat.PLAIN -> message + RenderingFormat.HTML -> "$message" + } + + /* NAMES RENDERING */ + override fun renderName(name: Name, rootRenderedElement: Boolean): String { + val escaped = escape(name.render()) + return if (boldOnlyForNamesInHtml && textFormat == RenderingFormat.HTML && rootRenderedElement) { + "$escaped" + } else + escaped + } + + private fun renderName(descriptor: DeclarationDescriptor, builder: StringBuilder, rootRenderedElement: Boolean) { + builder.append(renderName(descriptor.name, rootRenderedElement)) + } + + private fun renderCompanionObjectName(descriptor: DeclarationDescriptor, builder: StringBuilder) { + if (renderCompanionObjectName) { + if (startFromName) { + builder.append("companion object") + } + renderSpaceIfNeeded(builder) + val containingDeclaration = descriptor.containingDeclaration + if (containingDeclaration != null) { + builder.append("of ") + builder.append(renderName(containingDeclaration.name, false)) + } + } + if (verbose || descriptor.name != SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT) { + if (!startFromName) renderSpaceIfNeeded(builder) + builder.append(renderName(descriptor.name, true)) + } + } + + override fun renderFqName(fqName: FqNameUnsafe) = renderFqName(fqName.pathSegments()) + + private fun renderFqName(pathSegments: List) = escape(org.jetbrains.kotlin.renderer.renderFqName(pathSegments)) + + override fun renderClassifierName(klass: ClassifierDescriptor): String = if (ErrorUtils.isError(klass)) { + klass.typeConstructor.toString() + } else + classifierNamePolicy.renderClassifier(klass, this) + + /* TYPES RENDERING */ + override fun renderType(type: KotlinType): String = buildString { + renderNormalizedType(typeNormalizer(type)) + } + + private fun StringBuilder.renderNormalizedType(type: KotlinType) { + val abbreviated = type.unwrap() as? AbbreviatedType + if (abbreviated != null) { + if (renderTypeExpansions) { + renderNormalizedTypeAsIs(abbreviated.expandedType) + } else { + // TODO nullability is lost for abbreviated type? + renderNormalizedTypeAsIs(abbreviated.abbreviation) + if (renderUnabbreviatedType) { + renderAbbreviatedTypeExpansion(abbreviated) + } + } + return + } + + renderNormalizedTypeAsIs(type) + } + + private fun StringBuilder.renderAbbreviatedTypeExpansion(abbreviated: AbbreviatedType) { + if (textFormat == RenderingFormat.HTML) { + append("") + } + append(" /* = ") + renderNormalizedTypeAsIs(abbreviated.expandedType) + append(" */") + if (textFormat == RenderingFormat.HTML) { + append("") + } + } + + private fun StringBuilder.renderNormalizedTypeAsIs(type: KotlinType) { + if (type is WrappedType && debugMode && !type.isComputed()) { + append("") + return + } + when (val unwrappedType = type.unwrap()) { + is FlexibleType -> append(unwrappedType.render(this@DescriptorRendererImpl, this@DescriptorRendererImpl)) + is SimpleType -> renderSimpleType(unwrappedType) + } + } + + private fun StringBuilder.renderSimpleType(type: SimpleType) { + if (type == CANT_INFER_FUNCTION_PARAM_TYPE || TypeUtils.isDontCarePlaceholder(type)) { + append("???") + return + } + if (ErrorUtils.isUninferredParameter(type)) { + if (uninferredTypeParameterAsName) { + append(renderError((type.constructor as UninferredParameterTypeConstructor).typeParameterDescriptor.name.toString())) + } else { + append("???") + } + return + } + + if (type.isError) { + renderDefaultType(type) + return + } + if (shouldRenderAsPrettyFunctionType(type)) { + renderFunctionType(type) + } else { + renderDefaultType(type) + } + } + + private fun shouldRenderAsPrettyFunctionType(type: KotlinType): Boolean { + return type.isBuiltinFunctionalType && type.arguments.none { it.isStarProjection } + } + + override fun renderFlexibleType(lowerRendered: String, upperRendered: String, builtIns: KotlinBuiltIns): String { + if (differsOnlyInNullability(lowerRendered, upperRendered)) { + if (upperRendered.startsWith("(")) { + // the case of complex type, e.g. (() -> Unit)? + return "($lowerRendered)!" + } + return "$lowerRendered!" + } + + val kotlinCollectionsPrefix = classifierNamePolicy.renderClassifier(builtIns.collection, this).substringBefore("Collection") + val mutablePrefix = "Mutable" + // java.util.List -> (Mutable)List! + val simpleCollection = replacePrefixes( + lowerRendered, + kotlinCollectionsPrefix + mutablePrefix, + upperRendered, + kotlinCollectionsPrefix, + "$kotlinCollectionsPrefix($mutablePrefix)" + ) + if (simpleCollection != null) return simpleCollection + // java.util.Map.Entry -> (Mutable)Map.(Mutable)Entry! + val mutableEntry = replacePrefixes( + lowerRendered, + kotlinCollectionsPrefix + "MutableMap.MutableEntry", + upperRendered, + kotlinCollectionsPrefix + "Map.Entry", + "$kotlinCollectionsPrefix(Mutable)Map.(Mutable)Entry" + ) + if (mutableEntry != null) return mutableEntry + + val kotlinPrefix = classifierNamePolicy.renderClassifier(builtIns.array, this).substringBefore("Array") + // Foo[] -> Array<(out) Foo!>! + val array = replacePrefixes( + lowerRendered, + kotlinPrefix + escape("Array<"), + upperRendered, + kotlinPrefix + escape("Array): String = if (typeArguments.isEmpty()) "" + else buildString { + append(lt()) + this.appendTypeProjections(typeArguments) + append(gt()) + } + + private fun StringBuilder.renderDefaultType(type: KotlinType) { + this.renderAnnotations(type) + + if (type.isError) { + if (type is UnresolvedType && presentableUnresolvedTypes) { + append(type.presentableName) + } else { + if (type is ErrorType && !informativeErrorType) { + append(type.presentableName) + } else { + append(type.constructor.toString()) // Debug name of an error type is more informative + } + } + append(renderTypeArguments(type.arguments)) + } else { + renderTypeConstructorAndArguments(type) + } + + if (type.isMarkedNullable) { + append("?") + } + + if (type.isDefinitelyNotNullType) { + append("!!") + } + } + + private fun StringBuilder.renderTypeConstructorAndArguments( + type: KotlinType, + typeConstructor: TypeConstructor = type.constructor + ) { + val possiblyInnerType = type.buildPossiblyInnerType() + if (possiblyInnerType == null) { + append(renderTypeConstructor(typeConstructor)) + append(renderTypeArguments(type.arguments)) + return + } + + renderPossiblyInnerType(possiblyInnerType) + } + + private fun StringBuilder.renderPossiblyInnerType(possiblyInnerType: PossiblyInnerType) { + possiblyInnerType.outerType?.let { + renderPossiblyInnerType(it) + append('.') + append(renderName(possiblyInnerType.classifierDescriptor.name, false)) + } ?: append(renderTypeConstructor(possiblyInnerType.classifierDescriptor.typeConstructor)) + + append(renderTypeArguments(possiblyInnerType.arguments)) + } + + override fun renderTypeConstructor(typeConstructor: TypeConstructor): String = when (val cd = typeConstructor.declarationDescriptor) { + is TypeParameterDescriptor, is ClassDescriptor, is TypeAliasDescriptor -> renderClassifierName(cd) + null -> typeConstructor.toString() + else -> error("Unexpected classifier: " + cd::class.java) + } + + override fun renderTypeProjection(typeProjection: TypeProjection) = buildString { + appendTypeProjections(listOf(typeProjection)) + } + + private fun StringBuilder.appendTypeProjections(typeProjections: List) { + typeProjections.joinTo(this, ", ") { + if (it.isStarProjection) { + "*" + } else { + val type = renderType(it.type) + if (it.projectionKind == Variance.INVARIANT) type else "${it.projectionKind} $type" + } + } + } + + private fun StringBuilder.renderFunctionType(type: KotlinType) { + val lengthBefore = length + // we need special renderer to skip @ExtensionFunctionType + with(functionTypeAnnotationsRenderer) { + renderAnnotations(type) + } + val hasAnnotations = length != lengthBefore + + val isSuspend = type.isSuspendFunctionType + val isNullable = type.isMarkedNullable + val receiverType = type.getReceiverTypeFromFunctionType() + + val needParenthesis = isNullable || (hasAnnotations && receiverType != null) + if (needParenthesis) { + if (isSuspend) { + insert(lengthBefore, '(') + } else { + if (hasAnnotations) { + assert(last() == ' ') + if (get(lastIndex - 1) != ')') { + // last annotation rendered without parenthesis - need to add them otherwise parsing will be incorrect + insert(lastIndex, "()") + } + } + + append("(") + } + } + + renderModifier(this, isSuspend, "suspend") + + if (receiverType != null) { + val surroundReceiver = shouldRenderAsPrettyFunctionType(receiverType) && !receiverType.isMarkedNullable || + receiverType.hasModifiersOrAnnotations() + if (surroundReceiver) { + append("(") + } + renderNormalizedType(receiverType) + if (surroundReceiver) { + append(")") + } + append(".") + } + + append("(") + + val parameterTypes = type.getValueParameterTypesFromFunctionType() + for ((index, typeProjection) in parameterTypes.withIndex()) { + if (index > 0) append(", ") + + val name = if (parameterNamesInFunctionalTypes) typeProjection.type.extractParameterNameFromFunctionTypeArgument() else null + if (name != null) { + append(renderName(name, false)) + append(": ") + } + + append(renderTypeProjection(typeProjection)) + } + + append(") ").append(arrow()).append(" ") + renderNormalizedType(type.getReturnTypeFromFunctionType()) + + if (needParenthesis) append(")") + + if (isNullable) append("?") + } + + private fun KotlinType.hasModifiersOrAnnotations() = + isSuspendFunctionType || !annotations.isEmpty() + + /* METHODS FOR ALL KINDS OF DESCRIPTORS */ + private fun StringBuilder.appendDefinedIn(descriptor: DeclarationDescriptor) { + if (descriptor is PackageFragmentDescriptor || descriptor is PackageViewDescriptor) { + return + } + if (descriptor is ModuleDescriptor) { + append(" is a module") + return + } + + val containingDeclaration = descriptor.containingDeclaration + if (containingDeclaration != null && containingDeclaration !is ModuleDescriptor) { + append(" ").append(renderMessage("defined in")).append(" ") + val fqName = DescriptorUtils.getFqName(containingDeclaration) + append(if (fqName.isRoot) "root package" else renderFqName(fqName)) + + if (withSourceFileForTopLevel && + containingDeclaration is PackageFragmentDescriptor && + descriptor is DeclarationDescriptorWithSource + ) { + descriptor.source.containingFile.name?.let { sourceFileName -> + append(" ").append(renderMessage("in file")).append(" ").append(sourceFileName) + } + } + } + } + + private fun StringBuilder.renderAnnotations(annotated: Annotated, target: AnnotationUseSiteTarget? = null) { + if (DescriptorRendererModifier.ANNOTATIONS !in modifiers) return + + val excluded = if (annotated is KotlinType) excludedTypeAnnotationClasses else excludedAnnotationClasses + + val annotationFilter = annotationFilter + for (annotation in annotated.annotations) { + if (annotation.fqName !in excluded + && !annotation.isParameterName() + && (annotationFilter == null || annotationFilter(annotation)) + ) { + append(renderAnnotation(annotation, target)) + if (eachAnnotationOnNewLine) { + appendLine() + } else { + append(" ") + } + } + } + } + + private fun AnnotationDescriptor.isParameterName(): Boolean { + return fqName == StandardNames.FqNames.parameterName + } + + override fun renderAnnotation(annotation: AnnotationDescriptor, target: AnnotationUseSiteTarget?): String { + return buildString { + append('@') + if (target != null) { + append(target.renderName + ":") + } + val annotationType = annotation.type + append(renderType(annotationType)) + + if (includeAnnotationArguments) { + val arguments = renderAndSortAnnotationArguments(annotation) + if (includeEmptyAnnotationArguments || arguments.isNotEmpty()) { + arguments.joinTo(this, ", ", "(", ")") + } + } + + if (verbose && (annotationType.isError || annotationType.constructor.declarationDescriptor is NotFoundClasses.MockClassDescriptor)) { + append(" /* annotation class not found */") + } + } + } + + private fun renderAndSortAnnotationArguments(descriptor: AnnotationDescriptor): List { + val allValueArguments = descriptor.allValueArguments + val classDescriptor = if (renderDefaultAnnotationArguments) descriptor.annotationClass else null + val parameterDescriptorsWithDefaultValue = classDescriptor?.unsubstitutedPrimaryConstructor?.valueParameters + ?.filter { it.declaresDefaultValue() } + ?.map { it.name } + .orEmpty() + val defaultList = parameterDescriptorsWithDefaultValue.filter { it !in allValueArguments }.map { "${it.asString()} = ..." } + val argumentList = allValueArguments.entries + .map { (name, value) -> + "${name.asString()} = ${if (name !in parameterDescriptorsWithDefaultValue) renderConstant(value) else "..."}" + } + return (defaultList + argumentList).sorted() + } + + private fun renderConstant(value: ConstantValue<*>): String { + return when (value) { + is ArrayValue -> value.value.joinToString(", ", "{", "}") { renderConstant(it) } + is AnnotationValue -> renderAnnotation(value.value).removePrefix("@") + is KClassValue -> when (val classValue = value.value) { + is KClassValue.Value.LocalClass -> "${classValue.type}::class" + is KClassValue.Value.NormalClass -> { + var type = classValue.classId.asSingleFqName().asString() + repeat(classValue.arrayDimensions) { type = "kotlin.Array<$type>" } + "$type::class" + } + } + else -> value.toString() + } + } + + private fun renderVisibility(visibility: DescriptorVisibility, builder: StringBuilder): Boolean { + @Suppress("NAME_SHADOWING") + var visibility = visibility + if (DescriptorRendererModifier.VISIBILITY !in modifiers) return false + if (normalizedVisibilities) { + visibility = visibility.normalize() + } + if (!renderDefaultVisibility && visibility == DescriptorVisibilities.DEFAULT_VISIBILITY) return false + builder.append(renderKeyword(visibility.internalDisplayName)).append(" ") + return true + } + + private fun renderModality(modality: Modality, builder: StringBuilder, defaultModality: Modality) { + if (!renderDefaultModality && modality == defaultModality) return + renderModifier(builder, DescriptorRendererModifier.MODALITY in modifiers, modality.name.toLowerCase()) + } + + private fun MemberDescriptor.implicitModalityWithoutExtensions(): Modality { + if (this is ClassDescriptor) { + return if (kind == ClassKind.INTERFACE) Modality.ABSTRACT else Modality.FINAL + } + val containingClassDescriptor = containingDeclaration as? ClassDescriptor ?: return Modality.FINAL + if (this !is CallableMemberDescriptor) return Modality.FINAL + if (this.overriddenDescriptors.isNotEmpty()) { + if (containingClassDescriptor.modality != Modality.FINAL) return Modality.OPEN + } + return if (containingClassDescriptor.kind == ClassKind.INTERFACE && this.visibility != DescriptorVisibilities.PRIVATE) { + if (this.modality == Modality.ABSTRACT) Modality.ABSTRACT else Modality.OPEN + } else + Modality.FINAL + } + + private fun renderModalityForCallable(callable: CallableMemberDescriptor, builder: StringBuilder) { + if (!DescriptorUtils.isTopLevelDeclaration(callable) || callable.modality != Modality.FINAL) { + if (overrideRenderingPolicy == OverrideRenderingPolicy.RENDER_OVERRIDE && callable.modality == Modality.OPEN && + overridesSomething(callable) + ) { + return + } + renderModality(callable.modality, builder, callable.implicitModalityWithoutExtensions()) + } + } + + private fun renderOverride(callableMember: CallableMemberDescriptor, builder: StringBuilder) { + if (DescriptorRendererModifier.OVERRIDE !in modifiers) return + if (overridesSomething(callableMember)) { + if (overrideRenderingPolicy != OverrideRenderingPolicy.RENDER_OPEN) { + renderModifier(builder, true, "override") + if (verbose) { + builder.append("/*").append(callableMember.overriddenDescriptors.size).append("*/ ") + } + } + } + } + + private fun renderMemberKind(callableMember: CallableMemberDescriptor, builder: StringBuilder) { + if (DescriptorRendererModifier.MEMBER_KIND !in modifiers) return + if (verbose && callableMember.kind != CallableMemberDescriptor.Kind.DECLARATION) { + builder.append("/*").append(callableMember.kind.name.toLowerCase()).append("*/ ") + } + } + + private fun renderModifier(builder: StringBuilder, value: Boolean, modifier: String) { + if (value) { + builder.append(renderKeyword(modifier)) + builder.append(" ") + } + } + + private fun renderMemberModifiers(descriptor: MemberDescriptor, builder: StringBuilder) { + renderModifier(builder, descriptor.isExternal, "external") + renderModifier(builder, DescriptorRendererModifier.EXPECT in modifiers && descriptor.isExpect, "expect") + renderModifier(builder, DescriptorRendererModifier.ACTUAL in modifiers && descriptor.isActual, "actual") + } + + private fun renderAdditionalModifiers(functionDescriptor: FunctionDescriptor, builder: StringBuilder) { + val isOperator = + functionDescriptor.isOperator && (functionDescriptor.overriddenDescriptors.none { it.isOperator } || alwaysRenderModifiers) + val isInfix = + functionDescriptor.isInfix && (functionDescriptor.overriddenDescriptors.none { it.isInfix } || alwaysRenderModifiers) + + renderModifier(builder, functionDescriptor.isTailrec, "tailrec") + renderSuspendModifier(functionDescriptor, builder) + renderModifier(builder, functionDescriptor.isInline, "inline") + renderModifier(builder, isInfix, "infix") + renderModifier(builder, isOperator, "operator") + } + + private fun renderSuspendModifier(functionDescriptor: FunctionDescriptor, builder: StringBuilder) { + renderModifier(builder, functionDescriptor.isSuspend, "suspend") + } + + override fun render(declarationDescriptor: DeclarationDescriptor): String { + return buildString { + declarationDescriptor.accept(RenderDeclarationDescriptorVisitor(), this) + + if (withDefinedIn) { + appendDefinedIn(declarationDescriptor) + } + } + } + + + /* TYPE PARAMETERS */ + private fun renderTypeParameter(typeParameter: TypeParameterDescriptor, builder: StringBuilder, topLevel: Boolean) { + if (topLevel) { + builder.append(lt()) + } + + if (verbose) { + builder.append("/*").append(typeParameter.index).append("*/ ") + } + + renderModifier(builder, typeParameter.isReified, "reified") + val variance = typeParameter.variance.label + renderModifier(builder, variance.isNotEmpty(), variance) + + builder.renderAnnotations(typeParameter) + + renderName(typeParameter, builder, topLevel) + val upperBoundsCount = typeParameter.upperBounds.size + if ((upperBoundsCount > 1 && !topLevel) || upperBoundsCount == 1) { + val upperBound = typeParameter.upperBounds.iterator().next() + if (!KotlinBuiltIns.isDefaultBound(upperBound)) { + builder.append(" : ").append(renderType(upperBound)) + } + } else if (topLevel) { + var first = true + for (upperBound in typeParameter.upperBounds) { + if (KotlinBuiltIns.isDefaultBound(upperBound)) { + continue + } + if (first) { + builder.append(" : ") + } else { + builder.append(" & ") + } + builder.append(renderType(upperBound)) + first = false + } + } else { + // rendered with "where" + } + + if (topLevel) { + builder.append(gt()) + } + } + + private fun renderTypeParameters(typeParameters: List, builder: StringBuilder, withSpace: Boolean) { + if (withoutTypeParameters) return + + if (typeParameters.isNotEmpty()) { + builder.append(lt()) + renderTypeParameterList(builder, typeParameters) + builder.append(gt()) + if (withSpace) { + builder.append(" ") + } + } + } + + private fun renderTypeParameterList(builder: StringBuilder, typeParameters: List) { + val iterator = typeParameters.iterator() + while (iterator.hasNext()) { + val typeParameterDescriptor = iterator.next() + renderTypeParameter(typeParameterDescriptor, builder, false) + if (iterator.hasNext()) { + builder.append(", ") + } + } + } + + /* FUNCTIONS */ + private fun renderFunction(function: FunctionDescriptor, builder: StringBuilder) { + if (!startFromName) { + if (!startFromDeclarationKeyword) { + builder.renderAnnotations(function) + renderVisibility(function.visibility, builder) + renderModalityForCallable(function, builder) + + if (includeAdditionalModifiers) { + renderMemberModifiers(function, builder) + } + + renderOverride(function, builder) + + if (includeAdditionalModifiers) { + renderAdditionalModifiers(function, builder) + } else { + renderSuspendModifier(function, builder) + } + + renderMemberKind(function, builder) + + if (verbose) { + if (function.isHiddenToOvercomeSignatureClash) { + builder.append("/*isHiddenToOvercomeSignatureClash*/ ") + } + + if (function.isHiddenForResolutionEverywhereBesideSupercalls) { + builder.append("/*isHiddenForResolutionEverywhereBesideSupercalls*/ ") + } + } + } + + builder.append(renderKeyword("fun")).append(" ") + renderTypeParameters(function.typeParameters, builder, true) + renderReceiver(function, builder) + } + + renderName(function, builder, true) + + renderValueParameters(function.valueParameters, function.hasSynthesizedParameterNames(), builder) + + renderReceiverAfterName(function, builder) + + val returnType = function.returnType + if (!withoutReturnType && (unitReturnType || (returnType == null || !KotlinBuiltIns.isUnit(returnType)))) { + builder.append(": ").append(if (returnType == null) "[NULL]" else renderType(returnType)) + } + + renderWhereSuffix(function.typeParameters, builder) + } + + private fun renderReceiverAfterName(callableDescriptor: CallableDescriptor, builder: StringBuilder) { + if (!receiverAfterName) return + + val receiver = callableDescriptor.extensionReceiverParameter + if (receiver != null) { + builder.append(" on ").append(renderType(receiver.type)) + } + } + + private fun renderReceiver(callableDescriptor: CallableDescriptor, builder: StringBuilder) { + val receiver = callableDescriptor.extensionReceiverParameter + if (receiver != null) { + builder.renderAnnotations(receiver, AnnotationUseSiteTarget.RECEIVER) + + val type = receiver.type + var result = renderType(type) + if (shouldRenderAsPrettyFunctionType(type) && !TypeUtils.isNullableType(type)) { + result = "($result)" + } + builder.append(result).append(".") + } + } + + private fun renderConstructor(constructor: ConstructorDescriptor, builder: StringBuilder) { + builder.renderAnnotations(constructor) + val visibilityRendered = (options.renderDefaultVisibility || constructor.constructedClass.modality != Modality.SEALED) + && renderVisibility(constructor.visibility, builder) + renderMemberKind(constructor, builder) + + val constructorKeywordRendered = renderConstructorKeyword || !constructor.isPrimary || visibilityRendered + if (constructorKeywordRendered) { + builder.append(renderKeyword("constructor")) + } + val classDescriptor = constructor.containingDeclaration + if (secondaryConstructorsAsPrimary) { + if (constructorKeywordRendered) { + builder.append(" ") + } + renderName(classDescriptor, builder, true) + renderTypeParameters(constructor.typeParameters, builder, false) + } + + renderValueParameters(constructor.valueParameters, constructor.hasSynthesizedParameterNames(), builder) + + if (renderConstructorDelegation && !constructor.isPrimary && classDescriptor is ClassDescriptor) { + val primaryConstructor = classDescriptor.unsubstitutedPrimaryConstructor + if (primaryConstructor != null) { + val parametersWithoutDefault = primaryConstructor.valueParameters.filter { + !it.declaresDefaultValue() && it.varargElementType == null + } + if (parametersWithoutDefault.isNotEmpty()) { + builder.append(" : ").append(renderKeyword("this")) + builder.append(parametersWithoutDefault.joinToString(prefix = "(", postfix = ")", separator = ", ") { "" }) + } + } + } + + if (secondaryConstructorsAsPrimary) { + renderWhereSuffix(constructor.typeParameters, builder) + } + } + + private fun renderWhereSuffix(typeParameters: List, builder: StringBuilder) { + if (withoutTypeParameters) return + + val upperBoundStrings = ArrayList(0) + + for (typeParameter in typeParameters) { + typeParameter.upperBounds + .drop(1) // first parameter is rendered by renderTypeParameter + .mapTo(upperBoundStrings) { renderName(typeParameter.name, false) + " : " + renderType(it) } + } + + if (upperBoundStrings.isNotEmpty()) { + builder.append(" ").append(renderKeyword("where")).append(" ") + upperBoundStrings.joinTo(builder, ", ") + } + } + + override fun renderValueParameters(parameters: Collection, synthesizedParameterNames: Boolean) = buildString { + renderValueParameters(parameters, synthesizedParameterNames, this) + } + + private fun renderValueParameters( + parameters: Collection, + synthesizedParameterNames: Boolean, + builder: StringBuilder + ) { + val includeNames = shouldRenderParameterNames(synthesizedParameterNames) + val parameterCount = parameters.size + valueParametersHandler.appendBeforeValueParameters(parameterCount, builder) + for ((index, parameter) in parameters.withIndex()) { + valueParametersHandler.appendBeforeValueParameter(parameter, index, parameterCount, builder) + renderValueParameter(parameter, includeNames, builder, false) + valueParametersHandler.appendAfterValueParameter(parameter, index, parameterCount, builder) + } + valueParametersHandler.appendAfterValueParameters(parameterCount, builder) + } + + private fun shouldRenderParameterNames(synthesizedParameterNames: Boolean): Boolean = when (parameterNameRenderingPolicy) { + ParameterNameRenderingPolicy.ALL -> true + ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED -> !synthesizedParameterNames + ParameterNameRenderingPolicy.NONE -> false + } + + /* VARIABLES */ + private fun renderValueParameter( + valueParameter: ValueParameterDescriptor, + includeName: Boolean, + builder: StringBuilder, + topLevel: Boolean + ) { + if (topLevel) { + builder.append(renderKeyword("value-parameter")).append(" ") + } + + if (verbose) { + builder.append("/*").append(valueParameter.index).append("*/ ") + } + + builder.renderAnnotations(valueParameter) + renderModifier(builder, valueParameter.isCrossinline, "crossinline") + renderModifier(builder, valueParameter.isNoinline, "noinline") + + val isPrimaryConstructor = renderPrimaryConstructorParametersAsProperties && + (valueParameter.containingDeclaration as? ClassConstructorDescriptor)?.isPrimary == true + if (isPrimaryConstructor) { + renderModifier(builder, actualPropertiesInPrimaryConstructor, "actual") + } + + renderVariable(valueParameter, includeName, builder, topLevel, isPrimaryConstructor) + + val withDefaultValue = + defaultParameterValueRenderer != null && + (if (debugMode) valueParameter.declaresDefaultValue() else valueParameter.declaresOrInheritsDefaultValue()) + if (withDefaultValue) { + builder.append(" = ${defaultParameterValueRenderer!!(valueParameter)}") + } + } + + private fun renderValVarPrefix(variable: VariableDescriptor, builder: StringBuilder, isInPrimaryConstructor: Boolean = false) { + if (isInPrimaryConstructor || variable !is ValueParameterDescriptor) { + builder.append(renderKeyword(if (variable.isVar) "var" else "val")).append(" ") + } + } + + private fun renderVariable( + variable: VariableDescriptor, + includeName: Boolean, + builder: StringBuilder, + topLevel: Boolean, + isInPrimaryConstructor: Boolean = false + ) { + val realType = variable.type + + val varargElementType = (variable as? ValueParameterDescriptor)?.varargElementType + val typeToRender = varargElementType ?: realType + renderModifier(builder, varargElementType != null, "vararg") + + if (isInPrimaryConstructor || topLevel && !startFromName) { + renderValVarPrefix(variable, builder, isInPrimaryConstructor) + } + + if (includeName) { + renderName(variable, builder, topLevel) + builder.append(": ") + } + + builder.append(renderType(typeToRender)) + + renderInitializer(variable, builder) + + if (verbose && varargElementType != null) { + builder.append(" /*").append(renderType(realType)).append("*/") + } + } + + private fun renderProperty(property: PropertyDescriptor, builder: StringBuilder) { + if (!startFromName) { + if (!startFromDeclarationKeyword) { + renderPropertyAnnotations(property, builder) + renderVisibility(property.visibility, builder) + renderModifier(builder, DescriptorRendererModifier.CONST in modifiers && property.isConst, "const") + renderMemberModifiers(property, builder) + renderModalityForCallable(property, builder) + renderOverride(property, builder) + renderModifier(builder, DescriptorRendererModifier.LATEINIT in modifiers && property.isLateInit, "lateinit") + renderMemberKind(property, builder) + } + renderValVarPrefix(property, builder) + renderTypeParameters(property.typeParameters, builder, true) + renderReceiver(property, builder) + } + + renderName(property, builder, true) + builder.append(": ").append(renderType(property.type)) + + renderReceiverAfterName(property, builder) + + renderInitializer(property, builder) + + renderWhereSuffix(property.typeParameters, builder) + } + + private fun renderPropertyAnnotations(property: PropertyDescriptor, builder: StringBuilder) { + if (DescriptorRendererModifier.ANNOTATIONS !in modifiers) return + + builder.renderAnnotations(property) + + property.backingField?.let { builder.renderAnnotations(it, AnnotationUseSiteTarget.FIELD) } + property.delegateField?.let { builder.renderAnnotations(it, AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD) } + + if (propertyAccessorRenderingPolicy == PropertyAccessorRenderingPolicy.NONE) { + property.getter?.let { + builder.renderAnnotations(it, AnnotationUseSiteTarget.PROPERTY_GETTER) + } + property.setter?.let { setter -> + setter.let { + builder.renderAnnotations(it, AnnotationUseSiteTarget.PROPERTY_SETTER) + } + setter.valueParameters.single().let { + builder.renderAnnotations(it, AnnotationUseSiteTarget.SETTER_PARAMETER) + } + } + } + } + + private fun renderInitializer(variable: VariableDescriptor, builder: StringBuilder) { + if (includePropertyConstant) { + variable.compileTimeInitializer?.let { constant -> + builder.append(" = ").append(escape(renderConstant(constant))) + } + } + } + + private fun renderTypeAlias(typeAlias: TypeAliasDescriptor, builder: StringBuilder) { + builder.renderAnnotations(typeAlias) + renderVisibility(typeAlias.visibility, builder) + renderMemberModifiers(typeAlias, builder) + builder.append(renderKeyword("typealias")).append(" ") + renderName(typeAlias, builder, true) + + renderTypeParameters(typeAlias.declaredTypeParameters, builder, false) + renderCapturedTypeParametersIfRequired(typeAlias, builder) + + builder.append(" = ").append(renderType(typeAlias.underlyingType)) + } + + private fun renderCapturedTypeParametersIfRequired(classifier: ClassifierDescriptorWithTypeParameters, builder: StringBuilder) { + val typeParameters = classifier.declaredTypeParameters + val typeConstructorParameters = classifier.typeConstructor.parameters + + if (verbose && classifier.isInner && typeConstructorParameters.size > typeParameters.size) { + builder.append(" /*captured type parameters: ") + renderTypeParameterList(builder, typeConstructorParameters.subList(typeParameters.size, typeConstructorParameters.size)) + builder.append("*/") + } + } + + /* CLASSES */ + private fun renderClass(klass: ClassDescriptor, builder: StringBuilder) { + val isEnumEntry = klass.kind == ClassKind.ENUM_ENTRY + + if (!startFromName) { + builder.renderAnnotations(klass) + if (!isEnumEntry) { + renderVisibility(klass.visibility, builder) + } + if (!(klass.kind == ClassKind.INTERFACE && klass.modality == Modality.ABSTRACT || + klass.kind.isSingleton && klass.modality == Modality.FINAL) + ) { + renderModality(klass.modality, builder, klass.implicitModalityWithoutExtensions()) + } + renderMemberModifiers(klass, builder) + renderModifier(builder, DescriptorRendererModifier.INNER in modifiers && klass.isInner, "inner") + renderModifier(builder, DescriptorRendererModifier.DATA in modifiers && klass.isData, "data") + renderModifier(builder, DescriptorRendererModifier.INLINE in modifiers && klass.isInline, "inline") + renderModifier(builder, DescriptorRendererModifier.FUN in modifiers && klass.isFun, "fun") + renderClassKindPrefix(klass, builder) + } + + if (!isCompanionObject(klass)) { + if (!startFromName) renderSpaceIfNeeded(builder) + renderName(klass, builder, true) + } else { + renderCompanionObjectName(klass, builder) + } + + if (isEnumEntry) return + + val typeParameters = klass.declaredTypeParameters + renderTypeParameters(typeParameters, builder, false) + renderCapturedTypeParametersIfRequired(klass, builder) + + if (!klass.kind.isSingleton && classWithPrimaryConstructor) { + val primaryConstructor = klass.unsubstitutedPrimaryConstructor + if (primaryConstructor != null) { + builder.append(" ") + builder.renderAnnotations(primaryConstructor) + renderVisibility(primaryConstructor.visibility, builder) + builder.append(renderKeyword("constructor")) + renderValueParameters(primaryConstructor.valueParameters, primaryConstructor.hasSynthesizedParameterNames(), builder) + } + } + + renderSuperTypes(klass, builder) + renderWhereSuffix(typeParameters, builder) + } + + private fun renderSuperTypes(klass: ClassDescriptor, builder: StringBuilder) { + if (withoutSuperTypes) return + + if (KotlinBuiltIns.isNothing(klass.defaultType)) return + + val supertypes = klass.typeConstructor.supertypes + if (supertypes.isEmpty() || supertypes.size == 1 && KotlinBuiltIns.isAnyOrNullableAny(supertypes.iterator().next())) return + + renderSpaceIfNeeded(builder) + builder.append(": ") + supertypes.joinTo(builder, ", ") { renderType(it) } + } + + private fun renderClassKindPrefix(klass: ClassDescriptor, builder: StringBuilder) { + builder.append(renderKeyword(getClassifierKindPrefix(klass))) + } + + + /* OTHER */ + private fun renderPackageView(packageView: PackageViewDescriptor, builder: StringBuilder) { + renderPackageHeader(packageView.fqName, "package", builder) + if (debugMode) { + builder.append(" in context of ") + renderName(packageView.module, builder, false) + } + } + + private fun renderPackageFragment(fragment: PackageFragmentDescriptor, builder: StringBuilder) { + renderPackageHeader(fragment.fqName, "package-fragment", builder) + if (debugMode) { + builder.append(" in ") + renderName(fragment.containingDeclaration, builder, false) + } + } + + private fun renderPackageHeader(fqName: FqName, fragmentOrView: String, builder: StringBuilder) { + builder.append(renderKeyword(fragmentOrView)) + val fqNameString = renderFqName(fqName.toUnsafe()) + if (fqNameString.isNotEmpty()) { + builder.append(" ") + builder.append(fqNameString) + } + } + + private fun renderAccessorModifiers(descriptor: PropertyAccessorDescriptor, builder: StringBuilder) { + renderMemberModifiers(descriptor, builder) + } + + /* STUPID DISPATCH-ONLY VISITOR */ + private inner class RenderDeclarationDescriptorVisitor : DeclarationDescriptorVisitor { + override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, builder: StringBuilder) { + renderValueParameter(descriptor, true, builder, true) + } + + override fun visitVariableDescriptor(descriptor: VariableDescriptor, builder: StringBuilder) { + renderVariable(descriptor, true, builder, true) + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, builder: StringBuilder) { + renderProperty(descriptor, builder) + } + + override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, builder: StringBuilder) { + visitPropertyAccessorDescriptor(descriptor, builder, "getter") + } + + override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, builder: StringBuilder) { + visitPropertyAccessorDescriptor(descriptor, builder, "setter") + } + + private fun visitPropertyAccessorDescriptor(descriptor: PropertyAccessorDescriptor, builder: StringBuilder, kind: String) { + when (propertyAccessorRenderingPolicy) { + PropertyAccessorRenderingPolicy.PRETTY -> { + renderAccessorModifiers(descriptor, builder) + builder.append("$kind for ") + renderProperty(descriptor.correspondingProperty, builder) + } + PropertyAccessorRenderingPolicy.DEBUG -> { + visitFunctionDescriptor(descriptor, builder) + } + PropertyAccessorRenderingPolicy.NONE -> { + } + } + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, builder: StringBuilder) { + renderFunction(descriptor, builder) + } + + override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, builder: StringBuilder) { + builder.append(descriptor.name) // renders + } + + override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, builder: StringBuilder) { + renderConstructor(constructorDescriptor, builder) + } + + override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, builder: StringBuilder) { + renderTypeParameter(descriptor, builder, true) + } + + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, builder: StringBuilder) { + renderPackageFragment(descriptor, builder) + } + + override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, builder: StringBuilder) { + renderPackageView(descriptor, builder) + } + + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, builder: StringBuilder) { + renderName(descriptor, builder, true) + } + + override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, builder: StringBuilder) { + visitClassDescriptor(scriptDescriptor, builder) + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, builder: StringBuilder) { + renderClass(descriptor, builder) + } + + override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, builder: StringBuilder) { + renderTypeAlias(descriptor, builder) + } + } + + private fun renderSpaceIfNeeded(builder: StringBuilder) { + val length = builder.length + if (length == 0 || builder[length - 1] != ' ') { + builder.append(' ') + } + } + + private fun replacePrefixes( + lowerRendered: String, + lowerPrefix: String, + upperRendered: String, + upperPrefix: String, + foldedPrefix: String + ): String? { + if (lowerRendered.startsWith(lowerPrefix) && upperRendered.startsWith(upperPrefix)) { + val lowerWithoutPrefix = lowerRendered.substring(lowerPrefix.length) + val upperWithoutPrefix = upperRendered.substring(upperPrefix.length) + val flexibleCollectionName = foldedPrefix + lowerWithoutPrefix + + if (lowerWithoutPrefix == upperWithoutPrefix) return flexibleCollectionName + + if (differsOnlyInNullability(lowerWithoutPrefix, upperWithoutPrefix)) { + return "$flexibleCollectionName!" + } + } + return null + } + + private fun differsOnlyInNullability(lower: String, upper: String) = + lower == upper.replace("?", "") || upper.endsWith("?") && ("$lower?") == upper || "($lower)?" == upper + + private fun overridesSomething(callable: CallableMemberDescriptor) = !callable.overriddenDescriptors.isEmpty() +} diff --git a/src/subprojects/packcc/build/clang/Makefile b/src/subprojects/packcc/build/clang/Makefile new file mode 100644 index 00000000..5b4448b2 --- /dev/null +++ b/src/subprojects/packcc/build/clang/Makefile @@ -0,0 +1,58 @@ +CC=clang +CFLAGS_D=-std=gnu89 -fsigned-char -Wall -Wextra -Wno-unused-parameter -Wno-overlength-strings -pedantic -O0 -g2 +CFLAGS_R=-std=gnu89 -fsigned-char -Wall -Wextra -Wno-unused-parameter -Wno-overlength-strings -pedantic -O2 -DNDEBUG +LDFLAGS_D= +LDFLAGS_R= + +ROOTDIR=../.. +SRCDIR=$(ROOTDIR)/src +TESTDIR=$(ROOTDIR)/tests +EXDIR=$(ROOTDIR)/examples +TMPDIR_D=debug/tmp +TMPDIR_R=release/tmp +BINDIR_D=debug/bin +BINDIR_R=release/bin + +EXAMPLES:=$(patsubst $(EXDIR)/%.peg,examples/%,$(wildcard $(EXDIR)/*.peg)) + +BINS= \ + $(BINDIR_D)/packcc \ + $(BINDIR_R)/packcc \ + $(patsubst %,$(BINDIR_D)/%,$(EXAMPLES)) \ + $(patsubst %,$(BINDIR_R)/%,$(EXAMPLES)) +SRCS= \ + $(patsubst %,$(TMPDIR_D)/%.c,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_D)/%.h,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_R)/%.c,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_R)/%.h,$(EXAMPLES)) + +.PHONY: all check clean + +.SECONDARY: $(SRCS) + +all: $(BINS) + +$(BINDIR_D)/packcc: $(SRCDIR)/packcc.c + mkdir -p $(dir $@) && $(CC) $(CFLAGS_D) -o $@ $< $(LDFLAGS_D) + +$(BINDIR_R)/packcc: $(SRCDIR)/packcc.c + mkdir -p $(dir $@) && $(CC) $(CFLAGS_R) -o $@ $< $(LDFLAGS_R) + +$(BINDIR_D)/examples/%: $(TMPDIR_D)/examples/%.c $(TMPDIR_D)/examples/%.h + mkdir -p $(dir $@) && $(CC) $(CFLAGS_D) -I. -o $@ $< $(LDFLAGS_D) + +$(BINDIR_R)/examples/%: $(TMPDIR_R)/examples/%.c $(TMPDIR_R)/examples/%.h + mkdir -p $(dir $@) && $(CC) $(CFLAGS_R) -I. -o $@ $< $(LDFLAGS_R) + +$(TMPDIR_D)/examples/%.c $(TMPDIR_D)/examples/%.h: $(EXDIR)/%.peg $(BINDIR_D)/packcc + mkdir -p $(dir $@) && $(BINDIR_D)/packcc -I$(ROOTDIR)/import -o $(basename $@) $< + +$(TMPDIR_R)/examples/%.c $(TMPDIR_R)/examples/%.h: $(EXDIR)/%.peg $(BINDIR_R)/packcc + mkdir -p $(dir $@) && $(BINDIR_R)/packcc -I$(ROOTDIR)/import -o $(basename $@) $< + +check: $(BINDIR_D)/packcc $(BINDIR_R)/packcc + @echo "== Debug Version ==" && PACKCC=$$PWD/$(BINDIR_D)/packcc CC="$(CC) $(CFLAGS_D)" $(TESTDIR)/test.sh + @echo "== Release Version ==" && PACKCC=$$PWD/$(BINDIR_R)/packcc CC="$(CC) $(CFLAGS_R)" $(TESTDIR)/test.sh + +clean: + rm -f $(BINS) $(SRCS) diff --git a/src/subprojects/packcc/build/gcc/Makefile b/src/subprojects/packcc/build/gcc/Makefile new file mode 100644 index 00000000..e80c6859 --- /dev/null +++ b/src/subprojects/packcc/build/gcc/Makefile @@ -0,0 +1,58 @@ +CC=gcc +CFLAGS_D=-std=gnu89 -fsigned-char -Wall -Wextra -Wno-unused-parameter -Wno-overlength-strings -pedantic -O0 -g2 +CFLAGS_R=-std=gnu89 -fsigned-char -Wall -Wextra -Wno-unused-parameter -Wno-overlength-strings -pedantic -O2 -DNDEBUG +LDFLAGS_D= +LDFLAGS_R= + +ROOTDIR=../.. +SRCDIR=$(ROOTDIR)/src +TESTDIR=$(ROOTDIR)/tests +EXDIR=$(ROOTDIR)/examples +TMPDIR_D=debug/tmp +TMPDIR_R=release/tmp +BINDIR_D=debug/bin +BINDIR_R=release/bin + +EXAMPLES:=$(patsubst $(EXDIR)/%.peg,examples/%,$(wildcard $(EXDIR)/*.peg)) + +BINS= \ + $(BINDIR_D)/packcc \ + $(BINDIR_R)/packcc \ + $(patsubst %,$(BINDIR_D)/%,$(EXAMPLES)) \ + $(patsubst %,$(BINDIR_R)/%,$(EXAMPLES)) +SRCS= \ + $(patsubst %,$(TMPDIR_D)/%.c,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_D)/%.h,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_R)/%.c,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_R)/%.h,$(EXAMPLES)) + +.PHONY: all check clean + +.SECONDARY: $(SRCS) + +all: $(BINS) + +$(BINDIR_D)/packcc: $(SRCDIR)/packcc.c + mkdir -p $(dir $@) && $(CC) $(CFLAGS_D) -o $@ $< $(LDFLAGS_D) + +$(BINDIR_R)/packcc: $(SRCDIR)/packcc.c + mkdir -p $(dir $@) && $(CC) $(CFLAGS_R) -o $@ $< $(LDFLAGS_R) + +$(BINDIR_D)/examples/%: $(TMPDIR_D)/examples/%.c $(TMPDIR_D)/examples/%.h + mkdir -p $(dir $@) && $(CC) $(CFLAGS_D) -I. -o $@ $< $(LDFLAGS_D) + +$(BINDIR_R)/examples/%: $(TMPDIR_R)/examples/%.c $(TMPDIR_R)/examples/%.h + mkdir -p $(dir $@) && $(CC) $(CFLAGS_R) -I. -o $@ $< $(LDFLAGS_R) + +$(TMPDIR_D)/examples/%.c $(TMPDIR_D)/examples/%.h: $(EXDIR)/%.peg $(BINDIR_D)/packcc + mkdir -p $(dir $@) && $(BINDIR_D)/packcc -I$(ROOTDIR)/import -o $(basename $@) $< + +$(TMPDIR_R)/examples/%.c $(TMPDIR_R)/examples/%.h: $(EXDIR)/%.peg $(BINDIR_R)/packcc + mkdir -p $(dir $@) && $(BINDIR_R)/packcc -I$(ROOTDIR)/import -o $(basename $@) $< + +check: $(BINDIR_D)/packcc $(BINDIR_R)/packcc + @echo "== Debug Version ==" && PACKCC=$$PWD/$(BINDIR_D)/packcc CC="$(CC) $(CFLAGS_D)" $(TESTDIR)/test.sh + @echo "== Release Version ==" && PACKCC=$$PWD/$(BINDIR_R)/packcc CC="$(CC) $(CFLAGS_R)" $(TESTDIR)/test.sh + +clean: + rm -f $(BINS) $(SRCS) diff --git a/src/subprojects/packcc/build/mingw-clang/Makefile b/src/subprojects/packcc/build/mingw-clang/Makefile new file mode 100644 index 00000000..31a721d6 --- /dev/null +++ b/src/subprojects/packcc/build/mingw-clang/Makefile @@ -0,0 +1,58 @@ +CC=clang +CFLAGS_D=-std=gnu89 -Wall -Wextra -Wno-unused-parameter -Wno-overlength-strings -Wno-long-long -Wno-format -pedantic -O0 -g2 +CFLAGS_R=-std=gnu89 -Wall -Wextra -Wno-unused-parameter -Wno-overlength-strings -Wno-long-long -Wno-format -pedantic -O2 -DNDEBUG +LDFLAGS_D= +LDFLAGS_R= + +ROOTDIR=../.. +SRCDIR=$(ROOTDIR)/src +TESTDIR=$(ROOTDIR)/tests +EXDIR=$(ROOTDIR)/examples +TMPDIR_D=debug/tmp +TMPDIR_R=release/tmp +BINDIR_D=debug/bin +BINDIR_R=release/bin + +EXAMPLES:=$(patsubst $(EXDIR)/%.peg,examples/%,$(wildcard $(EXDIR)/*.peg)) + +BINS= \ + $(BINDIR_D)/packcc \ + $(BINDIR_R)/packcc \ + $(patsubst %,$(BINDIR_D)/%,$(EXAMPLES)) \ + $(patsubst %,$(BINDIR_R)/%,$(EXAMPLES)) +SRCS= \ + $(patsubst %,$(TMPDIR_D)/%.c,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_D)/%.h,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_R)/%.c,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_R)/%.h,$(EXAMPLES)) + +.PHONY: all check clean + +.SECONDARY: $(SRCS) + +all: $(BINS) + +$(BINDIR_D)/packcc: $(SRCDIR)/packcc.c + mkdir -p $(dir $@) && $(CC) $(CFLAGS_D) -o $@ $< $(LDFLAGS_D) + +$(BINDIR_R)/packcc: $(SRCDIR)/packcc.c + mkdir -p $(dir $@) && $(CC) $(CFLAGS_R) -o $@ $< $(LDFLAGS_R) + +$(BINDIR_D)/examples/%: $(TMPDIR_D)/examples/%.c $(TMPDIR_D)/examples/%.h + mkdir -p $(dir $@) && $(CC) $(CFLAGS_D) -I. -o $@ $< $(LDFLAGS_D) + +$(BINDIR_R)/examples/%: $(TMPDIR_R)/examples/%.c $(TMPDIR_R)/examples/%.h + mkdir -p $(dir $@) && $(CC) $(CFLAGS_R) -I. -o $@ $< $(LDFLAGS_R) + +$(TMPDIR_D)/examples/%.c $(TMPDIR_D)/examples/%.h: $(EXDIR)/%.peg $(BINDIR_D)/packcc + mkdir -p $(dir $@) && $(BINDIR_D)/packcc -I$(ROOTDIR)/import -o $(basename $@) $< + +$(TMPDIR_R)/examples/%.c $(TMPDIR_R)/examples/%.h: $(EXDIR)/%.peg $(BINDIR_R)/packcc + mkdir -p $(dir $@) && $(BINDIR_R)/packcc -I$(ROOTDIR)/import -o $(basename $@) $< + +check: $(BINDIR_D)/packcc $(BINDIR_R)/packcc + @echo "== Debug Version ==" && PACKCC=$$PWD/$(BINDIR_D)/packcc CC="$(CC) $(CFLAGS_D)" $(TESTDIR)/test.sh + @echo "== Release Version ==" && PACKCC=$$PWD/$(BINDIR_R)/packcc CC="$(CC) $(CFLAGS_R)" $(TESTDIR)/test.sh + +clean: + rm -f $(BINS) $(SRCS) diff --git a/src/subprojects/packcc/build/mingw-gcc/Makefile b/src/subprojects/packcc/build/mingw-gcc/Makefile new file mode 100644 index 00000000..bdbba39f --- /dev/null +++ b/src/subprojects/packcc/build/mingw-gcc/Makefile @@ -0,0 +1,58 @@ +CC=gcc +CFLAGS_D=-std=gnu89 -Wall -Wextra -Wno-unused-parameter -Wno-overlength-strings -Wno-long-long -Wno-format -pedantic -O0 -g2 +CFLAGS_R=-std=gnu89 -Wall -Wextra -Wno-unused-parameter -Wno-overlength-strings -Wno-long-long -Wno-format -pedantic -O2 -DNDEBUG +LDFLAGS_D= +LDFLAGS_R= + +ROOTDIR=../.. +SRCDIR=$(ROOTDIR)/src +TESTDIR=$(ROOTDIR)/tests +EXDIR=$(ROOTDIR)/examples +TMPDIR_D=debug/tmp +TMPDIR_R=release/tmp +BINDIR_D=debug/bin +BINDIR_R=release/bin + +EXAMPLES:=$(patsubst $(EXDIR)/%.peg,examples/%,$(wildcard $(EXDIR)/*.peg)) + +BINS= \ + $(BINDIR_D)/packcc \ + $(BINDIR_R)/packcc \ + $(patsubst %,$(BINDIR_D)/%,$(EXAMPLES)) \ + $(patsubst %,$(BINDIR_R)/%,$(EXAMPLES)) +SRCS= \ + $(patsubst %,$(TMPDIR_D)/%.c,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_D)/%.h,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_R)/%.c,$(EXAMPLES)) \ + $(patsubst %,$(TMPDIR_R)/%.h,$(EXAMPLES)) + +.PHONY: all check clean + +.SECONDARY: $(SRCS) + +all: $(BINS) + +$(BINDIR_D)/packcc: $(SRCDIR)/packcc.c + mkdir -p $(dir $@) && $(CC) $(CFLAGS_D) -o $@ $< $(LDFLAGS_D) + +$(BINDIR_R)/packcc: $(SRCDIR)/packcc.c + mkdir -p $(dir $@) && $(CC) $(CFLAGS_R) -o $@ $< $(LDFLAGS_R) + +$(BINDIR_D)/examples/%: $(TMPDIR_D)/examples/%.c $(TMPDIR_D)/examples/%.h + mkdir -p $(dir $@) && $(CC) $(CFLAGS_D) -I. -o $@ $< $(LDFLAGS_D) + +$(BINDIR_R)/examples/%: $(TMPDIR_R)/examples/%.c $(TMPDIR_R)/examples/%.h + mkdir -p $(dir $@) && $(CC) $(CFLAGS_R) -I. -o $@ $< $(LDFLAGS_R) + +$(TMPDIR_D)/examples/%.c $(TMPDIR_D)/examples/%.h: $(EXDIR)/%.peg $(BINDIR_D)/packcc + mkdir -p $(dir $@) && $(BINDIR_D)/packcc -I$(ROOTDIR)/import -o $(basename $@) $< + +$(TMPDIR_R)/examples/%.c $(TMPDIR_R)/examples/%.h: $(EXDIR)/%.peg $(BINDIR_R)/packcc + mkdir -p $(dir $@) && $(BINDIR_R)/packcc -I$(ROOTDIR)/import -o $(basename $@) $< + +check: $(BINDIR_D)/packcc $(BINDIR_R)/packcc + @echo "== Debug Version ==" && PACKCC=$$PWD/$(BINDIR_D)/packcc CC="$(CC) $(CFLAGS_D)" $(TESTDIR)/test.sh + @echo "== Release Version ==" && PACKCC=$$PWD/$(BINDIR_R)/packcc CC="$(CC) $(CFLAGS_R)" $(TESTDIR)/test.sh + +clean: + rm -f $(BINS) $(SRCS) diff --git a/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj b/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj new file mode 100644 index 00000000..97402246 --- /dev/null +++ b/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj @@ -0,0 +1,206 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + Document + $(ProjectDir)tmp\$(PlatformTarget)\$(Configuration)\%(Filename).c;%(Outputs) + false + ClCompile + true + $(ProjectDir)tmp\$(PlatformTarget)\$(Configuration)\%(Filename).c;%(Outputs) + false + ClCompile + true + $(ProjectDir)tmp\$(PlatformTarget)\$(Configuration)\%(Filename).c;%(Outputs) + false + ClCompile + true + $(ProjectDir)tmp\$(PlatformTarget)\$(Configuration)\%(Filename).c;%(Outputs) + false + ClCompile + true + false + false + false + false + false + false + false + false + $(SolutionDir)$(PlatformTarget)\$(Configuration)\packcc -o tmp\$(PlatformTarget)\$(Configuration)\%(Filename) %(FullPath) + $(SolutionDir)$(PlatformTarget)\$(Configuration)\packcc -o tmp\$(PlatformTarget)\$(Configuration)\%(Filename) %(FullPath) + $(SolutionDir)$(PlatformTarget)\$(Configuration)\packcc -o tmp\$(PlatformTarget)\$(Configuration)\%(Filename) %(FullPath) + $(SolutionDir)$(PlatformTarget)\$(Configuration)\packcc -o tmp\$(PlatformTarget)\$(Configuration)\%(Filename) %(FullPath) + + + + 16.0 + {5EB5881F-0182-4E32-A3E8-6940E5016770} + Win32Proj + calc + 10.0 + calc + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(ProjectDir)$(PlatformTarget)\$(Configuration)\ + $(PlatformTarget)\$(Configuration)\ + $(ProjectName) + .\;$(IncludePath) + + + true + $(ProjectDir)$(PlatformTarget)\$(Configuration)\ + $(PlatformTarget)\$(Configuration)\ + $(ProjectName) + .\;$(IncludePath) + + + false + $(ProjectDir)$(PlatformTarget)\$(Configuration)\ + $(PlatformTarget)\$(Configuration)\ + $(ProjectName) + .\;$(IncludePath) + + + false + $(ProjectDir)$(PlatformTarget)\$(Configuration)\ + $(PlatformTarget)\$(Configuration)\ + $(ProjectName) + .\;$(IncludePath) + + + + Level4 + 4090;4100;4456;26450;26451 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level4 + 4090;4100;4456;26450;26451 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + + + Level4 + 4090;4100;4456;26450;26451 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level4 + 4090;4100;4456;26450;26451 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + \ No newline at end of file diff --git a/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj.filters b/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj.filters new file mode 100644 index 00000000..8c568386 --- /dev/null +++ b/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj.user b/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj.user new file mode 100644 index 00000000..0f14913f --- /dev/null +++ b/src/subprojects/packcc/build/msvc/examples/calc/calc.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/subprojects/packcc/build/msvc/msvc.sln b/src/subprojects/packcc/build/msvc/msvc.sln new file mode 100644 index 00000000..97f234da --- /dev/null +++ b/src/subprojects/packcc/build/msvc/msvc.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29209.62 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "packcc", "packcc.vcxproj", "{9A1A5538-7127-4B2F-9C82-3282A69F3C9C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "calc", "examples\calc\calc.vcxproj", "{5EB5881F-0182-4E32-A3E8-6940E5016770}" + ProjectSection(ProjectDependencies) = postProject + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C} = {9A1A5538-7127-4B2F-9C82-3282A69F3C9C} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{16C15CF5-EA71-4DEB-A758-CC52E0CA2558}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C}.Debug|x64.ActiveCfg = Debug|x64 + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C}.Debug|x64.Build.0 = Debug|x64 + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C}.Debug|x86.ActiveCfg = Debug|Win32 + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C}.Debug|x86.Build.0 = Debug|Win32 + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C}.Release|x64.ActiveCfg = Release|x64 + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C}.Release|x64.Build.0 = Release|x64 + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C}.Release|x86.ActiveCfg = Release|Win32 + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C}.Release|x86.Build.0 = Release|Win32 + {5EB5881F-0182-4E32-A3E8-6940E5016770}.Debug|x64.ActiveCfg = Debug|x64 + {5EB5881F-0182-4E32-A3E8-6940E5016770}.Debug|x64.Build.0 = Debug|x64 + {5EB5881F-0182-4E32-A3E8-6940E5016770}.Debug|x86.ActiveCfg = Debug|Win32 + {5EB5881F-0182-4E32-A3E8-6940E5016770}.Debug|x86.Build.0 = Debug|Win32 + {5EB5881F-0182-4E32-A3E8-6940E5016770}.Release|x64.ActiveCfg = Release|x64 + {5EB5881F-0182-4E32-A3E8-6940E5016770}.Release|x64.Build.0 = Release|x64 + {5EB5881F-0182-4E32-A3E8-6940E5016770}.Release|x86.ActiveCfg = Release|Win32 + {5EB5881F-0182-4E32-A3E8-6940E5016770}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5EB5881F-0182-4E32-A3E8-6940E5016770} = {16C15CF5-EA71-4DEB-A758-CC52E0CA2558} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BD6C24C6-47A2-40C5-87E8-F72C92F9D5FF} + EndGlobalSection +EndGlobal diff --git a/src/subprojects/packcc/build/msvc/packcc.vcxproj b/src/subprojects/packcc/build/msvc/packcc.vcxproj new file mode 100644 index 00000000..da40f8b1 --- /dev/null +++ b/src/subprojects/packcc/build/msvc/packcc.vcxproj @@ -0,0 +1,171 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {9A1A5538-7127-4B2F-9C82-3282A69F3C9C} + Win32Proj + packcc + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(PlatformTarget)\$(Configuration)\ + $(PlatformTarget)\$(Configuration)\ + + + true + $(SolutionDir)$(PlatformTarget)\$(Configuration)\ + $(PlatformTarget)\$(Configuration)\ + + + false + $(SolutionDir)$(PlatformTarget)\$(Configuration)\ + $(PlatformTarget)\$(Configuration)\ + + + false + $(SolutionDir)$(PlatformTarget)\$(Configuration)\ + $(PlatformTarget)\$(Configuration)\ + + + + Level4 + 4090;4100;4456;26450;26451 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + true + false + + + Console + true + + + + + Level4 + 4090;4100;4456;26450;26451 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + true + false + + + Console + true + + + + + Level4 + 4090;4100;4456;26450;26451 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + true + false + + + Console + true + true + true + + + + + Level4 + 4090;4100;4456;26450;26451 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + true + false + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/src/subprojects/packcc/build/msvc/packcc.vcxproj.filters b/src/subprojects/packcc/build/msvc/packcc.vcxproj.filters new file mode 100644 index 00000000..3de6784b --- /dev/null +++ b/src/subprojects/packcc/build/msvc/packcc.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/src/subprojects/packcc/build/msvc/packcc.vcxproj.user b/src/subprojects/packcc/build/msvc/packcc.vcxproj.user new file mode 100644 index 00000000..0f14913f --- /dev/null +++ b/src/subprojects/packcc/build/msvc/packcc.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/subprojects/packcc/examples/README.md b/src/subprojects/packcc/examples/README.md new file mode 100644 index 00000000..ed74d234 --- /dev/null +++ b/src/subprojects/packcc/examples/README.md @@ -0,0 +1,13 @@ +# Examples + +## Overview + +In this directory, examples are stored. + +## Example List + +- [Desktop Calculator](calc.peg) +- [Simple AST builder](ast-calc.peg) +- [AST Builder for Tiny-C](ast-tinyc) + +For details, see PackCC [README.md](../README.md). diff --git a/src/subprojects/packcc/examples/ast-calc.peg b/src/subprojects/packcc/examples/ast-calc.peg new file mode 100644 index 00000000..ba6ab255 --- /dev/null +++ b/src/subprojects/packcc/examples/ast-calc.peg @@ -0,0 +1,122 @@ +# This code is hereby placed in the public domain. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%prefix "calc" + +%value "calc_ast_node_t *" # <-- must be set + +%auxil "calc_ast_manager_t *" # <-- must be set + +%header { +#define CALC_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */ + +typedef struct text_data_tag { /* <-- node custom data type */ + char *text; +} calc_ast_node_custom_data_t; +} + +%source { +#include +#include +} + +statement <- _ e:expression _ EOL { $$ = e; } + / ( !EOL . )* EOL { $$ = NULL; } + +expression <- e:term { $$ = e; } + +term <- l:term _ '+' _ r:factor { $$ = calc_ast_node__create_2(l, r); $$->custom.text = strdup("+"); } + / l:term _ '-' _ r:factor { $$ = calc_ast_node__create_2(l, r); $$->custom.text = strdup("-"); } + / e:factor { $$ = e; } + +factor <- l:factor _ '*' _ r:unary { $$ = calc_ast_node__create_2(l, r); $$->custom.text = strdup("*"); } + / l:factor _ '/' _ r:unary { $$ = calc_ast_node__create_2(l, r); $$->custom.text = strdup("/"); } + / e:unary { $$ = e; } + +unary <- '+' _ e:unary { $$ = calc_ast_node__create_1(e); $$->custom.text = strdup("+"); } + / '-' _ e:unary { $$ = calc_ast_node__create_1(e); $$->custom.text = strdup("-"); } + / e:primary { $$ = e; } + +primary <- < [0-9]+ > { $$ = calc_ast_node__create_0(); $$->custom.text = strdup($1); } + / '(' _ e:expression _ ')' { $$ = e; } + +_ <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' / ';' + +%import "code/pcc_ast.peg" # <-- provides AST build functions + +%% +void calc_ast_node_custom_data__initialize(calc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */ + obj->text = NULL; +} + +void calc_ast_node_custom_data__finalize(calc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */ + free(obj->text); +} + +static void dump_ast(const calc_ast_node_t *obj, int depth) { + if (obj) { + switch (obj->type) { + case CALC_AST_NODE_TYPE_NULLARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "nullary", obj->custom.text); + break; + case CALC_AST_NODE_TYPE_UNARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "unary", obj->custom.text); + dump_ast(obj->data.unary.node, depth + 1); + break; + case CALC_AST_NODE_TYPE_BINARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "binary", obj->custom.text); + dump_ast(obj->data.binary.node[0], depth + 1); + dump_ast(obj->data.binary.node[1], depth + 1); + break; + case CALC_AST_NODE_TYPE_TERNARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "ternary", obj->custom.text); + dump_ast(obj->data.ternary.node[0], depth + 1); + dump_ast(obj->data.ternary.node[1], depth + 1); + dump_ast(obj->data.ternary.node[2], depth + 1); + break; + case CALC_AST_NODE_TYPE_VARIADIC: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "variadic", obj->custom.text); + { + size_t i; + for (i = 0; i < obj->data.variadic.len; i++) { + dump_ast(obj->data.variadic.node[i], depth + 1); + } + } + break; + default: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "(unknown)", obj->custom.text); + break; + } + } + else { + printf("%*s(null)\n", 2 * depth, ""); + } +} + +int main(int argc, char **argv) { + calc_ast_manager_t mgr; + calc_ast_manager__initialize(&mgr); + { + calc_context_t *ctx = calc_create(&mgr); + calc_ast_node_t *ast = NULL; + while (calc_parse(ctx, &ast)) { + dump_ast(ast, 0); + calc_ast_node__destroy(ast); + } + calc_destroy(ctx); + } + calc_ast_manager__finalize(&mgr); + return 0; +} diff --git a/src/subprojects/packcc/examples/ast-tinyc/.gitignore b/src/subprojects/packcc/examples/ast-tinyc/.gitignore new file mode 100644 index 00000000..84c048a7 --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/src/subprojects/packcc/examples/ast-tinyc/CMakeLists.txt b/src/subprojects/packcc/examples/ast-tinyc/CMakeLists.txt new file mode 100644 index 00000000..0ae1898d --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.2) + +project(ast) + +set(PACKCC packcc CACHE FILEPATH "Specify file path of packcc command.") + +add_custom_command( + OUTPUT parser.c parser.h + COMMAND ${PACKCC} ARGS -o parser ${CMAKE_CURRENT_SOURCE_DIR}/parser.peg + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/parser.peg + VERBATIM +) + +add_executable(ast main.c parser.c system.c utility.c) + +target_compile_features(ast PRIVATE c_std_99) +target_include_directories(ast BEFORE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/subprojects/packcc/examples/ast-tinyc/README.md b/src/subprojects/packcc/examples/ast-tinyc/README.md new file mode 100644 index 00000000..3dc4107f --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/README.md @@ -0,0 +1,142 @@ +# AST Builder for Tiny-C # + +## Overview ## + +This example builds an AST (abstract syntax tree) from an input source file +written in [Tiny-C](http://www.iro.umontreal.ca/~felipe/IFT2030-Automne2002/Complements/tinyc.c) with some extension shown below, +and prints the AST in the standard output. +If there are syntax errors, it shows them with line and column numbers. + +__Extension:__ +- Supports all arithmetic, logical and bitwise operators, +- Accepts octal and hexadecimal integers, +- Permits uppercase letters, number letters, and underscores in an identifier, +- Accepts `'\v'` and `'\f'` as white-spaces, +- Supports comment blocks. + +This example is placed in the public domain! +So, you can use it freely without noticing the copyright of the original author. + +## How to compile this example ## + +### For Unix-like OS ### + +You can get the executable by executing the following commands: + +``` +cd /path/to/this_directory +mkdir build +cd build +cmake -DPACKCC=/path/to/packcc .. +make +``` + +Here, `/path/to/this_directory` represents the path name of this directory, +and `/path/to/packcc` represents the path name of `packcc` command. +If `packcc` command is installed in one of the directories specified in the environment variable `PATH`, +the option `-DPACKCC=/path/to/packcc` is not necessary. + +The executable `ast` will be created in the directory `build`. + +### For Windows ### + +#### Using Visual Studio #### + +You must have [Build Tools for Visual Studio](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019) installed in your system. +You can get the executable by executing the following commands using 'Developer Command Prompt for VS 2019' or 'Developer PowerShell for VS 2019': + +``` +cd \path\to\this_directory +mkdir build +cd build +cmake -DPACKCC=\path\to\packcc .. +MSBuild ALL_BUILD.vcxproj +``` + +Here, `\path\to\this_directory` represents the path name of this directory, +and `\path\to\packcc` represents the path name of `packcc` command. +If `packcc` command is installed in one of the directories specified in the environment variable `PATH`, +the option `-DPACKCC=\path\to\packcc` is not necessary. + +The executable `ast.exe` will be created in the directory `build\Debug`. + +#### Using MinGW-w64 #### + +You can get the executable by executing the following commands: + +``` +cd /path/to/this_directory +mkdir build +cd build +cmake -G "MSYS Makefiles" -DPACKCC=/path/to/packcc .. +make +``` + +Here, `/path/to/this_directory` represents the path name of this directory, +and `/path/to/packcc` represents the path name of `packcc` command. +If `packcc` command is installed in one of the directories specified in the environment variable `PATH`, +the option `-DPACKCC=/path/to/packcc` is not necessary. + +The executable `ast.exe` will be created in the directory `build`. + +## How to run this example ## + +Example input source files are prepared in [`inputs`](inputs) directory. +Most of these are taken from [grammars-v4](https://github.com/antlr/grammars-v4/) repository of [ANTLR project](https://github.com/antlr/) with thanks. + +Here, it is assumed that you are in the directory `build`. +If you want to print out the AST of the input source file [`inputs/example2.c`](inputs/example2.c), execute the following command: + +``` +./ast ../inputs/example2.c +``` + +You will see the output below: + +``` +STATEMENT_LIST: arity = 1 + STATEMENT_LIST: arity = 3 + OPERATOR_ASSIGN: arity = 2 + IDENTIFIER: line = 2, column = 3, value = 'i' + INTEGER_DEC: line = 2, column = 5, value = '125' + OPERATOR_ASSIGN: arity = 2 + IDENTIFIER: line = 2, column = 10, value = 'j' + INTEGER_DEC: line = 2, column = 12, value = '100' + STATEMENT_WHILE: arity = 2 + OPERATOR_SUB: arity = 2 + IDENTIFIER: line = 2, column = 24, value = 'i' + IDENTIFIER: line = 2, column = 26, value = 'j' + STATEMENT_IF_ELSE: arity = 3 + OPERATOR_LT: arity = 2 + IDENTIFIER: line = 2, column = 33, value = 'i' + IDENTIFIER: line = 2, column = 35, value = 'j' + OPERATOR_ASSIGN: arity = 2 + IDENTIFIER: line = 2, column = 38, value = 'j' + OPERATOR_SUB: arity = 2 + IDENTIFIER: line = 2, column = 40, value = 'j' + IDENTIFIER: line = 2, column = 42, value = 'i' + OPERATOR_ASSIGN: arity = 2 + IDENTIFIER: line = 2, column = 50, value = 'i' + OPERATOR_SUB: arity = 2 + IDENTIFIER: line = 2, column = 52, value = 'i' + IDENTIFIER: line = 2, column = 54, value = 'j' +``` + +If there are errors in the input source file, this example reports up to 4 errors at a time. +You can see this behavior by the following command using [`inputs/erroneous1.c`](inputs/erroneous1.c): + +``` +./ast ../inputs/erroneous1.c +``` + +You will see the error messages below: + +``` +ERROR: line 6, column 5: Unexpected token 'do' +ERROR: line 7, column 5: Statement missing after 'do' +ERROR: line 4, column 5: 'else' without corresponding 'if' +ERROR: line 3, column 5: 'else' without corresponding 'if' +``` + +Note that the multiple error recognition of this example is not sophisticated. +To improve it, you have to design elaborate grammar rules for error skipping to detect next multiple errors naturally. diff --git a/src/subprojects/packcc/examples/ast-tinyc/inputs/erroneous1.c b/src/subprojects/packcc/examples/ast-tinyc/inputs/erroneous1.c new file mode 100644 index 00000000..d05add87 --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/inputs/erroneous1.c @@ -0,0 +1,7 @@ +/* This code has multiple errors for testing. */ + + else + else + if + do + do diff --git a/src/subprojects/packcc/examples/ast-tinyc/inputs/example1.c b/src/subprojects/packcc/examples/ast-tinyc/inputs/example1.c new file mode 100644 index 00000000..4869df0a --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/inputs/example1.c @@ -0,0 +1,2 @@ +/* https://github.com/antlr/grammars-v4/blob/master/tinyc/examples/example1.c */ +{ i=1; while (i<100) i=i+i; } diff --git a/src/subprojects/packcc/examples/ast-tinyc/inputs/example2.c b/src/subprojects/packcc/examples/ast-tinyc/inputs/example2.c new file mode 100644 index 00000000..fc84b623 --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/inputs/example2.c @@ -0,0 +1,2 @@ +/* https://github.com/antlr/grammars-v4/blob/master/tinyc/examples/example2.c */ +{ i=125; j=100; while (i-j) if (i + +int main(int argc, char **argv) { + if (argc > 2) { + fprintf(stderr, "ERROR: Too many arguments\n"); + return 1; /* usage error */ + } + const char *path = (argc > 1) ? argv[1] : NULL; + int ret = 0; + system_t system; + parser_context_t *parser = NULL; + if (setjmp(system.jmp) == 0) { + system__initialize(&system); + system__open_source_file(&system, path); + parser = parser_create(&system); + ast_node_t *ast; + const int b = parser_parse(parser, &ast); + if (system.source.ecount > 0) longjmp(system.jmp, 1); /* never returns */ + if (b) { + ret = 10; /* internal error */ + fprintf(stderr, "FATAL: Internal error\n"); + /* <-- input text remaining due to incompleteness of the grammar */ + } + else { + system__dump_ast(&system, ast); + } + } + else { + ret = 2; /* error during parsing */ + } + parser_destroy(parser); + system__finalize(&system); /* all system resources are freed */ + return ret; +} diff --git a/src/subprojects/packcc/examples/ast-tinyc/parser.peg b/src/subprojects/packcc/examples/ast-tinyc/parser.peg new file mode 100644 index 00000000..5ecc3886 --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/parser.peg @@ -0,0 +1,587 @@ +# This code is hereby placed in the public domain. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%prefix "parser" + +%value "ast_node_t *" +%auxil "system_t *" + +%header { +#include "system.h" +} + +%source { +#define PCC_ERROR(auxil) system__handle_syntax_error(auxil, SYNTAX_ERROR_UNKNOWN, range__void()) /* <-- caused by incompleteness of the grammar */ +#define PCC_GETCHAR(auxil) system__read_source_file(auxil) +#define PCC_MALLOC(auxil, size) system__allocate_memory(auxil, size) +#define PCC_REALLOC(auxil, ptr, size) system__reallocate_memory(auxil, ptr, size) +#define PCC_FREE(auxil, ptr) system__deallocate_memory(auxil, ptr) +} + +program + <- _ l:statement_list _ end_of_file + { + $$ = l; + } + / _ end_of_file + { + $$ = system__create_ast_node_variadic(auxil, AST_NODE_TYPE_STATEMENT_LIST, range__new($0s, $0e)); + } + +statement_list + <- s:statement _ l:statement_list + { + $$ = l; + $$->range = range__new($0s, $0e); + ast_node__prepend_child($$, s); + } + / s:statement + { + $$ = system__create_ast_node_variadic(auxil, AST_NODE_TYPE_STATEMENT_LIST, range__new($0s, $0e)); + ast_node__prepend_child($$, s); + } + +statement + <- kw_if _ e:expression_in_parentheses _ s:statement _ kw_else _ t:statement + { + $$ = system__create_ast_node_ternary(auxil, AST_NODE_TYPE_STATEMENT_IF_ELSE, range__new($0s, $0e), e, s, t); + } + / kw_if _ e:expression_in_parentheses _ s:statement + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_STATEMENT_IF, range__new($0s, $0e), e, s); + } + / kw_while _ e:expression_in_parentheses _ s:statement + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_STATEMENT_WHILE, range__new($0s, $0e), e, s); + } + / kw_do _ s:statement _ kw_while _ e:expression_in_parentheses _ ';' + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_STATEMENT_DO_WHILE, range__new($0s, $0e), e, s); + } + / '{' _ l:statement_list _ '}' + { + $$ = l; + } + / '{' _ '}' + { + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_STATEMENT_VOID, range__new($0s, $0e)); + } + / e:expression _ ';' + { + $$ = e; + } + / ';' + { + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_STATEMENT_VOID, range__new($0s, $0e)); + } + ## error handling ## + / kw_if _ e:expression_in_parentheses _ s:statement _ kw_else + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_ELSE_WITHOUT_STATEMENT, range__new($0s, $0e)); + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_ERROR_SKIP_IF_2, range__new($0s, $0e), e, s); + } + / kw_if _ e:expression_in_parentheses + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_IF_WITHOUT_STATEMENT, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP_IF_1, range__new($0s, $0e), e); + } + / kw_if + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_IF_WITHOUT_CONDITION, range__new($0s, $0e)); + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_ERROR_SKIP_IF_0, range__new($0s, $0e)); + } + / kw_else _ s:statement + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_LONE_ELSE, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP_ELSE_1, range__new($0s, $0e), s); + } + / kw_else + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_LONE_ELSE, range__new($0s, $0e)); + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_ERROR_SKIP_ELSE_0, range__new($0s, $0e)); + } + / kw_while _ e:expression_in_parentheses + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_WHILE_WITHOUT_STATEMENT, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP_WHILE_1, range__new($0s, $0e), e); + } + / kw_while + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_WHILE_WITHOUT_CONDITION, range__new($0s, $0e)); + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_ERROR_SKIP_WHILE_0, range__new($0s, $0e)); + } + / kw_do _ s:statement _ kw_while _ e:expression_in_parentheses + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_NO_ENDING_SEMICOLON, range__new($0s, $0e)); + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_ERROR_SKIP_DO_2, range__new($0s, $0e), s, e); + } + / kw_do _ s:statement _ kw_while + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_WHILE_WITHOUT_STATEMENT, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP_DO_1, range__new($0s, $0e), s); + } + / kw_do _ s:statement + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_DO_WITHOUT_WHILE, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP_DO_1, range__new($0s, $0e), s); + } + / kw_do + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_DO_WITHOUT_STATEMENT, range__new($0s, $0e)); + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_ERROR_SKIP_DO_0, range__new($0s, $0e)); + } + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_in_parentheses + <- '(' _ e:expression _ ')' + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression + <- l:expression _ ',' _ e:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_COMMA, range__new($0s, $0e), l, e); + } + / e:expression_assignment + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_assignment + <- e:expression_condition _ '&=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_AND, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '|=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_OR, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '^=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_XOR, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '+=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_ADD, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '-=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_SUB, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '*=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_MUL, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '/=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_DIV, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '%=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_MOD, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '<<=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_SHL, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '>>=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN_SHR, range__new($0s, $0e), e, r); + } + / e:expression_condition _ '=' _ r:expression_assignment + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ASSIGN, range__new($0s, $0e), e, r); + } + / e:expression_condition + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_condition + <- e:expression_or2 _ '?' _ l:expression _ ':' _ r:expression_condition + { + $$ = system__create_ast_node_ternary(auxil, AST_NODE_TYPE_OPERATOR_COND, range__new($0s, $0e), e, l, r); + } + / e:expression_or2 + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_or2 + <- l:expression_or2 _ '||' _ e:expression_and2 + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_OR2, range__new($0s, $0e), l, e); + } + / e:expression_and2 + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_and2 + <- l:expression_and2 _ '&&' _ e:expression_or + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_AND2, range__new($0s, $0e), l, e); + } + / e:expression_or + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_or + <- l:expression_or _ '|' _ e:expression_xor + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_OR, range__new($0s, $0e), l, e); + } + / e:expression_xor + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_xor + <- l:expression_xor _ '^' _ e:expression_and + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_XOR, range__new($0s, $0e), l, e); + } + / e:expression_and + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_and + <- l:expression_and _ '&' _ e:expression_equality + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_AND, range__new($0s, $0e), l, e); + } + / e:expression_equality + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_equality + <- l:expression_equality _ '==' _ e:expression_relation + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_EQ, range__new($0s, $0e), l, e); + } + / l:expression_equality _ '!=' _ e:expression_relation + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_NE, range__new($0s, $0e), l, e); + } + / e:expression_relation + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_relation + <- l:expression_relation _ '<=' _ e:expression_shift + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_LE, range__new($0s, $0e), l, e); + } + / l:expression_relation _ '>=' _ e:expression_shift + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_GE, range__new($0s, $0e), l, e); + } + / l:expression_relation _ '<' _ e:expression_shift + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_LT, range__new($0s, $0e), l, e); + } + / l:expression_relation _ '>' _ e:expression_shift + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_GT, range__new($0s, $0e), l, e); + } + / e:expression_shift + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_shift + <- l:expression_shift _ '<<' _ e:expression_addition + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_SHL, range__new($0s, $0e), l, e); + } + / l:expression_shift _ '>>' _ e:expression_addition + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_SHR, range__new($0s, $0e), l, e); + } + / e:expression_addition + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_addition + <- l:expression_addition _ '+' _ e:expression_multiplication + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_ADD, range__new($0s, $0e), l, e); + } + / l:expression_addition _ '-' _ e:expression_multiplication + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_SUB, range__new($0s, $0e), l, e); + } + / e:expression_multiplication + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_multiplication + <- l:expression_multiplication _ '*' _ e:expression_unary + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_MUL, range__new($0s, $0e), l, e); + } + / l:expression_multiplication _ '/' _ e:expression_unary + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_DIV, range__new($0s, $0e), l, e); + } + / l:expression_multiplication _ '%' _ e:expression_unary + { + $$ = system__create_ast_node_binary(auxil, AST_NODE_TYPE_OPERATOR_MOD, range__new($0s, $0e), l, e); + } + / e:expression_unary + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_unary + <- '++' _ e:expression_unary + { + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_OPERATOR_INC, range__new($0s, $0e), e); + } + / '--' _ e:expression_unary + { + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_OPERATOR_DEC, range__new($0s, $0e), e); + } + / '+' _ e:expression_unary + { + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_OPERATOR_PLUS, range__new($0s, $0e), e); + } + / '-' _ e:expression_unary + { + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_OPERATOR_MINUS, range__new($0s, $0e), e); + } + / '!' _ e:expression_unary + { + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_OPERATOR_NOT, range__new($0s, $0e), e); + } + / '~' _ e:expression_unary + { + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_OPERATOR_INV, range__new($0s, $0e), e); + } + / e:expression_postfix + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_postfix + <- e:expression_postfix _ '++' + { + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_OPERATOR_POST_INC, range__new($0s, $0e), e); + } + / e:expression_postfix _ '--' + { + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_OPERATOR_POST_DEC, range__new($0s, $0e), e); + } + / e:expression_primary + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +expression_primary + <- e:identifier + { + $$ = e; + } + / e:integer + { + $$ = e; + } + / '(' _ e:expression _ ')' + { + $$ = e; + } + ## error handling ## + / e:error_skip + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNEXPECTED_TOKEN, range__new($0s, $0e)); + $$ = system__create_ast_node_unary(auxil, AST_NODE_TYPE_ERROR_SKIP, range__new($0s, $0e), e); + } + +error_skip + <- '{' l:statement_list '}'? + { + $$ = l; + } + / '(' e:expression ')'? + { + $$ = e; + } + / '[' e:expression ']'? + { + $$ = e; + } + / (L/D)+ + { + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_UNEXPECTED_TOKEN, range__new($0s, $0e)); + } + / !_ . + { + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_UNEXPECTED_TOKEN, range__new($0s, $0e)); + } + +identifier + <- !keyword L(L/D)* + { + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_IDENTIFIER, range__new($0s, $0e)); + } + +integer + <- '0'[xX]X+ + { + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_INTEGER_HEX, range__new($0s, $0e)); + } + / '0'O+ + { + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_INTEGER_OCT, range__new($0s, $0e)); + } + / !'0' D+ + { + $$ = system__create_ast_node_terminal(auxil, AST_NODE_TYPE_INTEGER_DEC, range__new($0s, $0e)); + } + +keyword + <- kw_if + / kw_else + / kw_do + / kw_while + +kw_if <- 'if' !(L/D) +kw_else <- 'else' !(L/D) +kw_do <- 'do' !(L/D) +kw_while <- 'while' !(L/D) + +O <- [0-7] +D <- [0-9] +X <- [0-9a-fA-F] +L <- [a-zA-Z_] + +_ <- ( space / comment )* +comment + <- '/*' ( !'*/' . )* '*/' + ## error handling ## + / '/*' ( !'*/' . )* + { + system__handle_syntax_error(auxil, SYNTAX_ERROR_UNCLOSED_COMMENT_BLOCK, range__new($0s, $0e)); + } +space <- blank / end_of_line +blank <- [ \t\v\f] +end_of_line <- '\r\n' / '\n' / '\r' +end_of_file <- !. diff --git a/src/subprojects/packcc/examples/ast-tinyc/system.c b/src/subprojects/packcc/examples/ast-tinyc/system.c new file mode 100644 index 00000000..4f852b8c --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/system.c @@ -0,0 +1,482 @@ +/* + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef _MSC_VER +#undef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* suppress the warning of fopen() use */ +#endif /* _MSC_VER */ + +#include "system.h" + +#include + +#ifndef ERROR_MAX +#define ERROR_MAX 4 /* the maximum number of errors displayed at a time */ +#endif + +static void append_text_character_(system_t *obj, char c) { + const size_t n = obj->source.text.n; + if (!char_array__resize(&(obj->source.text), n + 1)) { + fprintf(stderr, "FATAL: Out of memory\n"); + longjmp(obj->jmp, 1); /* never returns */ + } + obj->source.text.p[n] = (char)c; +} + +static void append_line_head_(system_t *obj, size_t h) { + const size_t n = obj->source.line.n; + if (!size_t_array__resize(&(obj->source.line), n + 1)) { + fprintf(stderr, "FATAL: Out of memory\n"); + longjmp(obj->jmp, 1); /* never returns */ + } + obj->source.line.p[n] = h; +} + +static size_t count_characters_(const char *buf, size_t start, size_t end) { + /* UTF-8 multibyte character support but without checking UTF-8 validity */ + size_t n = 0, i = start; + while (i < end) { + const int c = (int)(unsigned char)buf[i]; + if (c == 0) break; + n++; + i += (c < 0x80) ? 1 : ((c & 0xe0) == 0xc0) ? 2 : ((c & 0xf0) == 0xe0) ? 3 : ((c & 0xf8) == 0xf0) ? 4 : /* invalid code */ 1; + } + return n; +} + +static void compute_line_and_column_(system_t *obj, size_t pos, size_t *line, size_t *column) { + size_t i; + for (i = 1; i < obj->source.line.n; i++) { + if (pos < obj->source.line.p[i]) break; + } + if (line) *line = i; + if (column) *column = count_characters_(obj->source.text.p, obj->source.line.p[i - 1], pos) + 1; +} + +void system__initialize(system_t *obj) { + obj->source.path = NULL; + obj->source.file = NULL; + char_array__initialize(&(obj->source.text)); + size_t_array__initialize(&(obj->source.line)); + obj->source.ecount = 0; + obj->managed.first = NULL; + obj->managed.last = NULL; + append_line_head_(obj, 0); +} + +void system__finalize(system_t *obj) { + if (obj->source.file != NULL && obj->source.file != stdin) fclose(obj->source.file); + char_array__finalize(&(obj->source.text)); + size_t_array__finalize(&(obj->source.line)); + system__destroy_all_ast_nodes(obj); +} + +void *system__allocate_memory(system_t *obj, size_t size) { + void *const p = malloc(size); + if (p == NULL) { + fprintf(stderr, "FATAL: Out of memory\n"); + longjmp(obj->jmp, 1); /* never returns */ + } + return p; +} + +void *system__reallocate_memory(system_t *obj, void *ptr, size_t size) { + void *const p = realloc(ptr, size); + if (p == NULL) { + fprintf(stderr, "FATAL: Out of memory\n"); + longjmp(obj->jmp, 1); /* never returns */ + } + return p; +} + +void system__deallocate_memory(system_t *obj, void *ptr) { + free(ptr); +} + +void system__open_source_file(system_t *obj, const char *path) { + if (path != NULL) { + FILE *const f = fopen(path, "rt"); + if (f == NULL) { + fprintf(stderr, "FATAL: Cannot open file '%s'\n", path); + longjmp(obj->jmp, 1); /* never returns */ + } + obj->source.path = path; + obj->source.file = f; + } + else { + obj->source.path = NULL; + obj->source.file = stdin; + } +} + +void system__close_source_file(system_t *obj) { + if (obj->source.file != NULL && obj->source.file != stdin) { + if (fclose(obj->source.file) == EOF) { + fprintf(stderr, "FATAL: Error occurred while closing file '%s'\n", obj->source.path); + longjmp(obj->jmp, 1); /* never returns */ + } + } + obj->source.path = NULL; + obj->source.file = NULL; +} + +int system__read_source_file(system_t *obj) { + const int c = fgetc(obj->source.file); + if (c != EOF) { + append_text_character_(obj, (char)c); + if (c == '\r') { + append_line_head_(obj, obj->source.text.n); + } + else if (c == '\n') { + if (obj->source.text.n >= 2 && obj->source.text.p[obj->source.text.n - 2] == '\r') { + obj->source.line.p[obj->source.line.n - 1] = obj->source.text.n; + } + else { + append_line_head_(obj, obj->source.text.n); + } + } + } + else { + if (ferror(obj->source.file)) { + if (obj->source.path != NULL) { + fprintf(stderr, "FATAL: Error occurred while reading file '%s'\n", obj->source.path); + } + else { + fprintf(stderr, "FATAL: Error occurred while reading standard input\n"); + } + longjmp(obj->jmp, 1); /* never returns */ + } + } + return c; +} + +static ast_node_t *create_ast_node_(system_t *obj, ast_node_type_t type, range_t range) { + ast_node_t *const node = (ast_node_t *)system__allocate_memory(obj, sizeof(ast_node_t)); + node->type = type; + node->range = range; + node->arity = 0; + node->parent = NULL; + node->sibling.prev = NULL; + node->sibling.next = NULL; + node->child.first = NULL; + node->child.last = NULL; + node->system = obj; + if (obj->managed.last != NULL) { + node->managed.prev = obj->managed.last; + node->managed.next = NULL; + obj->managed.last = node; + if (node->managed.prev != NULL) { + node->managed.prev->managed.next = node; + } + else { + obj->managed.first = node; + } + } + else { + node->managed.prev = NULL; + node->managed.next = NULL; + obj->managed.first = node; + obj->managed.last = node; + } + return node; +} + +ast_node_t *system__create_ast_node_terminal(system_t *obj, ast_node_type_t type, range_t range) { + return create_ast_node_(obj, type, range); +} + +ast_node_t *system__create_ast_node_unary(system_t *obj, ast_node_type_t type, range_t range, ast_node_t *node1) { + if (node1 == NULL) { + fprintf(stderr, "FATAL: Internal error\n"); + longjmp(obj->jmp, 1); /* never returns */ + } + ast_node_t *const node = create_ast_node_(obj, type, range); + ast_node__append_child(node, node1); + return node; +} + +ast_node_t *system__create_ast_node_binary(system_t *obj, ast_node_type_t type, range_t range, ast_node_t *node1, ast_node_t *node2) { + if (node1 == NULL || node2 == NULL) { + fprintf(stderr, "FATAL: Internal error\n"); + longjmp(obj->jmp, 1); /* never returns */ + } + ast_node_t *const node = create_ast_node_(obj, type, range); + ast_node__append_child(node, node1); + ast_node__append_child(node, node2); + return node; +} + +ast_node_t *system__create_ast_node_ternary(system_t *obj, ast_node_type_t type, range_t range, ast_node_t *node1, ast_node_t *node2, ast_node_t *node3) { + if (node1 == NULL || node2 == NULL || node3 == NULL) { + fprintf(stderr, "FATAL: Internal error\n"); + longjmp(obj->jmp, 1); /* never returns */ + } + ast_node_t *const node = create_ast_node_(obj, type, range); + ast_node__append_child(node, node1); + ast_node__append_child(node, node2); + ast_node__append_child(node, node3); + return node; +} + +ast_node_t *system__create_ast_node_variadic(system_t *obj, ast_node_type_t type, range_t range) { + return create_ast_node_(obj, type, range); +} + +void system__destroy_all_ast_nodes(system_t *obj) { + while (obj->managed.first != NULL) { + ast_node__destroy(obj->managed.first); + } +} + +void ast_node__prepend_child(ast_node_t *obj, ast_node_t *node) { + if (node == NULL) return; /* just ignored */ + if (node->parent != NULL) { + if (node->sibling.prev != NULL) { + node->sibling.prev->sibling.next = node->sibling.next; + } + else { + node->parent->child.first = node->sibling.next; + } + if (node->sibling.next != NULL) { + node->sibling.next->sibling.prev = node->sibling.prev; + } + else { + node->parent->child.last = node->sibling.prev; + } + node->parent->arity--; + } + node->parent = obj; + if (obj->child.first != NULL) { + obj->child.first->sibling.prev = node; + node->sibling.next = obj->child.first; + node->sibling.prev = NULL; + obj->child.first = node; + } + else { + node->sibling.next = NULL; + node->sibling.prev = NULL; + obj->child.first = node; + obj->child.last = node; + } + obj->arity++; +} + +void ast_node__append_child(ast_node_t *obj, ast_node_t *node) { + if (node == NULL) return; /* just ignored */ + if (node->parent != NULL) { + if (node->sibling.prev != NULL) { + node->sibling.prev->sibling.next = node->sibling.next; + } + else { + node->parent->child.first = node->sibling.next; + } + if (node->sibling.next != NULL) { + node->sibling.next->sibling.prev = node->sibling.prev; + } + else { + node->parent->child.last = node->sibling.prev; + } + node->parent->arity--; + } + node->parent = obj; + if (obj->child.last != NULL) { + obj->child.last->sibling.next = node; + node->sibling.prev = obj->child.last; + node->sibling.next = NULL; + obj->child.last = node; + } + else { + node->sibling.prev = NULL; + node->sibling.next = NULL; + obj->child.last = node; + obj->child.first = node; + } + obj->arity++; +} + +void ast_node__destroy(ast_node_t *obj) { + if (obj->parent != NULL) { + if (obj->sibling.prev != NULL) { + obj->sibling.prev->sibling.next = obj->sibling.next; + } + else { + obj->parent->child.first = obj->sibling.next; + } + if (obj->sibling.next != NULL) { + obj->sibling.next->sibling.prev = obj->sibling.prev; + } + else { + obj->parent->child.last = obj->sibling.prev; + } + obj->parent->arity--; + } + while (obj->child.first != NULL) { + ast_node_t *const child = obj->child.first; + obj->child.first = child->sibling.next; + child->sibling.next = NULL; + child->sibling.prev = NULL; + child->parent = NULL; + } + { + if (obj->managed.prev != NULL) { + obj->managed.prev->managed.next = obj->managed.next; + } + else { + obj->system->managed.first = obj->managed.next; + } + if (obj->managed.next != NULL) { + obj->managed.next->managed.prev = obj->managed.prev; + } + else { + obj->system->managed.last = obj->managed.prev; + } + } + system__deallocate_memory(obj->system, obj); +} + +void system__handle_syntax_error(system_t *obj, syntax_error_t error, range_t range) { + size_t line, col; + compute_line_and_column_(obj, range.min, &line, &col); + obj->source.ecount++; + switch (error) { + case SYNTAX_ERROR_IF_WITHOUT_CONDITION: + fprintf(stderr, "ERROR: line %zu, column %zu: Condition missing after 'if'\n", line, col); + break; + case SYNTAX_ERROR_IF_WITHOUT_STATEMENT: + fprintf(stderr, "ERROR: line %zu, column %zu: Statement missing after 'if' condition\n", line, col); + break; + case SYNTAX_ERROR_ELSE_WITHOUT_STATEMENT: + fprintf(stderr, "ERROR: line %zu, column %zu: Statement missing after 'else'\n", line, col); + break; + case SYNTAX_ERROR_LONE_ELSE: + fprintf(stderr, "ERROR: line %zu, column %zu: 'else' without corresponding 'if'\n", line, col); + break; + case SYNTAX_ERROR_WHILE_WITHOUT_CONDITION: + fprintf(stderr, "ERROR: line %zu, column %zu: Condition missing after 'while'\n", line, col); + break; + case SYNTAX_ERROR_WHILE_WITHOUT_STATEMENT: + fprintf(stderr, "ERROR: line %zu, column %zu: Statement missing after 'while' condition\n", line, col); + break; + case SYNTAX_ERROR_DO_WITHOUT_STATEMENT: + fprintf(stderr, "ERROR: line %zu, column %zu: Statement missing after 'do'\n", line, col); + break; + case SYNTAX_ERROR_DO_WITHOUT_WHILE: + fprintf(stderr, "ERROR: line %zu, column %zu: 'while' missing after 'do' statement\n", line, col); + break; + case SYNTAX_ERROR_NO_ENDING_SEMICOLON: + fprintf(stderr, "ERROR: line %zu, column %zu: Ending semicolon missing\n", line, col); + break; + case SYNTAX_ERROR_UNCLOSED_COMMENT_BLOCK: + fprintf(stderr, "ERROR: line %zu, column %zu: Unclosed comment block\n", line, col); + break; + case SYNTAX_ERROR_UNEXPECTED_TOKEN: + fprintf(stderr, "ERROR: line %zu, column %zu: Unexpected token '%.*s'\n", line, col, (int)(range.max - range.min), obj->source.text.p + range.min); + break; + case SYNTAX_ERROR_UNKNOWN: + fprintf(stderr, "ERROR: line %zu, column %zu: Unknown error\n", line, col); + break; + default: + fprintf(stderr, "ERROR: line %zu, column %zu: Undefined internal error\n", line, col); + } + if (obj->source.ecount >= ERROR_MAX) longjmp(obj->jmp, 1); /* never returns */ +} + +static void dump_ast_(system_t *obj, ast_node_t *node, int level) { + const char *type = "UNKNOWN"; + switch (node->type) { + case AST_NODE_TYPE_IDENTIFIER: type = "IDENTIFIER"; break; + case AST_NODE_TYPE_INTEGER_DEC: type = "INTEGER_DEC"; break; + case AST_NODE_TYPE_INTEGER_OCT: type = "INTEGER_OCT"; break; + case AST_NODE_TYPE_INTEGER_HEX: type = "INTEGER_HEX"; break; + case AST_NODE_TYPE_OPERATOR_PLUS: type = "OPERATOR_PLUS"; break; + case AST_NODE_TYPE_OPERATOR_MINUS: type = "OPERATOR_MINUS"; break; + case AST_NODE_TYPE_OPERATOR_INV: type = "OPERATOR_INV"; break; + case AST_NODE_TYPE_OPERATOR_NOT: type = "OPERATOR_NOT"; break; + case AST_NODE_TYPE_OPERATOR_INC: type = "OPERATOR_INC"; break; + case AST_NODE_TYPE_OPERATOR_DEC: type = "OPERATOR_DEC"; break; + case AST_NODE_TYPE_OPERATOR_POST_INC: type = "OPERATOR_POST_INC"; break; + case AST_NODE_TYPE_OPERATOR_POST_DEC: type = "OPERATOR_POST_DEC"; break; + case AST_NODE_TYPE_OPERATOR_ADD: type = "OPERATOR_ADD"; break; + case AST_NODE_TYPE_OPERATOR_SUB: type = "OPERATOR_SUB"; break; + case AST_NODE_TYPE_OPERATOR_MUL: type = "OPERATOR_MUL"; break; + case AST_NODE_TYPE_OPERATOR_DIV: type = "OPERATOR_DIV"; break; + case AST_NODE_TYPE_OPERATOR_MOD: type = "OPERATOR_MOD"; break; + case AST_NODE_TYPE_OPERATOR_AND: type = "OPERATOR_AND"; break; + case AST_NODE_TYPE_OPERATOR_AND2: type = "OPERATOR_AND2"; break; + case AST_NODE_TYPE_OPERATOR_OR: type = "OPERATOR_OR"; break; + case AST_NODE_TYPE_OPERATOR_OR2: type = "OPERATOR_OR2"; break; + case AST_NODE_TYPE_OPERATOR_XOR: type = "OPERATOR_XOR"; break; + case AST_NODE_TYPE_OPERATOR_SHL: type = "OPERATOR_SHL"; break; + case AST_NODE_TYPE_OPERATOR_SHR: type = "OPERATOR_SHR"; break; + case AST_NODE_TYPE_OPERATOR_EQ: type = "OPERATOR_EQ"; break; + case AST_NODE_TYPE_OPERATOR_NE: type = "OPERATOR_NE"; break; + case AST_NODE_TYPE_OPERATOR_LT: type = "OPERATOR_LT"; break; + case AST_NODE_TYPE_OPERATOR_LE: type = "OPERATOR_LE"; break; + case AST_NODE_TYPE_OPERATOR_GT: type = "OPERATOR_GT"; break; + case AST_NODE_TYPE_OPERATOR_GE: type = "OPERATOR_GE"; break; + case AST_NODE_TYPE_OPERATOR_COND: type = "OPERATOR_COND"; break; + case AST_NODE_TYPE_OPERATOR_COMMA: type = "OPERATOR_COMMA"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN: type = "OPERATOR_ASSIGN"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_ADD: type = "OPERATOR_ASSIGN_ADD"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_SUB: type = "OPERATOR_ASSIGN_SUB"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_MUL: type = "OPERATOR_ASSIGN_MUL"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_DIV: type = "OPERATOR_ASSIGN_DIV"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_MOD: type = "OPERATOR_ASSIGN_MOD"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_AND: type = "OPERATOR_ASSIGN_AND"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_OR: type = "OPERATOR_ASSIGN_OR"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_XOR: type = "OPERATOR_ASSIGN_XOR"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_SHL: type = "OPERATOR_ASSIGN_SHL"; break; + case AST_NODE_TYPE_OPERATOR_ASSIGN_SHR: type = "OPERATOR_ASSIGN_SHR"; break; + case AST_NODE_TYPE_STATEMENT_VOID: type = "STATEMENT_VOID"; break; + case AST_NODE_TYPE_STATEMENT_IF: type = "STATEMENT_IF"; break; + case AST_NODE_TYPE_STATEMENT_IF_ELSE: type = "STATEMENT_IF_ELSE"; break; + case AST_NODE_TYPE_STATEMENT_WHILE: type = "STATEMENT_WHILE"; break; + case AST_NODE_TYPE_STATEMENT_DO_WHILE: type = "STATEMENT_DO_WHILE"; break; + case AST_NODE_TYPE_STATEMENT_LIST: type = "STATEMENT_LIST"; break; + case AST_NODE_TYPE_ERROR_SKIP: type = "ERROR_SKIP"; break; + case AST_NODE_TYPE_ERROR_SKIP_IF_0: type = "ERROR_SKIP_IF_0"; break; + case AST_NODE_TYPE_ERROR_SKIP_IF_1: type = "ERROR_SKIP_IF_1"; break; + case AST_NODE_TYPE_ERROR_SKIP_IF_2: type = "ERROR_SKIP_IF_2"; break; + case AST_NODE_TYPE_ERROR_SKIP_ELSE_0: type = "ERROR_SKIP_ELSE_0"; break; + case AST_NODE_TYPE_ERROR_SKIP_ELSE_1: type = "ERROR_SKIP_ELSE_1"; break; + case AST_NODE_TYPE_ERROR_SKIP_DO_0: type = "ERROR_SKIP_DO_0"; break; + case AST_NODE_TYPE_ERROR_SKIP_DO_1: type = "ERROR_SKIP_DO_1"; break; + case AST_NODE_TYPE_ERROR_SKIP_DO_2: type = "ERROR_SKIP_DO_2"; break; + case AST_NODE_TYPE_ERROR_SKIP_WHILE_0: type = "ERROR_SKIP_WHILE_0"; break; + case AST_NODE_TYPE_ERROR_SKIP_WHILE_1: type = "ERROR_SKIP_WHILE_1"; break; + case AST_NODE_TYPE_UNEXPECTED_TOKEN: type = "UNEXPECTED_TOKEN"; break; + default: break; + } + if (node->arity > 0 || node->type == AST_NODE_TYPE_STATEMENT_LIST) { + printf("%*s%s: arity = %zu\n", 2 * level, "", type, node->arity); + for (ast_node_t *p = node->child.first; p != NULL; p = p->sibling.next) { + dump_ast_(obj, p, level + 1); + } + } + else { + size_t line, col; + compute_line_and_column_(obj, node->range.min, &line, &col); + printf( + "%*s%s: line = %zu, column = %zu, value = '%.*s'\n", + 2 * level, "", type, line, col, + (int)(node->range.max - node->range.min), obj->source.text.p + node->range.min + ); + } +} + +void system__dump_ast(system_t *obj, ast_node_t *root) { + dump_ast_(obj, root, 0); +} diff --git a/src/subprojects/packcc/examples/ast-tinyc/system.h b/src/subprojects/packcc/examples/ast-tinyc/system.h new file mode 100644 index 00000000..0f434a75 --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/system.h @@ -0,0 +1,177 @@ +/* + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef INCLUDED_SYSTEM_H +#define INCLUDED_SYSTEM_H + +#include "utility.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct system_tag system_t; +typedef struct ast_node_tag ast_node_t; + +typedef enum ast_node_type_tag { + AST_NODE_TYPE_IDENTIFIER, + AST_NODE_TYPE_INTEGER_DEC, + AST_NODE_TYPE_INTEGER_OCT, + AST_NODE_TYPE_INTEGER_HEX, + AST_NODE_TYPE_OPERATOR_PLUS, + AST_NODE_TYPE_OPERATOR_MINUS, + AST_NODE_TYPE_OPERATOR_INV, + AST_NODE_TYPE_OPERATOR_NOT, + AST_NODE_TYPE_OPERATOR_INC, + AST_NODE_TYPE_OPERATOR_DEC, + AST_NODE_TYPE_OPERATOR_POST_INC, + AST_NODE_TYPE_OPERATOR_POST_DEC, + AST_NODE_TYPE_OPERATOR_ADD, + AST_NODE_TYPE_OPERATOR_SUB, + AST_NODE_TYPE_OPERATOR_MUL, + AST_NODE_TYPE_OPERATOR_DIV, + AST_NODE_TYPE_OPERATOR_MOD, + AST_NODE_TYPE_OPERATOR_AND, + AST_NODE_TYPE_OPERATOR_AND2, + AST_NODE_TYPE_OPERATOR_OR, + AST_NODE_TYPE_OPERATOR_OR2, + AST_NODE_TYPE_OPERATOR_XOR, + AST_NODE_TYPE_OPERATOR_SHL, + AST_NODE_TYPE_OPERATOR_SHR, + AST_NODE_TYPE_OPERATOR_EQ, + AST_NODE_TYPE_OPERATOR_NE, + AST_NODE_TYPE_OPERATOR_LT, + AST_NODE_TYPE_OPERATOR_LE, + AST_NODE_TYPE_OPERATOR_GT, + AST_NODE_TYPE_OPERATOR_GE, + AST_NODE_TYPE_OPERATOR_COND, + AST_NODE_TYPE_OPERATOR_COMMA, + AST_NODE_TYPE_OPERATOR_ASSIGN, + AST_NODE_TYPE_OPERATOR_ASSIGN_ADD, + AST_NODE_TYPE_OPERATOR_ASSIGN_SUB, + AST_NODE_TYPE_OPERATOR_ASSIGN_MUL, + AST_NODE_TYPE_OPERATOR_ASSIGN_DIV, + AST_NODE_TYPE_OPERATOR_ASSIGN_MOD, + AST_NODE_TYPE_OPERATOR_ASSIGN_AND, + AST_NODE_TYPE_OPERATOR_ASSIGN_OR, + AST_NODE_TYPE_OPERATOR_ASSIGN_XOR, + AST_NODE_TYPE_OPERATOR_ASSIGN_SHL, + AST_NODE_TYPE_OPERATOR_ASSIGN_SHR, + AST_NODE_TYPE_STATEMENT_VOID, + AST_NODE_TYPE_STATEMENT_IF, + AST_NODE_TYPE_STATEMENT_IF_ELSE, + AST_NODE_TYPE_STATEMENT_WHILE, + AST_NODE_TYPE_STATEMENT_DO_WHILE, + AST_NODE_TYPE_STATEMENT_LIST, + AST_NODE_TYPE_ERROR_SKIP, + AST_NODE_TYPE_ERROR_SKIP_IF_0, + AST_NODE_TYPE_ERROR_SKIP_IF_1, + AST_NODE_TYPE_ERROR_SKIP_IF_2, + AST_NODE_TYPE_ERROR_SKIP_ELSE_0, + AST_NODE_TYPE_ERROR_SKIP_ELSE_1, + AST_NODE_TYPE_ERROR_SKIP_DO_0, + AST_NODE_TYPE_ERROR_SKIP_DO_1, + AST_NODE_TYPE_ERROR_SKIP_DO_2, + AST_NODE_TYPE_ERROR_SKIP_WHILE_0, + AST_NODE_TYPE_ERROR_SKIP_WHILE_1, + AST_NODE_TYPE_UNEXPECTED_TOKEN +} ast_node_type_t; + +struct ast_node_tag { + ast_node_type_t type; /* the AST node type */ + range_t range; /* the byte range in the source text */ + size_t arity; /* the number of the child AST nodes */ + ast_node_t *parent; /* the parent AST node */ + struct ast_node_sibling_tag { + ast_node_t *prev; /* the previous sibling AST node */ + ast_node_t *next; /* the next sibling AST node */ + } sibling; + struct ast_node_child_tag { + ast_node_t *first; /* the first child AST node */ + ast_node_t *last; /* the last child AST node */ + } child; + system_t *system; /* the system that manages this AST node */ + struct ast_node_managed_tag { + ast_node_t *prev; /* the previous AST node managed by the same system */ + ast_node_t *next; /* the next AST node managed by the same system */ + } managed; +}; + +typedef enum syntax_error_tag { + SYNTAX_ERROR_IF_WITHOUT_CONDITION, + SYNTAX_ERROR_IF_WITHOUT_STATEMENT, + SYNTAX_ERROR_ELSE_WITHOUT_STATEMENT, + SYNTAX_ERROR_LONE_ELSE, + SYNTAX_ERROR_WHILE_WITHOUT_CONDITION, + SYNTAX_ERROR_WHILE_WITHOUT_STATEMENT, + SYNTAX_ERROR_DO_WITHOUT_STATEMENT, + SYNTAX_ERROR_DO_WITHOUT_WHILE, + SYNTAX_ERROR_NO_ENDING_SEMICOLON, + SYNTAX_ERROR_UNCLOSED_COMMENT_BLOCK, + SYNTAX_ERROR_UNEXPECTED_TOKEN, + SYNTAX_ERROR_UNKNOWN +} syntax_error_t; + +struct system_tag { + struct system_input_tag { + const char *path; /* the source file path */ + FILE *file; /* the source file pointer */ + char_array_t text; /* the source text */ + size_t_array_t line; /* the byte positions of the line head in the source text */ + size_t ecount; /* the error count */ + } source; + struct system_managed_tag { + ast_node_t *first; /* the first managed AST node */ + ast_node_t *last; /* the last managed AST node */ + } managed; + jmp_buf jmp; +}; + +void system__initialize(system_t *obj); +void system__finalize(system_t *obj); + +void *system__allocate_memory(system_t *obj, size_t size); +void *system__reallocate_memory(system_t *obj, void *ptr, size_t size); +void system__deallocate_memory(system_t *obj, void *ptr); + +void system__open_source_file(system_t *obj, const char *path); /* the standard input if path == NULL */ +void system__close_source_file(system_t *obj); +int system__read_source_file(system_t *obj); + +void system__handle_syntax_error(system_t *obj, syntax_error_t error, range_t range); + +ast_node_t *system__create_ast_node_terminal(system_t *obj, ast_node_type_t type, range_t range); +ast_node_t *system__create_ast_node_unary(system_t *obj, ast_node_type_t type, range_t range, ast_node_t *node1); +ast_node_t *system__create_ast_node_binary(system_t *obj, ast_node_type_t type, range_t range, ast_node_t *node1, ast_node_t *node2); +ast_node_t *system__create_ast_node_ternary(system_t *obj, ast_node_type_t type, range_t range, ast_node_t *node1, ast_node_t *node2, ast_node_t *node3); +ast_node_t *system__create_ast_node_variadic(system_t *obj, ast_node_type_t type, range_t range); + +void system__destroy_all_ast_nodes(system_t *obj); + +void system__dump_ast(system_t *obj, ast_node_t *root); + +void ast_node__prepend_child(ast_node_t *obj, ast_node_t *node); +void ast_node__append_child(ast_node_t *obj, ast_node_t *node); +void ast_node__destroy(ast_node_t *obj); + +#ifdef __cplusplus +} +#endif + +#endif /* !INCLUDED_SYSTEM_H */ diff --git a/src/subprojects/packcc/examples/ast-tinyc/utility.c b/src/subprojects/packcc/examples/ast-tinyc/utility.c new file mode 100644 index 00000000..b735e2bc --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/utility.c @@ -0,0 +1,77 @@ +/* + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "utility.h" + +#include + +#ifndef CHAR_ARRAY_MIN +#define CHAR_ARRAY_MIN 256 /* the minimum number of char_array_t elements to be allocated */ +#endif + +#ifndef SIZE_T_ARRAY_MIN +#define SIZE_T_ARRAY_MIN 16 /* the minimum number of size_t_array_t elements to be allocated */ +#endif + +void char_array__initialize(char_array_t *obj) { + obj->m = 0; + obj->n = 0; + obj->p = NULL; +} + +void char_array__finalize(char_array_t *obj) { + free(obj->p); +} + +bool_t char_array__resize(char_array_t *obj, size_t size) { + if (obj->m < size) { + size_t m = obj->m; + if (m == 0) m = CHAR_ARRAY_MIN; + while (m < size && m != 0) m <<= 1; + if (m == 0) m = size; /* in case of shift overflow */ + char *const p = (char *)realloc(obj->p, m); + if (p == NULL) return BOOL_FALSE; + obj->p = p; + obj->m = m; + } + obj->n = size; + return BOOL_TRUE; +} + +void size_t_array__initialize(size_t_array_t *obj) { + obj->m = 0; + obj->n = 0; + obj->p = NULL; +} + +void size_t_array__finalize(size_t_array_t *obj) { + free(obj->p); +} + +bool_t size_t_array__resize(size_t_array_t *obj, size_t size) { + if (obj->m < size) { + size_t m = obj->m; + if (m == 0) m = SIZE_T_ARRAY_MIN; + while (m < size && m != 0) m <<= 1; + if (m == 0) m = size; /* in case of shift overflow */ + size_t *const p = (size_t *)realloc(obj->p, sizeof(size_t) * m); + if (p == NULL) return BOOL_FALSE; + obj->p = p; + obj->m = m; + } + obj->n = size; + return BOOL_TRUE; +} diff --git a/src/subprojects/packcc/examples/ast-tinyc/utility.h b/src/subprojects/packcc/examples/ast-tinyc/utility.h new file mode 100644 index 00000000..5b653142 --- /dev/null +++ b/src/subprojects/packcc/examples/ast-tinyc/utility.h @@ -0,0 +1,70 @@ +/* + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef INCLUDED_UTILITY_H +#define INCLUDED_UTILITY_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum bool_tag { + BOOL_FALSE = 0, + BOOL_TRUE +} bool_t; + +typedef struct range_tag { + size_t min; /* the start position (inclusive) */ + size_t max; /* the end position (exclusive) */ +} range_t; + +typedef struct char_array_tag { + size_t m; /* the allocated length */ + size_t n; /* the actual length */ + char *p; /* the buffer */ +} char_array_t; + +typedef struct size_t_array_tag { + size_t m; /* the allocated length */ + size_t n; /* the actual length */ + size_t *p; /* the buffer */ +} size_t_array_t; + +void char_array__initialize(char_array_t *obj); +void char_array__finalize(char_array_t *obj); +bool_t char_array__resize(char_array_t *obj, size_t size); + +void size_t_array__initialize(size_t_array_t *obj); +void size_t_array__finalize(size_t_array_t *obj); +bool_t size_t_array__resize(size_t_array_t *obj, size_t size); + +#ifdef __cplusplus +} +#endif + +inline static range_t range__void(void) { + const range_t obj = { 0, 0 }; + return obj; +} + +inline static range_t range__new(size_t min, size_t max) { + const range_t obj = { min, max }; + return obj; +} + +#endif /* !INCLUDED_UTILITY_H */ diff --git a/src/subprojects/packcc/examples/calc.peg b/src/subprojects/packcc/examples/calc.peg new file mode 100644 index 00000000..7d630a0e --- /dev/null +++ b/src/subprojects/packcc/examples/calc.peg @@ -0,0 +1,51 @@ +# This code is hereby placed in the public domain. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%prefix "calc" + +%source { +#include +#include +} + +statement <- _ e:expression _ EOL { printf("answer=%d\n", e); } + / ( !EOL . )* EOL { printf("error\n"); } + +expression <- e:term { $$ = e; } + +term <- l:term _ '+' _ r:factor { $$ = l + r; } + / l:term _ '-' _ r:factor { $$ = l - r; } + / e:factor { $$ = e; } + +factor <- l:factor _ '*' _ r:unary { $$ = l * r; } + / l:factor _ '/' _ r:unary { $$ = l / r; } + / e:unary { $$ = e; } + +unary <- '+' _ e:unary { $$ = +e; } + / '-' _ e:unary { $$ = -e; } + / e:primary { $$ = e; } + +primary <- < [0-9]+ > { $$ = atoi($1); } + / '(' _ e:expression _ ')' { $$ = e; } + +_ <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' / ';' + +%% +int main(int argc, char **argv) { + calc_context_t *ctx = calc_create(NULL); + while (calc_parse(ctx, NULL)); + calc_destroy(ctx); + return 0; +} diff --git a/src/subprojects/packcc/import/README.md b/src/subprojects/packcc/import/README.md new file mode 100644 index 00000000..a7904d12 --- /dev/null +++ b/src/subprojects/packcc/import/README.md @@ -0,0 +1,12 @@ +# Import Files + +## Overview + +In this directory, import files are stored. + +## Import File Categories + +| Category Name | Description | +| --- | --- | +| [`char`](char) | Import files that define character matching rules. | +| [`code`](code)| Import files that provide utility codes. | diff --git a/src/subprojects/packcc/import/char/README.md b/src/subprojects/packcc/import/char/README.md new file mode 100644 index 00000000..6bae2a7b --- /dev/null +++ b/src/subprojects/packcc/import/char/README.md @@ -0,0 +1,121 @@ +# Import Files of Character Matching Rules + +## Overview + +In this directory, import files that define character matching rules are stored. +These import files are recommended to **be imported after the last rule** in the PEG file that imports them. + +## Import Files + +### `char/ascii_character_group.peg` + +#### Synopsis + +An import file that defines rules to match an ASCII character belonging to a specific character group. + +#### PEG Rules + +The following PEG rules are available. + +| Rule Name | Description | +| --- | --- | +| `ASCII_Printable_Character` | Matches a printable character, i.e. a character other than control characters. | +| `ASCII_Letter` | Matches an alphabet character (`[A-Za-z]`). | +| `ASCII_Control_Character` | Matches a control character (`[\x00-\x1f\x7f]`). | +| `ASCII_Special_Character` | Matches a character other than control characters, number characters, and alphabet characters. | +| `ASCII_Number` | Matches a number character (`[0-9]`). | +| `ASCII_Uppercase_Letter` | Matches an uppercase alphabet character (`[A-Z]`). | +| `ASCII_Lowercase_Letter` | Matches a lowercase alphabet character (`[a-z]`). | +| `ASCII_C_alnum` | Matches a character for which the standard C function `isalnum()` returns a non-zero value (`[0-9A-Za-z]`). | +| `ASCII_C_alpha` | Matches a character for which the standard C function `isalpha()` returns a non-zero value (= `ASCII_Letter`). | +| `ASCII_C_blank` | Matches a character for which the standard C function `isblank()` returns a non-zero value (`[ \t]`). | +| `ASCII_C_cntrl` | Matches a character for which the standard C function `iscntrl()` returns a non-zero value (= `ASCII_Control_Character`). | +| `ASCII_C_digit` | Matches a character for which the standard C function `isdigit()` returns a non-zero value (= `ASCII_Number`). | +| `ASCII_C_graph` | Matches a character for which the standard C function `isgraph()` returns a non-zero value (= `ASCII_Printable_Character` excluding the space character `' '`). | +| `ASCII_C_lower` | Matches a character for which the standard C function `islower()` returns a non-zero value (= `ASCII_Lowercase_Letter`). | +| `ASCII_C_print` | Matches a character for which the standard C function `isprint()` returns a non-zero value (= `ASCII_Printable_Character`). | +| `ASCII_C_punct` | Matches a character for which the standard C function `ispunct()` returns a non-zero value (= `ASCII_Special_Character` excluding the space character `' '`). | +| `ASCII_C_space` | Matches a character for which the standard C function `isspace()` returns a non-zero value (`[ \t\n\v\f\r]`). | +| `ASCII_C_upper` | Matches a character for which the standard C function `isupper()` returns a non-zero value (= `ASCII_Uppercase_Letter`). | +| `ASCII_C_xdigit` | Matches a character for which the standard C function `isxdigit()` returns a non-zero value (`[0-9A-Fa-f]`). | + +### `char/unicode_general_category.peg` + +#### Synopsis + +An import file that defines rules to match a Unicode character belonging to a specific [general category](https://unicode.org/reports/tr44/#General_Category_Values). + +#### PEG Rules + +The following PEG rules are available. + +| Rule Name | Description | +| --- | --- | +| `Unicode_Uppercase_Letter` | Matches an uppercase letter. | +| `Unicode_Lowercase_Letter` | Matches a lowercase letter. | +| `Unicode_Titlecase_Letter` | Matches a digraph encoded as a single character, with the first part uppercase. | +| `Unicode_Cased_Letter` | Matches a cased letter (= `Unicode_Uppercase_Letter / Unicode_Lowercase_Letter / Unicode_Titlecase_Letter`). | +| `Unicode_Modifier_Letter` | Matches a modifier letter. | +| `Unicode_Other_Letter` | Matches a letter of other type, including syllables and ideographs. | +| `Unicode_Letter` | Matches a letter (= `Unicode_Cased_Letter / Unicode_Modifier_Letter / Unicode_Other_Letter`). | +| `Unicode_Nonspacing_Mark` | Matches a nonspacing combining mark (zero advance width). | +| `Unicode_Spacing_Mark` | Matches a spacing combining mark (positive advance width). | +| `Unicode_Enclosing_Mark` | Matches an enclosing combining mark. | +| `Unicode_Mark` | Matches a mark (= `Unicode_Nonspacing_Mark / Unicode_Spacing_Mark / Unicode_Enclosing_Mark`). | +| `Unicode_Decimal_Number` | Matches a decimal digit. | +| `Unicode_Letter_Number` | Matches a letterlike numeric character. | +| `Unicode_Other_Number` | Matches a numeric character of other type. | +| `Unicode_Number` | Matches a numeric character (= `Unicode_Decimal_Number / Unicode_Letter_Number / Unicode_Other_Number`). | +| `Unicode_Connector_Punctuation` | Matches a connecting punctuation mark, like a tie. | +| `Unicode_Dash_Punctuation` | Matches a dash or hyphen punctuation mark. | +| `Unicode_Open_Punctuation` | Matches an opening punctuation mark (of a pair). | +| `Unicode_Close_Punctuation` | Matches a closing punctuation mark (of a pair). | +| `Unicode_Initial_Punctuation` | Matches an initial quotation mark. | +| `Unicode_Final_Punctuation` | Matches a final quotation mark. | +| `Unicode_Other_Punctuation` | Matches a punctuation mark of other type. | +| `Unicode_Punctuation` | Matches a punctuation mark (= `Unicode_Connector_Punctuation / Unicode_Dash_Punctuation / Unicode_Open_Punctuation / Unicode_Close_Punctuation / Unicode_Initial_Punctuation / Unicode_Final_Punctuation / Unicode_Other_Punctuation`). | +| `Unicode_Math_Symbol` | Matches a symbol of mathematical use. | +| `Unicode_Currency_Symbol` | Matches a currency sign. | +| `Unicode_Modifier_Symbol` | Matches a non-letterlike modifier symbol. | +| `Unicode_Other_Symbol` | Matches a symbol of other type. | +| `Unicode_Symbol` | Matches a symbol (= `Unicode_Math_Symbol / Unicode_Currency_Symbol / Unicode_Modifier_Symbol / Unicode_Other_Symbol`). | +| `Unicode_Space_Separator` | Matches a space character (of various non-zero widths). | +| `Unicode_Line_Separator` | Matches U+2028 "LINE SEPARATOR" only. | +| `Unicode_Paragraph_Separator` | Matches U+2029 "PARAGRAPH SEPARATOR" only. | +| `Unicode_Separator` | Matches a space character (= `Unicode_Space_Separator / Unicode_Line_Separator / Unicode_Paragraph_Separator`). | +| `Unicode_Control` | Matches a [C0](https://www.unicode.org/charts/nameslist/n_0000.html) or [C1](https://www.unicode.org/charts/nameslist/n_0080.html) control code. | +| `Unicode_Format` | Matches a format control character. | +| `Unicode_Surrogate` | Matches a surrogate code point. | +| `Unicode_Private_Use` | Matches a private-use character. | +| `Unicode_Other` | Matches a character of other type (= `Unicode_Control / Unicode_Format / Unicode_Surrogate / Unicode_Private_Use`). | + +### `char/unicode_derived_core.peg` + +#### Synopsis + +An import file that defines rules to match a Unicode character belonging to a specific [derived core property](https://www.unicode.org/reports/tr44/#DerivedCoreProperties.txt). + +#### PEG Rules + +The following PEG rules are available. + +| Rule Name | Description | +| --- | --- | +| `Unicode_Lowercase` | Matches a character with the Lowercase property. | +| `Unicode_Uppercase` | Matches a character with the Uppercase property. | +| `Unicode_Cased` | Matches a character which is considered to be either uppercase, lowercase or titlecase characters. | +| `Unicode_Case_Ignorable` | Matches a character which is ignored for casing purposes. | +| `Unicode_Changes_When_Lowercased` | Matches a character whose normalized form is not stable under a toLowercase mapping. | +| `Unicode_Changes_When_Uppercased` | Matches a character whose normalized form is not stable under a toUppercase mapping. | +| `Unicode_Changes_When_Titlecased` | Matches a character whose normalized form is not stable under a toTitlecase mapping. | +| `Unicode_Changes_When_Casefolded` | Matches a character whose normalized form is not stable under case folding. | +| `Unicode_Changes_When_Casemapped` | Matches a character which may change when it undergoes case mapping. | +| `Unicode_Alphabetic` | Matches a character with the Alphabetic property. | +| `Unicode_Default_Ignorable_Code_Point` | Matches a character which should be ignored in rendering unless explicitly supported by programs. | +| `Unicode_Grapheme_Base` | Matches a character with the property used to define "Grapheme base". | +| `Unicode_Grapheme_Extend` | Matches a character with the property used to define "Grapheme extender". | +| `Unicode_Math` | Matches a character with the Math property. | +| `Unicode_ID_Start` | Matches a character which may be used as the first letter of an identifier in a programming language. | +| `Unicode_ID_Continue` | Matches a character which may be used as the second and subsequent letters of an identifier in a programming language. | +| `Unicode_XID_Start` | Matches a character which can be mapped to a `Unicode_ID_Start` character under NFKC-normalization. | +| `Unicode_XID_Continue` | Matches a character which can be mapped to a `Unicode_ID_Continue` character under NFKC-normalization. | diff --git a/src/subprojects/packcc/import/char/ascii_character_group.peg b/src/subprojects/packcc/import/char/ascii_character_group.peg new file mode 100644 index 00000000..03477403 --- /dev/null +++ b/src/subprojects/packcc/import/char/ascii_character_group.peg @@ -0,0 +1,35 @@ +# This file is hereby placed in the public domain. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AS IS AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ASCII_Printable_Character <- ASCII_Special_Character / ASCII_Number / ASCII_Letter +ASCII_Letter <- ASCII_Uppercase_Letter / ASCII_Lowercase_Letter + +ASCII_Control_Character <- [\x00-\x1f\x7f] +ASCII_Special_Character <- [\x20-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e] +ASCII_Number <- [0-9] +ASCII_Uppercase_Letter <- [A-Z] +ASCII_Lowercase_Letter <- [a-z] + +ASCII_C_alnum <- [0-9A-Za-z] +ASCII_C_alpha <- [A-Za-z] +ASCII_C_blank <- [ \t] +ASCII_C_cntrl <- [\x00-\x1f\x7f] +ASCII_C_digit <- [0-9] +ASCII_C_graph <- [\x21-\x7e] +ASCII_C_lower <- [a-z] +ASCII_C_print <- [\x20-\x7e] +ASCII_C_punct <- [\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e] +ASCII_C_space <- [ \t\n\v\f\r] +ASCII_C_upper <- [A-Z] +ASCII_C_xdigit <- [0-9A-Fa-f] diff --git a/src/subprojects/packcc/import/char/unicode_derived_core.peg b/src/subprojects/packcc/import/char/unicode_derived_core.peg new file mode 100644 index 00000000..5bfdf0ac --- /dev/null +++ b/src/subprojects/packcc/import/char/unicode_derived_core.peg @@ -0,0 +1,34 @@ +# This file was generated using the script 'unicode_derived_core.py'. + +# This file is hereby placed in the public domain. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AS IS AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Unicode_Math <- [\u002b\u003c-\u003e\u005e\u007c\u007e\u00ac\u00b1\u00d7\u00f7\u03d0-\u03d2\u03d5\u03f0-\u03f1\u03f4-\u03f6\u0606-\u0608\u2016\u2032-\u2034\u2040\u2044\u2052\u2061-\u2064\u207a-\u207e\u208a-\u208e\u20d0-\u20dc\u20e1\u20e5-\u20e6\u20eb-\u20ef\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2128-\u2129\u212c-\u212d\u212f-\u2131\u2133-\u2138\u213c-\u2149\u214b\u2190-\u21a7\u21a9-\u21ae\u21b0-\u21b1\u21b6-\u21b7\u21bc-\u21db\u21dd\u21e4-\u21e5\u21f4-\u22ff\u2308-\u230b\u2320-\u2321\u237c\u239b-\u23b5\u23b7\u23d0\u23dc-\u23e2\u25a0-\u25a1\u25ae-\u25b7\u25bc-\u25c1\u25c6-\u25c7\u25ca-\u25cb\u25cf-\u25d3\u25e2\u25e4\u25e7-\u25ec\u25f8-\u25ff\u2605-\u2606\u2640\u2642\u2660-\u2663\u266d-\u266f\u27c0-\u27ff\u2900-\u2aff\u2b30-\u2b44\u2b47-\u2b4c\ufb29\ufe61-\ufe66\ufe68\uff0b\uff1c-\uff1e\uff3c\uff3e\uff5c\uff5e\uffe2\uffe9-\uffec\ud803\udd8e-\ud803\udd8f\ud835\udc00-\ud835\udc54\ud835\udc56-\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd1e-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd52-\ud835\udea5\ud835\udea8-\ud835\udfcb\ud835\udfce-\ud835\udfff\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21-\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51-\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61-\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb\ud83b\udef0-\ud83b\udef1] +Unicode_Alphabetic <- [\u0041-\u005a\u0061-\u007a\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0345\u0363-\u0374\u0376-\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05b0-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u05d0-\u05ea\u05ef-\u05f2\u0610-\u061a\u0620-\u0657\u0659-\u065f\u066e-\u06d3\u06d5-\u06dc\u06e1-\u06e8\u06ed-\u06ef\u06fa-\u06fc\u06ff\u0710-\u073f\u074d-\u07b1\u07ca-\u07ea\u07f4-\u07f5\u07fa\u0800-\u0817\u081a-\u082c\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u0897\u08a0-\u08c9\u08d4-\u08df\u08e3-\u08e9\u08f0-\u093b\u093d-\u094c\u094e-\u0950\u0955-\u0963\u0971-\u0983\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd-\u09c4\u09c7-\u09c8\u09cb-\u09cc\u09ce\u09d7\u09dc-\u09dd\u09df-\u09e3\u09f0-\u09f1\u09fc\u0a01-\u0a03\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a3e-\u0a42\u0a47-\u0a48\u0a4b-\u0a4c\u0a51\u0a59-\u0a5c\u0a5e\u0a70-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acc\u0ad0\u0ae0-\u0ae3\u0af9-\u0afc\u0b01-\u0b03\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d-\u0b44\u0b47-\u0b48\u0b4b-\u0b4c\u0b56-\u0b57\u0b5c-\u0b5d\u0b5f-\u0b63\u0b71\u0b82-\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd0\u0bd7\u0c00-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4c\u0c55-\u0c56\u0c58-\u0c5a\u0c5d\u0c60-\u0c63\u0c80-\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccc\u0cd5-\u0cd6\u0cdd-\u0cde\u0ce0-\u0ce3\u0cf1-\u0cf3\u0d00-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4c\u0d4e\u0d54-\u0d57\u0d5f-\u0d63\u0d7a-\u0d7f\u0d81-\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2-\u0df3\u0e01-\u0e3a\u0e40-\u0e46\u0e4d\u0e81-\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ecd\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f71-\u0f83\u0f88-\u0f97\u0f99-\u0fbc\u1000-\u1036\u1038\u103b-\u103f\u1050-\u108f\u109a-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1713\u171f-\u1733\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772-\u1773\u1780-\u17b3\u17b6-\u17c8\u17d7\u17dc\u1820-\u1878\u1880-\u18aa\u18b0-\u18f5\u1900-\u191e\u1920-\u192b\u1930-\u1938\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a1b\u1a20-\u1a5e\u1a61-\u1a74\u1aa7\u1abf-\u1ac0\u1acc-\u1ace\u1b00-\u1b33\u1b35-\u1b43\u1b45-\u1b4c\u1b80-\u1ba9\u1bac-\u1baf\u1bba-\u1be5\u1be7-\u1bf1\u1c00-\u1c36\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5-\u1cf6\u1cfa\u1d00-\u1dbf\u1dd3-\u1df4\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u24b6-\u24e9\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a-\ua62b\ua640-\ua66e\ua674-\ua67b\ua67f-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0-\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua805\ua807-\ua827\ua840-\ua873\ua880-\ua8c3\ua8c5\ua8f2-\ua8f7\ua8fb\ua8fd-\ua8ff\ua90a-\ua92a\ua930-\ua952\ua960-\ua97c\ua980-\ua9b2\ua9b4-\ua9bf\ua9cf\ua9e0-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa36\uaa40-\uaa4d\uaa60-\uaa76\uaa7a-\uaabe\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf5\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabea\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\ud800\udc00-\ud800\udc0b\ud800\udc0d-\ud800\udc26\ud800\udc28-\ud800\udc3a\ud800\udc3c-\ud800\udc3d\ud800\udc3f-\ud800\udc4d\ud800\udc50-\ud800\udc5d\ud800\udc80-\ud800\udcfa\ud800\udd40-\ud800\udd74\ud800\ude80-\ud800\ude9c\ud800\udea0-\ud800\uded0\ud800\udf00-\ud800\udf1f\ud800\udf2d-\ud800\udf4a\ud800\udf50-\ud800\udf7a\ud800\udf80-\ud800\udf9d\ud800\udfa0-\ud800\udfc3\ud800\udfc8-\ud800\udfcf\ud800\udfd1-\ud800\udfd5\ud801\udc00-\ud801\udc9d\ud801\udcb0-\ud801\udcd3\ud801\udcd8-\ud801\udcfb\ud801\udd00-\ud801\udd27\ud801\udd30-\ud801\udd63\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud801\uddc0-\ud801\uddf3\ud801\ude00-\ud801\udf36\ud801\udf40-\ud801\udf55\ud801\udf60-\ud801\udf67\ud801\udf80-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud802\udc00-\ud802\udc05\ud802\udc08\ud802\udc0a-\ud802\udc35\ud802\udc37-\ud802\udc38\ud802\udc3c\ud802\udc3f-\ud802\udc55\ud802\udc60-\ud802\udc76\ud802\udc80-\ud802\udc9e\ud802\udce0-\ud802\udcf2\ud802\udcf4-\ud802\udcf5\ud802\udd00-\ud802\udd15\ud802\udd20-\ud802\udd39\ud802\udd80-\ud802\uddb7\ud802\uddbe-\ud802\uddbf\ud802\ude00-\ud802\ude03\ud802\ude05-\ud802\ude06\ud802\ude0c-\ud802\ude13\ud802\ude15-\ud802\ude17\ud802\ude19-\ud802\ude35\ud802\ude60-\ud802\ude7c\ud802\ude80-\ud802\ude9c\ud802\udec0-\ud802\udec7\ud802\udec9-\ud802\udee4\ud802\udf00-\ud802\udf35\ud802\udf40-\ud802\udf55\ud802\udf60-\ud802\udf72\ud802\udf80-\ud802\udf91\ud803\udc00-\ud803\udc48\ud803\udc80-\ud803\udcb2\ud803\udcc0-\ud803\udcf2\ud803\udd00-\ud803\udd27\ud803\udd4a-\ud803\udd65\ud803\udd69\ud803\udd6f-\ud803\udd85\ud803\ude80-\ud803\udea9\ud803\udeab-\ud803\udeac\ud803\udeb0-\ud803\udeb1\ud803\udec2-\ud803\udec4\ud803\udefc\ud803\udf00-\ud803\udf1c\ud803\udf27\ud803\udf30-\ud803\udf45\ud803\udf70-\ud803\udf81\ud803\udfb0-\ud803\udfc4\ud803\udfe0-\ud803\udff6\ud804\udc00-\ud804\udc45\ud804\udc71-\ud804\udc75\ud804\udc80-\ud804\udcb8\ud804\udcc2\ud804\udcd0-\ud804\udce8\ud804\udd00-\ud804\udd32\ud804\udd44-\ud804\udd47\ud804\udd50-\ud804\udd72\ud804\udd76\ud804\udd80-\ud804\uddbf\ud804\uddc1-\ud804\uddc4\ud804\uddce-\ud804\uddcf\ud804\uddda\ud804\udddc\ud804\ude00-\ud804\ude11\ud804\ude13-\ud804\ude34\ud804\ude37\ud804\ude3e-\ud804\ude41\ud804\ude80-\ud804\ude86\ud804\ude88\ud804\ude8a-\ud804\ude8d\ud804\ude8f-\ud804\ude9d\ud804\ude9f-\ud804\udea8\ud804\udeb0-\ud804\udee8\ud804\udf00-\ud804\udf03\ud804\udf05-\ud804\udf0c\ud804\udf0f-\ud804\udf10\ud804\udf13-\ud804\udf28\ud804\udf2a-\ud804\udf30\ud804\udf32-\ud804\udf33\ud804\udf35-\ud804\udf39\ud804\udf3d-\ud804\udf44\ud804\udf47-\ud804\udf48\ud804\udf4b-\ud804\udf4c\ud804\udf50\ud804\udf57\ud804\udf5d-\ud804\udf63\ud804\udf80-\ud804\udf89\ud804\udf8b\ud804\udf8e\ud804\udf90-\ud804\udfb5\ud804\udfb7-\ud804\udfc0\ud804\udfc2\ud804\udfc5\ud804\udfc7-\ud804\udfca\ud804\udfcc-\ud804\udfcd\ud804\udfd1\ud804\udfd3\ud805\udc00-\ud805\udc41\ud805\udc43-\ud805\udc45\ud805\udc47-\ud805\udc4a\ud805\udc5f-\ud805\udc61\ud805\udc80-\ud805\udcc1\ud805\udcc4-\ud805\udcc5\ud805\udcc7\ud805\udd80-\ud805\uddb5\ud805\uddb8-\ud805\uddbe\ud805\uddd8-\ud805\udddd\ud805\ude00-\ud805\ude3e\ud805\ude40\ud805\ude44\ud805\ude80-\ud805\udeb5\ud805\udeb8\ud805\udf00-\ud805\udf1a\ud805\udf1d-\ud805\udf2a\ud805\udf40-\ud805\udf46\ud806\udc00-\ud806\udc38\ud806\udca0-\ud806\udcdf\ud806\udcff-\ud806\udd06\ud806\udd09\ud806\udd0c-\ud806\udd13\ud806\udd15-\ud806\udd16\ud806\udd18-\ud806\udd35\ud806\udd37-\ud806\udd38\ud806\udd3b-\ud806\udd3c\ud806\udd3f-\ud806\udd42\ud806\udda0-\ud806\udda7\ud806\uddaa-\ud806\uddd7\ud806\uddda-\ud806\udddf\ud806\udde1\ud806\udde3-\ud806\udde4\ud806\ude00-\ud806\ude32\ud806\ude35-\ud806\ude3e\ud806\ude50-\ud806\ude97\ud806\ude9d\ud806\udeb0-\ud806\udef8\ud806\udfc0-\ud806\udfe0\ud807\udc00-\ud807\udc08\ud807\udc0a-\ud807\udc36\ud807\udc38-\ud807\udc3e\ud807\udc40\ud807\udc72-\ud807\udc8f\ud807\udc92-\ud807\udca7\ud807\udca9-\ud807\udcb6\ud807\udd00-\ud807\udd06\ud807\udd08-\ud807\udd09\ud807\udd0b-\ud807\udd36\ud807\udd3a\ud807\udd3c-\ud807\udd3d\ud807\udd3f-\ud807\udd41\ud807\udd43\ud807\udd46-\ud807\udd47\ud807\udd60-\ud807\udd65\ud807\udd67-\ud807\udd68\ud807\udd6a-\ud807\udd8e\ud807\udd90-\ud807\udd91\ud807\udd93-\ud807\udd96\ud807\udd98\ud807\udee0-\ud807\udef6\ud807\udf00-\ud807\udf10\ud807\udf12-\ud807\udf3a\ud807\udf3e-\ud807\udf40\ud807\udfb0\ud808\udc00-\ud808\udf99\ud809\udc00-\ud809\udc6e\ud809\udc80-\ud809\udd43\ud80b\udf90-\ud80b\udff0\ud80c\udc00-\ud80d\udc2f\ud80d\udc41-\ud80d\udc46\ud80d\udc60-\ud810\udffa\ud811\udc00-\ud811\ude46\ud818\udd00-\ud818\udd2e\ud81a\udc00-\ud81a\ude38\ud81a\ude40-\ud81a\ude5e\ud81a\ude70-\ud81a\udebe\ud81a\uded0-\ud81a\udeed\ud81a\udf00-\ud81a\udf2f\ud81a\udf40-\ud81a\udf43\ud81a\udf63-\ud81a\udf77\ud81a\udf7d-\ud81a\udf8f\ud81b\udd40-\ud81b\udd6c\ud81b\ude40-\ud81b\ude7f\ud81b\udf00-\ud81b\udf4a\ud81b\udf4f-\ud81b\udf87\ud81b\udf8f-\ud81b\udf9f\ud81b\udfe0-\ud81b\udfe1\ud81b\udfe3\ud81b\udff0-\ud81b\udff1\ud81c\udc00-\ud821\udff7\ud822\udc00-\ud823\udcd5\ud823\udcff-\ud823\udd08\ud82b\udff0-\ud82b\udff3\ud82b\udff5-\ud82b\udffb\ud82b\udffd-\ud82b\udffe\ud82c\udc00-\ud82c\udd22\ud82c\udd32\ud82c\udd50-\ud82c\udd52\ud82c\udd55\ud82c\udd64-\ud82c\udd67\ud82c\udd70-\ud82c\udefb\ud82f\udc00-\ud82f\udc6a\ud82f\udc70-\ud82f\udc7c\ud82f\udc80-\ud82f\udc88\ud82f\udc90-\ud82f\udc99\ud82f\udc9e\ud835\udc00-\ud835\udc54\ud835\udc56-\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd1e-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd52-\ud835\udea5\ud835\udea8-\ud835\udec0\ud835\udec2-\ud835\udeda\ud835\udedc-\ud835\udefa\ud835\udefc-\ud835\udf14\ud835\udf16-\ud835\udf34\ud835\udf36-\ud835\udf4e\ud835\udf50-\ud835\udf6e\ud835\udf70-\ud835\udf88\ud835\udf8a-\ud835\udfa8\ud835\udfaa-\ud835\udfc2\ud835\udfc4-\ud835\udfcb\ud837\udf00-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud838\udc00-\ud838\udc06\ud838\udc08-\ud838\udc18\ud838\udc1b-\ud838\udc21\ud838\udc23-\ud838\udc24\ud838\udc26-\ud838\udc2a\ud838\udc30-\ud838\udc6d\ud838\udc8f\ud838\udd00-\ud838\udd2c\ud838\udd37-\ud838\udd3d\ud838\udd4e\ud838\ude90-\ud838\udead\ud838\udec0-\ud838\udeeb\ud839\udcd0-\ud839\udceb\ud839\uddd0-\ud839\udded\ud839\uddf0\ud839\udfe0-\ud839\udfe6\ud839\udfe8-\ud839\udfeb\ud839\udfed-\ud839\udfee\ud839\udff0-\ud839\udffe\ud83a\udc00-\ud83a\udcc4\ud83a\udd00-\ud83a\udd43\ud83a\udd47\ud83a\udd4b\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21-\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51-\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61-\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb\ud83c\udd30-\ud83c\udd49\ud83c\udd50-\ud83c\udd69\ud83c\udd70-\ud83c\udd89\ud840\udc00-\ud869\udedf\ud869\udf00-\ud86d\udf39\ud86d\udf40-\ud86e\udc1d\ud86e\udc20-\ud873\udea1\ud873\udeb0-\ud87a\udfe0\ud87a\udff0-\ud87b\ude5d\ud87e\udc00-\ud87e\ude1d\ud880\udc00-\ud884\udf4a\ud884\udf50-\ud888\udfaf] +Unicode_Lowercase <- [\u0061-\u007a\u00aa\u00b5\u00ba\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02b8\u02c0-\u02c1\u02e0-\u02e4\u0345\u0371\u0373\u0377\u037a-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0529\u052b\u052d\u052f\u0560-\u0588\u10d0-\u10fa\u10fc-\u10ff\u13f8-\u13fd\u1c80-\u1c88\u1c8a\u1d00-\u1dbf\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u2071\u207f\u2090-\u209c\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2170-\u217f\u2184\u24d0-\u24e9\u2c30-\u2c5f\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7d\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua699\ua69b-\ua69d\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793-\ua795\ua797\ua799\ua79b\ua79d\ua79f\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7af\ua7b5\ua7b7\ua7b9\ua7bb\ua7bd\ua7bf\ua7c1\ua7c3\ua7c8\ua7ca\ua7cd\ua7d1\ua7d3\ua7d5\ua7d7\ua7d9\ua7db\ua7f2-\ua7f4\ua7f6\ua7f8-\ua7fa\uab30-\uab5a\uab5c-\uab69\uab70-\uabbf\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\ud801\udc28-\ud801\udc4f\ud801\udcd8-\ud801\udcfb\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud801\udf80\ud801\udf83-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud803\udcc0-\ud803\udcf2\ud803\udd70-\ud803\udd85\ud806\udcc0-\ud806\udcdf\ud81b\ude60-\ud81b\ude7f\ud835\udc1a-\ud835\udc33\ud835\udc4e-\ud835\udc54\ud835\udc56-\ud835\udc67\ud835\udc82-\ud835\udc9b\ud835\udcb6-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udccf\ud835\udcea-\ud835\udd03\ud835\udd1e-\ud835\udd37\ud835\udd52-\ud835\udd6b\ud835\udd86-\ud835\udd9f\ud835\uddba-\ud835\uddd3\ud835\uddee-\ud835\ude07\ud835\ude22-\ud835\ude3b\ud835\ude56-\ud835\ude6f\ud835\ude8a-\ud835\udea5\ud835\udec2-\ud835\udeda\ud835\udedc-\ud835\udee1\ud835\udefc-\ud835\udf14\ud835\udf16-\ud835\udf1b\ud835\udf36-\ud835\udf4e\ud835\udf50-\ud835\udf55\ud835\udf70-\ud835\udf88\ud835\udf8a-\ud835\udf8f\ud835\udfaa-\ud835\udfc2\ud835\udfc4-\ud835\udfc9\ud835\udfcb\ud837\udf00-\ud837\udf09\ud837\udf0b-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud838\udc30-\ud838\udc6d\ud83a\udd22-\ud83a\udd43] +Unicode_Uppercase <- [\u0041-\u005a\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u037f\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0528\u052a\u052c\u052e\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u13a0-\u13f5\u1c89\u1c90-\u1cba\u1cbd-\u1cbf\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2160-\u216f\u2183\u24b6-\u24cf\u2c00-\u2c2f\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua698\ua69a\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua796\ua798\ua79a\ua79c\ua79e\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa-\ua7ae\ua7b0-\ua7b4\ua7b6\ua7b8\ua7ba\ua7bc\ua7be\ua7c0\ua7c2\ua7c4-\ua7c7\ua7c9\ua7cb-\ua7cc\ua7d0\ua7d6\ua7d8\ua7da\ua7dc\ua7f5\uff21-\uff3a\ud801\udc00-\ud801\udc27\ud801\udcb0-\ud801\udcd3\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud803\udc80-\ud803\udcb2\ud803\udd50-\ud803\udd65\ud806\udca0-\ud806\udcbf\ud81b\ude40-\ud81b\ude5f\ud835\udc00-\ud835\udc19\ud835\udc34-\ud835\udc4d\ud835\udc68-\ud835\udc81\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb5\ud835\udcd0-\ud835\udce9\ud835\udd04-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd38-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd6c-\ud835\udd85\ud835\udda0-\ud835\uddb9\ud835\uddd4-\ud835\udded\ud835\ude08-\ud835\ude21\ud835\ude3c-\ud835\ude55\ud835\ude70-\ud835\ude89\ud835\udea8-\ud835\udec0\ud835\udee2-\ud835\udefa\ud835\udf1c-\ud835\udf34\ud835\udf56-\ud835\udf6e\ud835\udf90-\ud835\udfa8\ud835\udfca\ud83a\udd00-\ud83a\udd21\ud83c\udd30-\ud83c\udd49\ud83c\udd50-\ud83c\udd69\ud83c\udd70-\ud83c\udd89] +Unicode_Cased <- [\u0041-\u005a\u0061-\u007a\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u01ba\u01bc-\u01bf\u01c4-\u0293\u0295-\u02b8\u02c0-\u02c1\u02e0-\u02e4\u0345\u0370-\u0373\u0376-\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0560-\u0588\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u10ff\u13a0-\u13f5\u13f8-\u13fd\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2134\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u217f\u2183-\u2184\u24b6-\u24e9\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua640-\ua66d\ua680-\ua69d\ua722-\ua787\ua78b-\ua78e\ua790-\ua7cd\ua7d0-\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua7f6\ua7f8-\ua7fa\uab30-\uab5a\uab5c-\uab69\uab70-\uabbf\ufb00-\ufb06\ufb13-\ufb17\uff21-\uff3a\uff41-\uff5a\ud801\udc00-\ud801\udc4f\ud801\udcb0-\ud801\udcd3\ud801\udcd8-\ud801\udcfb\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud801\udf80\ud801\udf83-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud803\udc80-\ud803\udcb2\ud803\udcc0-\ud803\udcf2\ud803\udd50-\ud803\udd65\ud803\udd70-\ud803\udd85\ud806\udca0-\ud806\udcdf\ud81b\ude40-\ud81b\ude7f\ud835\udc00-\ud835\udc54\ud835\udc56-\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd1e-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd52-\ud835\udea5\ud835\udea8-\ud835\udec0\ud835\udec2-\ud835\udeda\ud835\udedc-\ud835\udefa\ud835\udefc-\ud835\udf14\ud835\udf16-\ud835\udf34\ud835\udf36-\ud835\udf4e\ud835\udf50-\ud835\udf6e\ud835\udf70-\ud835\udf88\ud835\udf8a-\ud835\udfa8\ud835\udfaa-\ud835\udfc2\ud835\udfc4-\ud835\udfcb\ud837\udf00-\ud837\udf09\ud837\udf0b-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud838\udc30-\ud838\udc6d\ud83a\udd00-\ud83a\udd43\ud83c\udd30-\ud83c\udd49\ud83c\udd50-\ud83c\udd69\ud83c\udd70-\ud83c\udd89] +Unicode_Case_Ignorable <- [\u0027\u002e\u003a\u005e\u0060\u00a8\u00ad\u00af\u00b4\u00b7-\u00b8\u02b0-\u036f\u0374-\u0375\u037a\u0384-\u0385\u0387\u0483-\u0489\u0559\u055f\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u05f4\u0600-\u0605\u0610-\u061a\u061c\u0640\u064b-\u065f\u0670\u06d6-\u06dd\u06df-\u06e8\u06ea-\u06ed\u070f\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f5\u07fa\u07fd\u0816-\u082d\u0859-\u085b\u0888\u0890-\u0891\u0897-\u089f\u08c9-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0971\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2-\u09e3\u09fe\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0afa-\u0aff\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b55-\u0b56\u0b62-\u0b63\u0b82\u0bc0\u0bcd\u0c00\u0c04\u0c3c\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc6\u0ccc-\u0ccd\u0ce2-\u0ce3\u0d00-\u0d01\u0d3b-\u0d3c\u0d41-\u0d44\u0d4d\u0d62-\u0d63\u0d81\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e46-\u0e4e\u0eb1\u0eb4-\u0ebc\u0ec6\u0ec8-\u0ece\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u10fc\u135d-\u135f\u1712-\u1714\u1732-\u1733\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17d7\u17dd\u180b-\u180f\u1843\u1885-\u1886\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1aa7\u1ab0-\u1ace\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1c78-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9\u1d2c-\u1d6a\u1d78\u1d9b-\u1dff\u1fbd\u1fbf-\u1fc1\u1fcd-\u1fcf\u1fdd-\u1fdf\u1fed-\u1fef\u1ffd-\u1ffe\u200b-\u200f\u2018-\u2019\u2024\u2027\u202a-\u202e\u2060-\u2064\u2066-\u206f\u2071\u207f\u2090-\u209c\u20d0-\u20f0\u2c7c-\u2c7d\u2cef-\u2cf1\u2d6f\u2d7f\u2de0-\u2dff\u2e2f\u3005\u302a-\u302d\u3031-\u3035\u303b\u3099-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua66f-\ua672\ua674-\ua67d\ua67f\ua69c-\ua69f\ua6f0-\ua6f1\ua700-\ua721\ua770\ua788-\ua78a\ua7f2-\ua7f4\ua7f8-\ua7f9\ua802\ua806\ua80b\ua825-\ua826\ua82c\ua8c4-\ua8c5\ua8e0-\ua8f1\ua8ff\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc-\ua9bd\ua9cf\ua9e5-\ua9e6\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa70\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaadd\uaaec-\uaaed\uaaf3-\uaaf4\uaaf6\uab5b-\uab5f\uab69-\uab6b\uabe5\uabe8\uabed\ufb1e\ufbb2-\ufbc2\ufe00-\ufe0f\ufe13\ufe20-\ufe2f\ufe52\ufe55\ufeff\uff07\uff0e\uff1a\uff3e\uff40\uff70\uff9e-\uff9f\uffe3\ufff9-\ufffb\ud800\uddfd\ud800\udee0\ud800\udf76-\ud800\udf7a\ud801\udf80-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud802\ude01-\ud802\ude03\ud802\ude05-\ud802\ude06\ud802\ude0c-\ud802\ude0f\ud802\ude38-\ud802\ude3a\ud802\ude3f\ud802\udee5-\ud802\udee6\ud803\udd24-\ud803\udd27\ud803\udd4e\ud803\udd69-\ud803\udd6d\ud803\udd6f\ud803\udeab-\ud803\udeac\ud803\udefc-\ud803\udeff\ud803\udf46-\ud803\udf50\ud803\udf82-\ud803\udf85\ud804\udc01\ud804\udc38-\ud804\udc46\ud804\udc70\ud804\udc73-\ud804\udc74\ud804\udc7f-\ud804\udc81\ud804\udcb3-\ud804\udcb6\ud804\udcb9-\ud804\udcba\ud804\udcbd\ud804\udcc2\ud804\udccd\ud804\udd00-\ud804\udd02\ud804\udd27-\ud804\udd2b\ud804\udd2d-\ud804\udd34\ud804\udd73\ud804\udd80-\ud804\udd81\ud804\uddb6-\ud804\uddbe\ud804\uddc9-\ud804\uddcc\ud804\uddcf\ud804\ude2f-\ud804\ude31\ud804\ude34\ud804\ude36-\ud804\ude37\ud804\ude3e\ud804\ude41\ud804\udedf\ud804\udee3-\ud804\udeea\ud804\udf00-\ud804\udf01\ud804\udf3b-\ud804\udf3c\ud804\udf40\ud804\udf66-\ud804\udf6c\ud804\udf70-\ud804\udf74\ud804\udfbb-\ud804\udfc0\ud804\udfce\ud804\udfd0\ud804\udfd2\ud804\udfe1-\ud804\udfe2\ud805\udc38-\ud805\udc3f\ud805\udc42-\ud805\udc44\ud805\udc46\ud805\udc5e\ud805\udcb3-\ud805\udcb8\ud805\udcba\ud805\udcbf-\ud805\udcc0\ud805\udcc2-\ud805\udcc3\ud805\uddb2-\ud805\uddb5\ud805\uddbc-\ud805\uddbd\ud805\uddbf-\ud805\uddc0\ud805\udddc-\ud805\udddd\ud805\ude33-\ud805\ude3a\ud805\ude3d\ud805\ude3f-\ud805\ude40\ud805\udeab\ud805\udead\ud805\udeb0-\ud805\udeb5\ud805\udeb7\ud805\udf1d\ud805\udf1f\ud805\udf22-\ud805\udf25\ud805\udf27-\ud805\udf2b\ud806\udc2f-\ud806\udc37\ud806\udc39-\ud806\udc3a\ud806\udd3b-\ud806\udd3c\ud806\udd3e\ud806\udd43\ud806\uddd4-\ud806\uddd7\ud806\uddda-\ud806\udddb\ud806\udde0\ud806\ude01-\ud806\ude0a\ud806\ude33-\ud806\ude38\ud806\ude3b-\ud806\ude3e\ud806\ude47\ud806\ude51-\ud806\ude56\ud806\ude59-\ud806\ude5b\ud806\ude8a-\ud806\ude96\ud806\ude98-\ud806\ude99\ud807\udc30-\ud807\udc36\ud807\udc38-\ud807\udc3d\ud807\udc3f\ud807\udc92-\ud807\udca7\ud807\udcaa-\ud807\udcb0\ud807\udcb2-\ud807\udcb3\ud807\udcb5-\ud807\udcb6\ud807\udd31-\ud807\udd36\ud807\udd3a\ud807\udd3c-\ud807\udd3d\ud807\udd3f-\ud807\udd45\ud807\udd47\ud807\udd90-\ud807\udd91\ud807\udd95\ud807\udd97\ud807\udef3-\ud807\udef4\ud807\udf00-\ud807\udf01\ud807\udf36-\ud807\udf3a\ud807\udf40\ud807\udf42\ud807\udf5a\ud80d\udc30-\ud80d\udc40\ud80d\udc47-\ud80d\udc55\ud818\udd1e-\ud818\udd29\ud818\udd2d-\ud818\udd2f\ud81a\udef0-\ud81a\udef4\ud81a\udf30-\ud81a\udf36\ud81a\udf40-\ud81a\udf43\ud81b\udd40-\ud81b\udd42\ud81b\udd6b-\ud81b\udd6c\ud81b\udf4f\ud81b\udf8f-\ud81b\udf9f\ud81b\udfe0-\ud81b\udfe1\ud81b\udfe3-\ud81b\udfe4\ud82b\udff0-\ud82b\udff3\ud82b\udff5-\ud82b\udffb\ud82b\udffd-\ud82b\udffe\ud82f\udc9d-\ud82f\udc9e\ud82f\udca0-\ud82f\udca3\ud833\udf00-\ud833\udf2d\ud833\udf30-\ud833\udf46\ud834\udd67-\ud834\udd69\ud834\udd73-\ud834\udd82\ud834\udd85-\ud834\udd8b\ud834\uddaa-\ud834\uddad\ud834\ude42-\ud834\ude44\ud836\ude00-\ud836\ude36\ud836\ude3b-\ud836\ude6c\ud836\ude75\ud836\ude84\ud836\ude9b-\ud836\ude9f\ud836\udea1-\ud836\udeaf\ud838\udc00-\ud838\udc06\ud838\udc08-\ud838\udc18\ud838\udc1b-\ud838\udc21\ud838\udc23-\ud838\udc24\ud838\udc26-\ud838\udc2a\ud838\udc30-\ud838\udc6d\ud838\udc8f\ud838\udd30-\ud838\udd3d\ud838\udeae\ud838\udeec-\ud838\udeef\ud839\udceb-\ud839\udcef\ud839\uddee-\ud839\uddef\ud83a\udcd0-\ud83a\udcd6\ud83a\udd44-\ud83a\udd4b\ud83c\udffb-\ud83c\udfff\udb40\udc01\udb40\udc20-\udb40\udc7f\udb40\udd00-\udb40\uddef] +Unicode_Changes_When_Lowercased <- [\u0041-\u005a\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4-\u01c5\u01c7-\u01c8\u01ca-\u01cb\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1-\u01f2\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u037f\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0528\u052a\u052c\u052e\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u13a0-\u13f5\u1c89\u1c90-\u1cba\u1cbd-\u1cbf\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fb8-\u1fbc\u1fc8-\u1fcc\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffc\u2126\u212a-\u212b\u2132\u2160-\u216f\u2183\u24b6-\u24cf\u2c00-\u2c2f\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua698\ua69a\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua796\ua798\ua79a\ua79c\ua79e\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa-\ua7ae\ua7b0-\ua7b4\ua7b6\ua7b8\ua7ba\ua7bc\ua7be\ua7c0\ua7c2\ua7c4-\ua7c7\ua7c9\ua7cb-\ua7cc\ua7d0\ua7d6\ua7d8\ua7da\ua7dc\ua7f5\uff21-\uff3a\ud801\udc00-\ud801\udc27\ud801\udcb0-\ud801\udcd3\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud803\udc80-\ud803\udcb2\ud803\udd50-\ud803\udd65\ud806\udca0-\ud806\udcbf\ud81b\ude40-\ud81b\ude5f\ud83a\udd00-\ud83a\udd21] +Unicode_Changes_When_Uppercased <- [\u0061-\u007a\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01ad\u01b0\u01b4\u01b6\u01b9\u01bd\u01bf\u01c5-\u01c6\u01c8-\u01c9\u01cb-\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f2-\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0254\u0256-\u0257\u0259\u025b-\u025c\u0260-\u0261\u0263-\u0266\u0268-\u026c\u026f\u0271-\u0272\u0275\u027d\u0280\u0282-\u0283\u0287-\u028c\u0292\u029d-\u029e\u0345\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0529\u052b\u052d\u052f\u0561-\u0587\u10d0-\u10fa\u10fd-\u10ff\u13f8-\u13fd\u1c80-\u1c88\u1c8a\u1d79\u1d7d\u1d8e\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9b\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fb7\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u1ffc\u214e\u2170-\u217f\u2184\u24d0-\u24e9\u2c30-\u2c5f\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c73\u2c76\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua699\ua69b\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua791\ua793-\ua794\ua797\ua799\ua79b\ua79d\ua79f\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7b5\ua7b7\ua7b9\ua7bb\ua7bd\ua7bf\ua7c1\ua7c3\ua7c8\ua7ca\ua7cd\ua7d1\ua7d7\ua7d9\ua7db\ua7f6\uab53\uab70-\uabbf\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\ud801\udc28-\ud801\udc4f\ud801\udcd8-\ud801\udcfb\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud803\udcc0-\ud803\udcf2\ud803\udd70-\ud803\udd85\ud806\udcc0-\ud806\udcdf\ud81b\ude60-\ud81b\ude7f\ud83a\udd22-\ud83a\udd43] +Unicode_Changes_When_Titlecased <- [\u0061-\u007a\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01ad\u01b0\u01b4\u01b6\u01b9\u01bd\u01bf\u01c4\u01c6-\u01c7\u01c9-\u01ca\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f1\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0254\u0256-\u0257\u0259\u025b-\u025c\u0260-\u0261\u0263-\u0266\u0268-\u026c\u026f\u0271-\u0272\u0275\u027d\u0280\u0282-\u0283\u0287-\u028c\u0292\u029d-\u029e\u0345\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0529\u052b\u052d\u052f\u0561-\u0587\u13f8-\u13fd\u1c80-\u1c88\u1c8a\u1d79\u1d7d\u1d8e\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9b\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u214e\u2170-\u217f\u2184\u24d0-\u24e9\u2c30-\u2c5f\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c73\u2c76\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua699\ua69b\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua791\ua793-\ua794\ua797\ua799\ua79b\ua79d\ua79f\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7b5\ua7b7\ua7b9\ua7bb\ua7bd\ua7bf\ua7c1\ua7c3\ua7c8\ua7ca\ua7cd\ua7d1\ua7d7\ua7d9\ua7db\ua7f6\uab53\uab70-\uabbf\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\ud801\udc28-\ud801\udc4f\ud801\udcd8-\ud801\udcfb\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud803\udcc0-\ud803\udcf2\ud803\udd70-\ud803\udd85\ud806\udcc0-\ud806\udcdf\ud81b\ude60-\ud81b\ude7f\ud83a\udd22-\ud83a\udd43] +Unicode_Changes_When_Casefolded <- [\u0041-\u005a\u00b5\u00c0-\u00d6\u00d8-\u00df\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u0149-\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u017f\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4-\u01c5\u01c7-\u01c8\u01ca-\u01cb\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1-\u01f2\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0345\u0370\u0372\u0376\u037f\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03c2\u03cf-\u03d1\u03d5-\u03d6\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f0-\u03f1\u03f4-\u03f5\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0528\u052a\u052c\u052e\u0531-\u0556\u0587\u10a0-\u10c5\u10c7\u10cd\u13f8-\u13fd\u1c80-\u1c89\u1c90-\u1cba\u1cbd-\u1cbf\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9a-\u1e9b\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1f80-\u1faf\u1fb2-\u1fb4\u1fb7-\u1fbc\u1fc2-\u1fc4\u1fc7-\u1fcc\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff2-\u1ff4\u1ff7-\u1ffc\u2126\u212a-\u212b\u2132\u2160-\u216f\u2183\u24b6-\u24cf\u2c00-\u2c2f\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua698\ua69a\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua796\ua798\ua79a\ua79c\ua79e\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa-\ua7ae\ua7b0-\ua7b4\ua7b6\ua7b8\ua7ba\ua7bc\ua7be\ua7c0\ua7c2\ua7c4-\ua7c7\ua7c9\ua7cb-\ua7cc\ua7d0\ua7d6\ua7d8\ua7da\ua7dc\ua7f5\uab70-\uabbf\ufb00-\ufb06\ufb13-\ufb17\uff21-\uff3a\ud801\udc00-\ud801\udc27\ud801\udcb0-\ud801\udcd3\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud803\udc80-\ud803\udcb2\ud803\udd50-\ud803\udd65\ud806\udca0-\ud806\udcbf\ud81b\ude40-\ud81b\ude5f\ud83a\udd00-\ud83a\udd21] +Unicode_Changes_When_Casemapped <- [\u0041-\u005a\u0061-\u007a\u00b5\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u0137\u0139-\u018c\u018e-\u01a9\u01ac-\u01b9\u01bc-\u01bd\u01bf\u01c4-\u0220\u0222-\u0233\u023a-\u0254\u0256-\u0257\u0259\u025b-\u025c\u0260-\u0261\u0263-\u0266\u0268-\u026c\u026f\u0271-\u0272\u0275\u027d\u0280\u0282-\u0283\u0287-\u028c\u0292\u029d-\u029e\u0345\u0370-\u0373\u0376-\u0377\u037b-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03d1\u03d5-\u03f5\u03f7-\u03fb\u03fd-\u0481\u048a-\u052f\u0531-\u0556\u0561-\u0587\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fd-\u10ff\u13a0-\u13f5\u13f8-\u13fd\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1d79\u1d7d\u1d8e\u1e00-\u1e9b\u1e9e\u1ea0-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2126\u212a-\u212b\u2132\u214e\u2160-\u217f\u2183-\u2184\u24b6-\u24e9\u2c00-\u2c70\u2c72-\u2c73\u2c75-\u2c76\u2c7e-\u2ce3\u2ceb-\u2cee\u2cf2-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua640-\ua66d\ua680-\ua69b\ua722-\ua72f\ua732-\ua76f\ua779-\ua787\ua78b-\ua78d\ua790-\ua794\ua796-\ua7ae\ua7b0-\ua7cd\ua7d0-\ua7d1\ua7d6-\ua7dc\ua7f5-\ua7f6\uab53\uab70-\uabbf\ufb00-\ufb06\ufb13-\ufb17\uff21-\uff3a\uff41-\uff5a\ud801\udc00-\ud801\udc4f\ud801\udcb0-\ud801\udcd3\ud801\udcd8-\ud801\udcfb\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud803\udc80-\ud803\udcb2\ud803\udcc0-\ud803\udcf2\ud803\udd50-\ud803\udd65\ud803\udd70-\ud803\udd85\ud806\udca0-\ud806\udcdf\ud81b\ude40-\ud81b\ude7f\ud83a\udd00-\ud83a\udd43] +Unicode_ID_Start <- [\u0041-\u005a\u0061-\u007a\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376-\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e-\u066f\u0671-\u06d3\u06d5\u06e5-\u06e6\u06ee-\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4-\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u09fc\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0-\u0ae1\u0af9\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60-\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd-\u0cde\u0ce0-\u0ce1\u0cf1-\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32-\u0e33\u0e40-\u0e46\u0e81-\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2-\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065-\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae-\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5-\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a-\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0-\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd-\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5-\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\ud800\udc00-\ud800\udc0b\ud800\udc0d-\ud800\udc26\ud800\udc28-\ud800\udc3a\ud800\udc3c-\ud800\udc3d\ud800\udc3f-\ud800\udc4d\ud800\udc50-\ud800\udc5d\ud800\udc80-\ud800\udcfa\ud800\udd40-\ud800\udd74\ud800\ude80-\ud800\ude9c\ud800\udea0-\ud800\uded0\ud800\udf00-\ud800\udf1f\ud800\udf2d-\ud800\udf4a\ud800\udf50-\ud800\udf75\ud800\udf80-\ud800\udf9d\ud800\udfa0-\ud800\udfc3\ud800\udfc8-\ud800\udfcf\ud800\udfd1-\ud800\udfd5\ud801\udc00-\ud801\udc9d\ud801\udcb0-\ud801\udcd3\ud801\udcd8-\ud801\udcfb\ud801\udd00-\ud801\udd27\ud801\udd30-\ud801\udd63\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud801\uddc0-\ud801\uddf3\ud801\ude00-\ud801\udf36\ud801\udf40-\ud801\udf55\ud801\udf60-\ud801\udf67\ud801\udf80-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud802\udc00-\ud802\udc05\ud802\udc08\ud802\udc0a-\ud802\udc35\ud802\udc37-\ud802\udc38\ud802\udc3c\ud802\udc3f-\ud802\udc55\ud802\udc60-\ud802\udc76\ud802\udc80-\ud802\udc9e\ud802\udce0-\ud802\udcf2\ud802\udcf4-\ud802\udcf5\ud802\udd00-\ud802\udd15\ud802\udd20-\ud802\udd39\ud802\udd80-\ud802\uddb7\ud802\uddbe-\ud802\uddbf\ud802\ude00\ud802\ude10-\ud802\ude13\ud802\ude15-\ud802\ude17\ud802\ude19-\ud802\ude35\ud802\ude60-\ud802\ude7c\ud802\ude80-\ud802\ude9c\ud802\udec0-\ud802\udec7\ud802\udec9-\ud802\udee4\ud802\udf00-\ud802\udf35\ud802\udf40-\ud802\udf55\ud802\udf60-\ud802\udf72\ud802\udf80-\ud802\udf91\ud803\udc00-\ud803\udc48\ud803\udc80-\ud803\udcb2\ud803\udcc0-\ud803\udcf2\ud803\udd00-\ud803\udd23\ud803\udd4a-\ud803\udd65\ud803\udd6f-\ud803\udd85\ud803\ude80-\ud803\udea9\ud803\udeb0-\ud803\udeb1\ud803\udec2-\ud803\udec4\ud803\udf00-\ud803\udf1c\ud803\udf27\ud803\udf30-\ud803\udf45\ud803\udf70-\ud803\udf81\ud803\udfb0-\ud803\udfc4\ud803\udfe0-\ud803\udff6\ud804\udc03-\ud804\udc37\ud804\udc71-\ud804\udc72\ud804\udc75\ud804\udc83-\ud804\udcaf\ud804\udcd0-\ud804\udce8\ud804\udd03-\ud804\udd26\ud804\udd44\ud804\udd47\ud804\udd50-\ud804\udd72\ud804\udd76\ud804\udd83-\ud804\uddb2\ud804\uddc1-\ud804\uddc4\ud804\uddda\ud804\udddc\ud804\ude00-\ud804\ude11\ud804\ude13-\ud804\ude2b\ud804\ude3f-\ud804\ude40\ud804\ude80-\ud804\ude86\ud804\ude88\ud804\ude8a-\ud804\ude8d\ud804\ude8f-\ud804\ude9d\ud804\ude9f-\ud804\udea8\ud804\udeb0-\ud804\udede\ud804\udf05-\ud804\udf0c\ud804\udf0f-\ud804\udf10\ud804\udf13-\ud804\udf28\ud804\udf2a-\ud804\udf30\ud804\udf32-\ud804\udf33\ud804\udf35-\ud804\udf39\ud804\udf3d\ud804\udf50\ud804\udf5d-\ud804\udf61\ud804\udf80-\ud804\udf89\ud804\udf8b\ud804\udf8e\ud804\udf90-\ud804\udfb5\ud804\udfb7\ud804\udfd1\ud804\udfd3\ud805\udc00-\ud805\udc34\ud805\udc47-\ud805\udc4a\ud805\udc5f-\ud805\udc61\ud805\udc80-\ud805\udcaf\ud805\udcc4-\ud805\udcc5\ud805\udcc7\ud805\udd80-\ud805\uddae\ud805\uddd8-\ud805\udddb\ud805\ude00-\ud805\ude2f\ud805\ude44\ud805\ude80-\ud805\udeaa\ud805\udeb8\ud805\udf00-\ud805\udf1a\ud805\udf40-\ud805\udf46\ud806\udc00-\ud806\udc2b\ud806\udca0-\ud806\udcdf\ud806\udcff-\ud806\udd06\ud806\udd09\ud806\udd0c-\ud806\udd13\ud806\udd15-\ud806\udd16\ud806\udd18-\ud806\udd2f\ud806\udd3f\ud806\udd41\ud806\udda0-\ud806\udda7\ud806\uddaa-\ud806\uddd0\ud806\udde1\ud806\udde3\ud806\ude00\ud806\ude0b-\ud806\ude32\ud806\ude3a\ud806\ude50\ud806\ude5c-\ud806\ude89\ud806\ude9d\ud806\udeb0-\ud806\udef8\ud806\udfc0-\ud806\udfe0\ud807\udc00-\ud807\udc08\ud807\udc0a-\ud807\udc2e\ud807\udc40\ud807\udc72-\ud807\udc8f\ud807\udd00-\ud807\udd06\ud807\udd08-\ud807\udd09\ud807\udd0b-\ud807\udd30\ud807\udd46\ud807\udd60-\ud807\udd65\ud807\udd67-\ud807\udd68\ud807\udd6a-\ud807\udd89\ud807\udd98\ud807\udee0-\ud807\udef2\ud807\udf02\ud807\udf04-\ud807\udf10\ud807\udf12-\ud807\udf33\ud807\udfb0\ud808\udc00-\ud808\udf99\ud809\udc00-\ud809\udc6e\ud809\udc80-\ud809\udd43\ud80b\udf90-\ud80b\udff0\ud80c\udc00-\ud80d\udc2f\ud80d\udc41-\ud80d\udc46\ud80d\udc60-\ud810\udffa\ud811\udc00-\ud811\ude46\ud818\udd00-\ud818\udd1d\ud81a\udc00-\ud81a\ude38\ud81a\ude40-\ud81a\ude5e\ud81a\ude70-\ud81a\udebe\ud81a\uded0-\ud81a\udeed\ud81a\udf00-\ud81a\udf2f\ud81a\udf40-\ud81a\udf43\ud81a\udf63-\ud81a\udf77\ud81a\udf7d-\ud81a\udf8f\ud81b\udd40-\ud81b\udd6c\ud81b\ude40-\ud81b\ude7f\ud81b\udf00-\ud81b\udf4a\ud81b\udf50\ud81b\udf93-\ud81b\udf9f\ud81b\udfe0-\ud81b\udfe1\ud81b\udfe3\ud81c\udc00-\ud821\udff7\ud822\udc00-\ud823\udcd5\ud823\udcff-\ud823\udd08\ud82b\udff0-\ud82b\udff3\ud82b\udff5-\ud82b\udffb\ud82b\udffd-\ud82b\udffe\ud82c\udc00-\ud82c\udd22\ud82c\udd32\ud82c\udd50-\ud82c\udd52\ud82c\udd55\ud82c\udd64-\ud82c\udd67\ud82c\udd70-\ud82c\udefb\ud82f\udc00-\ud82f\udc6a\ud82f\udc70-\ud82f\udc7c\ud82f\udc80-\ud82f\udc88\ud82f\udc90-\ud82f\udc99\ud835\udc00-\ud835\udc54\ud835\udc56-\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd1e-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd52-\ud835\udea5\ud835\udea8-\ud835\udec0\ud835\udec2-\ud835\udeda\ud835\udedc-\ud835\udefa\ud835\udefc-\ud835\udf14\ud835\udf16-\ud835\udf34\ud835\udf36-\ud835\udf4e\ud835\udf50-\ud835\udf6e\ud835\udf70-\ud835\udf88\ud835\udf8a-\ud835\udfa8\ud835\udfaa-\ud835\udfc2\ud835\udfc4-\ud835\udfcb\ud837\udf00-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud838\udc30-\ud838\udc6d\ud838\udd00-\ud838\udd2c\ud838\udd37-\ud838\udd3d\ud838\udd4e\ud838\ude90-\ud838\udead\ud838\udec0-\ud838\udeeb\ud839\udcd0-\ud839\udceb\ud839\uddd0-\ud839\udded\ud839\uddf0\ud839\udfe0-\ud839\udfe6\ud839\udfe8-\ud839\udfeb\ud839\udfed-\ud839\udfee\ud839\udff0-\ud839\udffe\ud83a\udc00-\ud83a\udcc4\ud83a\udd00-\ud83a\udd43\ud83a\udd4b\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21-\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51-\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61-\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb\ud840\udc00-\ud869\udedf\ud869\udf00-\ud86d\udf39\ud86d\udf40-\ud86e\udc1d\ud86e\udc20-\ud873\udea1\ud873\udeb0-\ud87a\udfe0\ud87a\udff0-\ud87b\ude5d\ud87e\udc00-\ud87e\ude1d\ud880\udc00-\ud884\udf4a\ud884\udf50-\ud888\udfaf] +Unicode_ID_Continue <- [\u0030-\u0039\u0041-\u005a\u005f\u0061-\u007a\u00aa\u00b5\u00b7\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376-\u0377\u037a-\u037d\u037f\u0386-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u05d0-\u05ea\u05ef-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u07fd\u0800-\u082d\u0840-\u085b\u0860-\u086a\u0870-\u0887\u0889-\u088e\u0897-\u08e1\u08e3-\u0963\u0966-\u096f\u0971-\u0983\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7-\u09c8\u09cb-\u09ce\u09d7\u09dc-\u09dd\u09df-\u09e3\u09e6-\u09f1\u09fc\u09fe\u0a01-\u0a03\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a3c\u0a3e-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0af9-\u0aff\u0b01-\u0b03\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47-\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b5c-\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82-\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c00-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3c-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c58-\u0c5a\u0c5d\u0c60-\u0c63\u0c66-\u0c6f\u0c80-\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5-\u0cd6\u0cdd-\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1-\u0cf3\u0d00-\u0d0c\u0d0e-\u0d10\u0d12-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d54-\u0d57\u0d5f-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d81-\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2-\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81-\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ece\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18-\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1369-\u1371\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1715\u171f-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772-\u1773\u1780-\u17d3\u17d7\u17dc-\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u1820-\u1878\u1880-\u18aa\u18b0-\u18f5\u1900-\u191e\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19da\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b4c\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1cd0-\u1cd2\u1cd4-\u1cfa\u1d00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c-\u200d\u203f-\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099-\u309f\u30a1-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0-\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua827\ua82c\ua840-\ua873\ua880-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua8fd-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\ua9e0-\ua9fe\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabea\uabec-\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe2f\ufe33-\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff65-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\ud800\udc00-\ud800\udc0b\ud800\udc0d-\ud800\udc26\ud800\udc28-\ud800\udc3a\ud800\udc3c-\ud800\udc3d\ud800\udc3f-\ud800\udc4d\ud800\udc50-\ud800\udc5d\ud800\udc80-\ud800\udcfa\ud800\udd40-\ud800\udd74\ud800\uddfd\ud800\ude80-\ud800\ude9c\ud800\udea0-\ud800\uded0\ud800\udee0\ud800\udf00-\ud800\udf1f\ud800\udf2d-\ud800\udf4a\ud800\udf50-\ud800\udf7a\ud800\udf80-\ud800\udf9d\ud800\udfa0-\ud800\udfc3\ud800\udfc8-\ud800\udfcf\ud800\udfd1-\ud800\udfd5\ud801\udc00-\ud801\udc9d\ud801\udca0-\ud801\udca9\ud801\udcb0-\ud801\udcd3\ud801\udcd8-\ud801\udcfb\ud801\udd00-\ud801\udd27\ud801\udd30-\ud801\udd63\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud801\uddc0-\ud801\uddf3\ud801\ude00-\ud801\udf36\ud801\udf40-\ud801\udf55\ud801\udf60-\ud801\udf67\ud801\udf80-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud802\udc00-\ud802\udc05\ud802\udc08\ud802\udc0a-\ud802\udc35\ud802\udc37-\ud802\udc38\ud802\udc3c\ud802\udc3f-\ud802\udc55\ud802\udc60-\ud802\udc76\ud802\udc80-\ud802\udc9e\ud802\udce0-\ud802\udcf2\ud802\udcf4-\ud802\udcf5\ud802\udd00-\ud802\udd15\ud802\udd20-\ud802\udd39\ud802\udd80-\ud802\uddb7\ud802\uddbe-\ud802\uddbf\ud802\ude00-\ud802\ude03\ud802\ude05-\ud802\ude06\ud802\ude0c-\ud802\ude13\ud802\ude15-\ud802\ude17\ud802\ude19-\ud802\ude35\ud802\ude38-\ud802\ude3a\ud802\ude3f\ud802\ude60-\ud802\ude7c\ud802\ude80-\ud802\ude9c\ud802\udec0-\ud802\udec7\ud802\udec9-\ud802\udee6\ud802\udf00-\ud802\udf35\ud802\udf40-\ud802\udf55\ud802\udf60-\ud802\udf72\ud802\udf80-\ud802\udf91\ud803\udc00-\ud803\udc48\ud803\udc80-\ud803\udcb2\ud803\udcc0-\ud803\udcf2\ud803\udd00-\ud803\udd27\ud803\udd30-\ud803\udd39\ud803\udd40-\ud803\udd65\ud803\udd69-\ud803\udd6d\ud803\udd6f-\ud803\udd85\ud803\ude80-\ud803\udea9\ud803\udeab-\ud803\udeac\ud803\udeb0-\ud803\udeb1\ud803\udec2-\ud803\udec4\ud803\udefc-\ud803\udf1c\ud803\udf27\ud803\udf30-\ud803\udf50\ud803\udf70-\ud803\udf85\ud803\udfb0-\ud803\udfc4\ud803\udfe0-\ud803\udff6\ud804\udc00-\ud804\udc46\ud804\udc66-\ud804\udc75\ud804\udc7f-\ud804\udcba\ud804\udcc2\ud804\udcd0-\ud804\udce8\ud804\udcf0-\ud804\udcf9\ud804\udd00-\ud804\udd34\ud804\udd36-\ud804\udd3f\ud804\udd44-\ud804\udd47\ud804\udd50-\ud804\udd73\ud804\udd76\ud804\udd80-\ud804\uddc4\ud804\uddc9-\ud804\uddcc\ud804\uddce-\ud804\uddda\ud804\udddc\ud804\ude00-\ud804\ude11\ud804\ude13-\ud804\ude37\ud804\ude3e-\ud804\ude41\ud804\ude80-\ud804\ude86\ud804\ude88\ud804\ude8a-\ud804\ude8d\ud804\ude8f-\ud804\ude9d\ud804\ude9f-\ud804\udea8\ud804\udeb0-\ud804\udeea\ud804\udef0-\ud804\udef9\ud804\udf00-\ud804\udf03\ud804\udf05-\ud804\udf0c\ud804\udf0f-\ud804\udf10\ud804\udf13-\ud804\udf28\ud804\udf2a-\ud804\udf30\ud804\udf32-\ud804\udf33\ud804\udf35-\ud804\udf39\ud804\udf3b-\ud804\udf44\ud804\udf47-\ud804\udf48\ud804\udf4b-\ud804\udf4d\ud804\udf50\ud804\udf57\ud804\udf5d-\ud804\udf63\ud804\udf66-\ud804\udf6c\ud804\udf70-\ud804\udf74\ud804\udf80-\ud804\udf89\ud804\udf8b\ud804\udf8e\ud804\udf90-\ud804\udfb5\ud804\udfb7-\ud804\udfc0\ud804\udfc2\ud804\udfc5\ud804\udfc7-\ud804\udfca\ud804\udfcc-\ud804\udfd3\ud804\udfe1-\ud804\udfe2\ud805\udc00-\ud805\udc4a\ud805\udc50-\ud805\udc59\ud805\udc5e-\ud805\udc61\ud805\udc80-\ud805\udcc5\ud805\udcc7\ud805\udcd0-\ud805\udcd9\ud805\udd80-\ud805\uddb5\ud805\uddb8-\ud805\uddc0\ud805\uddd8-\ud805\udddd\ud805\ude00-\ud805\ude40\ud805\ude44\ud805\ude50-\ud805\ude59\ud805\ude80-\ud805\udeb8\ud805\udec0-\ud805\udec9\ud805\uded0-\ud805\udee3\ud805\udf00-\ud805\udf1a\ud805\udf1d-\ud805\udf2b\ud805\udf30-\ud805\udf39\ud805\udf40-\ud805\udf46\ud806\udc00-\ud806\udc3a\ud806\udca0-\ud806\udce9\ud806\udcff-\ud806\udd06\ud806\udd09\ud806\udd0c-\ud806\udd13\ud806\udd15-\ud806\udd16\ud806\udd18-\ud806\udd35\ud806\udd37-\ud806\udd38\ud806\udd3b-\ud806\udd43\ud806\udd50-\ud806\udd59\ud806\udda0-\ud806\udda7\ud806\uddaa-\ud806\uddd7\ud806\uddda-\ud806\udde1\ud806\udde3-\ud806\udde4\ud806\ude00-\ud806\ude3e\ud806\ude47\ud806\ude50-\ud806\ude99\ud806\ude9d\ud806\udeb0-\ud806\udef8\ud806\udfc0-\ud806\udfe0\ud806\udff0-\ud806\udff9\ud807\udc00-\ud807\udc08\ud807\udc0a-\ud807\udc36\ud807\udc38-\ud807\udc40\ud807\udc50-\ud807\udc59\ud807\udc72-\ud807\udc8f\ud807\udc92-\ud807\udca7\ud807\udca9-\ud807\udcb6\ud807\udd00-\ud807\udd06\ud807\udd08-\ud807\udd09\ud807\udd0b-\ud807\udd36\ud807\udd3a\ud807\udd3c-\ud807\udd3d\ud807\udd3f-\ud807\udd47\ud807\udd50-\ud807\udd59\ud807\udd60-\ud807\udd65\ud807\udd67-\ud807\udd68\ud807\udd6a-\ud807\udd8e\ud807\udd90-\ud807\udd91\ud807\udd93-\ud807\udd98\ud807\udda0-\ud807\udda9\ud807\udee0-\ud807\udef6\ud807\udf00-\ud807\udf10\ud807\udf12-\ud807\udf3a\ud807\udf3e-\ud807\udf42\ud807\udf50-\ud807\udf5a\ud807\udfb0\ud808\udc00-\ud808\udf99\ud809\udc00-\ud809\udc6e\ud809\udc80-\ud809\udd43\ud80b\udf90-\ud80b\udff0\ud80c\udc00-\ud80d\udc2f\ud80d\udc40-\ud80d\udc55\ud80d\udc60-\ud810\udffa\ud811\udc00-\ud811\ude46\ud818\udd00-\ud818\udd39\ud81a\udc00-\ud81a\ude38\ud81a\ude40-\ud81a\ude5e\ud81a\ude60-\ud81a\ude69\ud81a\ude70-\ud81a\udebe\ud81a\udec0-\ud81a\udec9\ud81a\uded0-\ud81a\udeed\ud81a\udef0-\ud81a\udef4\ud81a\udf00-\ud81a\udf36\ud81a\udf40-\ud81a\udf43\ud81a\udf50-\ud81a\udf59\ud81a\udf63-\ud81a\udf77\ud81a\udf7d-\ud81a\udf8f\ud81b\udd40-\ud81b\udd6c\ud81b\udd70-\ud81b\udd79\ud81b\ude40-\ud81b\ude7f\ud81b\udf00-\ud81b\udf4a\ud81b\udf4f-\ud81b\udf87\ud81b\udf8f-\ud81b\udf9f\ud81b\udfe0-\ud81b\udfe1\ud81b\udfe3-\ud81b\udfe4\ud81b\udff0-\ud81b\udff1\ud81c\udc00-\ud821\udff7\ud822\udc00-\ud823\udcd5\ud823\udcff-\ud823\udd08\ud82b\udff0-\ud82b\udff3\ud82b\udff5-\ud82b\udffb\ud82b\udffd-\ud82b\udffe\ud82c\udc00-\ud82c\udd22\ud82c\udd32\ud82c\udd50-\ud82c\udd52\ud82c\udd55\ud82c\udd64-\ud82c\udd67\ud82c\udd70-\ud82c\udefb\ud82f\udc00-\ud82f\udc6a\ud82f\udc70-\ud82f\udc7c\ud82f\udc80-\ud82f\udc88\ud82f\udc90-\ud82f\udc99\ud82f\udc9d-\ud82f\udc9e\ud833\udcf0-\ud833\udcf9\ud833\udf00-\ud833\udf2d\ud833\udf30-\ud833\udf46\ud834\udd65-\ud834\udd69\ud834\udd6d-\ud834\udd72\ud834\udd7b-\ud834\udd82\ud834\udd85-\ud834\udd8b\ud834\uddaa-\ud834\uddad\ud834\ude42-\ud834\ude44\ud835\udc00-\ud835\udc54\ud835\udc56-\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd1e-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd52-\ud835\udea5\ud835\udea8-\ud835\udec0\ud835\udec2-\ud835\udeda\ud835\udedc-\ud835\udefa\ud835\udefc-\ud835\udf14\ud835\udf16-\ud835\udf34\ud835\udf36-\ud835\udf4e\ud835\udf50-\ud835\udf6e\ud835\udf70-\ud835\udf88\ud835\udf8a-\ud835\udfa8\ud835\udfaa-\ud835\udfc2\ud835\udfc4-\ud835\udfcb\ud835\udfce-\ud835\udfff\ud836\ude00-\ud836\ude36\ud836\ude3b-\ud836\ude6c\ud836\ude75\ud836\ude84\ud836\ude9b-\ud836\ude9f\ud836\udea1-\ud836\udeaf\ud837\udf00-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud838\udc00-\ud838\udc06\ud838\udc08-\ud838\udc18\ud838\udc1b-\ud838\udc21\ud838\udc23-\ud838\udc24\ud838\udc26-\ud838\udc2a\ud838\udc30-\ud838\udc6d\ud838\udc8f\ud838\udd00-\ud838\udd2c\ud838\udd30-\ud838\udd3d\ud838\udd40-\ud838\udd49\ud838\udd4e\ud838\ude90-\ud838\udeae\ud838\udec0-\ud838\udef9\ud839\udcd0-\ud839\udcf9\ud839\uddd0-\ud839\uddfa\ud839\udfe0-\ud839\udfe6\ud839\udfe8-\ud839\udfeb\ud839\udfed-\ud839\udfee\ud839\udff0-\ud839\udffe\ud83a\udc00-\ud83a\udcc4\ud83a\udcd0-\ud83a\udcd6\ud83a\udd00-\ud83a\udd4b\ud83a\udd50-\ud83a\udd59\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21-\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51-\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61-\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb\ud83e\udff0-\ud83e\udff9\ud840\udc00-\ud869\udedf\ud869\udf00-\ud86d\udf39\ud86d\udf40-\ud86e\udc1d\ud86e\udc20-\ud873\udea1\ud873\udeb0-\ud87a\udfe0\ud87a\udff0-\ud87b\ude5d\ud87e\udc00-\ud87e\ude1d\ud880\udc00-\ud884\udf4a\ud884\udf50-\ud888\udfaf\udb40\udd00-\udb40\uddef] +Unicode_XID_Start <- [\u0041-\u005a\u0061-\u007a\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376-\u0377\u037b-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e-\u066f\u0671-\u06d3\u06d5\u06e5-\u06e6\u06ee-\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4-\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u09fc\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0-\u0ae1\u0af9\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60-\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd-\u0cde\u0ce0-\u0ce1\u0cf1-\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e40-\u0e46\u0e81-\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065-\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae-\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5-\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a-\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0-\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd-\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5-\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufc5d\ufc64-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdf9\ufe71\ufe73\ufe77\ufe79\ufe7b\ufe7d\ufe7f-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uff9d\uffa0-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\ud800\udc00-\ud800\udc0b\ud800\udc0d-\ud800\udc26\ud800\udc28-\ud800\udc3a\ud800\udc3c-\ud800\udc3d\ud800\udc3f-\ud800\udc4d\ud800\udc50-\ud800\udc5d\ud800\udc80-\ud800\udcfa\ud800\udd40-\ud800\udd74\ud800\ude80-\ud800\ude9c\ud800\udea0-\ud800\uded0\ud800\udf00-\ud800\udf1f\ud800\udf2d-\ud800\udf4a\ud800\udf50-\ud800\udf75\ud800\udf80-\ud800\udf9d\ud800\udfa0-\ud800\udfc3\ud800\udfc8-\ud800\udfcf\ud800\udfd1-\ud800\udfd5\ud801\udc00-\ud801\udc9d\ud801\udcb0-\ud801\udcd3\ud801\udcd8-\ud801\udcfb\ud801\udd00-\ud801\udd27\ud801\udd30-\ud801\udd63\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud801\uddc0-\ud801\uddf3\ud801\ude00-\ud801\udf36\ud801\udf40-\ud801\udf55\ud801\udf60-\ud801\udf67\ud801\udf80-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud802\udc00-\ud802\udc05\ud802\udc08\ud802\udc0a-\ud802\udc35\ud802\udc37-\ud802\udc38\ud802\udc3c\ud802\udc3f-\ud802\udc55\ud802\udc60-\ud802\udc76\ud802\udc80-\ud802\udc9e\ud802\udce0-\ud802\udcf2\ud802\udcf4-\ud802\udcf5\ud802\udd00-\ud802\udd15\ud802\udd20-\ud802\udd39\ud802\udd80-\ud802\uddb7\ud802\uddbe-\ud802\uddbf\ud802\ude00\ud802\ude10-\ud802\ude13\ud802\ude15-\ud802\ude17\ud802\ude19-\ud802\ude35\ud802\ude60-\ud802\ude7c\ud802\ude80-\ud802\ude9c\ud802\udec0-\ud802\udec7\ud802\udec9-\ud802\udee4\ud802\udf00-\ud802\udf35\ud802\udf40-\ud802\udf55\ud802\udf60-\ud802\udf72\ud802\udf80-\ud802\udf91\ud803\udc00-\ud803\udc48\ud803\udc80-\ud803\udcb2\ud803\udcc0-\ud803\udcf2\ud803\udd00-\ud803\udd23\ud803\udd4a-\ud803\udd65\ud803\udd6f-\ud803\udd85\ud803\ude80-\ud803\udea9\ud803\udeb0-\ud803\udeb1\ud803\udec2-\ud803\udec4\ud803\udf00-\ud803\udf1c\ud803\udf27\ud803\udf30-\ud803\udf45\ud803\udf70-\ud803\udf81\ud803\udfb0-\ud803\udfc4\ud803\udfe0-\ud803\udff6\ud804\udc03-\ud804\udc37\ud804\udc71-\ud804\udc72\ud804\udc75\ud804\udc83-\ud804\udcaf\ud804\udcd0-\ud804\udce8\ud804\udd03-\ud804\udd26\ud804\udd44\ud804\udd47\ud804\udd50-\ud804\udd72\ud804\udd76\ud804\udd83-\ud804\uddb2\ud804\uddc1-\ud804\uddc4\ud804\uddda\ud804\udddc\ud804\ude00-\ud804\ude11\ud804\ude13-\ud804\ude2b\ud804\ude3f-\ud804\ude40\ud804\ude80-\ud804\ude86\ud804\ude88\ud804\ude8a-\ud804\ude8d\ud804\ude8f-\ud804\ude9d\ud804\ude9f-\ud804\udea8\ud804\udeb0-\ud804\udede\ud804\udf05-\ud804\udf0c\ud804\udf0f-\ud804\udf10\ud804\udf13-\ud804\udf28\ud804\udf2a-\ud804\udf30\ud804\udf32-\ud804\udf33\ud804\udf35-\ud804\udf39\ud804\udf3d\ud804\udf50\ud804\udf5d-\ud804\udf61\ud804\udf80-\ud804\udf89\ud804\udf8b\ud804\udf8e\ud804\udf90-\ud804\udfb5\ud804\udfb7\ud804\udfd1\ud804\udfd3\ud805\udc00-\ud805\udc34\ud805\udc47-\ud805\udc4a\ud805\udc5f-\ud805\udc61\ud805\udc80-\ud805\udcaf\ud805\udcc4-\ud805\udcc5\ud805\udcc7\ud805\udd80-\ud805\uddae\ud805\uddd8-\ud805\udddb\ud805\ude00-\ud805\ude2f\ud805\ude44\ud805\ude80-\ud805\udeaa\ud805\udeb8\ud805\udf00-\ud805\udf1a\ud805\udf40-\ud805\udf46\ud806\udc00-\ud806\udc2b\ud806\udca0-\ud806\udcdf\ud806\udcff-\ud806\udd06\ud806\udd09\ud806\udd0c-\ud806\udd13\ud806\udd15-\ud806\udd16\ud806\udd18-\ud806\udd2f\ud806\udd3f\ud806\udd41\ud806\udda0-\ud806\udda7\ud806\uddaa-\ud806\uddd0\ud806\udde1\ud806\udde3\ud806\ude00\ud806\ude0b-\ud806\ude32\ud806\ude3a\ud806\ude50\ud806\ude5c-\ud806\ude89\ud806\ude9d\ud806\udeb0-\ud806\udef8\ud806\udfc0-\ud806\udfe0\ud807\udc00-\ud807\udc08\ud807\udc0a-\ud807\udc2e\ud807\udc40\ud807\udc72-\ud807\udc8f\ud807\udd00-\ud807\udd06\ud807\udd08-\ud807\udd09\ud807\udd0b-\ud807\udd30\ud807\udd46\ud807\udd60-\ud807\udd65\ud807\udd67-\ud807\udd68\ud807\udd6a-\ud807\udd89\ud807\udd98\ud807\udee0-\ud807\udef2\ud807\udf02\ud807\udf04-\ud807\udf10\ud807\udf12-\ud807\udf33\ud807\udfb0\ud808\udc00-\ud808\udf99\ud809\udc00-\ud809\udc6e\ud809\udc80-\ud809\udd43\ud80b\udf90-\ud80b\udff0\ud80c\udc00-\ud80d\udc2f\ud80d\udc41-\ud80d\udc46\ud80d\udc60-\ud810\udffa\ud811\udc00-\ud811\ude46\ud818\udd00-\ud818\udd1d\ud81a\udc00-\ud81a\ude38\ud81a\ude40-\ud81a\ude5e\ud81a\ude70-\ud81a\udebe\ud81a\uded0-\ud81a\udeed\ud81a\udf00-\ud81a\udf2f\ud81a\udf40-\ud81a\udf43\ud81a\udf63-\ud81a\udf77\ud81a\udf7d-\ud81a\udf8f\ud81b\udd40-\ud81b\udd6c\ud81b\ude40-\ud81b\ude7f\ud81b\udf00-\ud81b\udf4a\ud81b\udf50\ud81b\udf93-\ud81b\udf9f\ud81b\udfe0-\ud81b\udfe1\ud81b\udfe3\ud81c\udc00-\ud821\udff7\ud822\udc00-\ud823\udcd5\ud823\udcff-\ud823\udd08\ud82b\udff0-\ud82b\udff3\ud82b\udff5-\ud82b\udffb\ud82b\udffd-\ud82b\udffe\ud82c\udc00-\ud82c\udd22\ud82c\udd32\ud82c\udd50-\ud82c\udd52\ud82c\udd55\ud82c\udd64-\ud82c\udd67\ud82c\udd70-\ud82c\udefb\ud82f\udc00-\ud82f\udc6a\ud82f\udc70-\ud82f\udc7c\ud82f\udc80-\ud82f\udc88\ud82f\udc90-\ud82f\udc99\ud835\udc00-\ud835\udc54\ud835\udc56-\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd1e-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd52-\ud835\udea5\ud835\udea8-\ud835\udec0\ud835\udec2-\ud835\udeda\ud835\udedc-\ud835\udefa\ud835\udefc-\ud835\udf14\ud835\udf16-\ud835\udf34\ud835\udf36-\ud835\udf4e\ud835\udf50-\ud835\udf6e\ud835\udf70-\ud835\udf88\ud835\udf8a-\ud835\udfa8\ud835\udfaa-\ud835\udfc2\ud835\udfc4-\ud835\udfcb\ud837\udf00-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud838\udc30-\ud838\udc6d\ud838\udd00-\ud838\udd2c\ud838\udd37-\ud838\udd3d\ud838\udd4e\ud838\ude90-\ud838\udead\ud838\udec0-\ud838\udeeb\ud839\udcd0-\ud839\udceb\ud839\uddd0-\ud839\udded\ud839\uddf0\ud839\udfe0-\ud839\udfe6\ud839\udfe8-\ud839\udfeb\ud839\udfed-\ud839\udfee\ud839\udff0-\ud839\udffe\ud83a\udc00-\ud83a\udcc4\ud83a\udd00-\ud83a\udd43\ud83a\udd4b\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21-\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51-\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61-\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb\ud840\udc00-\ud869\udedf\ud869\udf00-\ud86d\udf39\ud86d\udf40-\ud86e\udc1d\ud86e\udc20-\ud873\udea1\ud873\udeb0-\ud87a\udfe0\ud87a\udff0-\ud87b\ude5d\ud87e\udc00-\ud87e\ude1d\ud880\udc00-\ud884\udf4a\ud884\udf50-\ud888\udfaf] +Unicode_XID_Continue <- [\u0030-\u0039\u0041-\u005a\u005f\u0061-\u007a\u00aa\u00b5\u00b7\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376-\u0377\u037b-\u037d\u037f\u0386-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u05d0-\u05ea\u05ef-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u07fd\u0800-\u082d\u0840-\u085b\u0860-\u086a\u0870-\u0887\u0889-\u088e\u0897-\u08e1\u08e3-\u0963\u0966-\u096f\u0971-\u0983\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7-\u09c8\u09cb-\u09ce\u09d7\u09dc-\u09dd\u09df-\u09e3\u09e6-\u09f1\u09fc\u09fe\u0a01-\u0a03\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a3c\u0a3e-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0af9-\u0aff\u0b01-\u0b03\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47-\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b5c-\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82-\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c00-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3c-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c58-\u0c5a\u0c5d\u0c60-\u0c63\u0c66-\u0c6f\u0c80-\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5-\u0cd6\u0cdd-\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1-\u0cf3\u0d00-\u0d0c\u0d0e-\u0d10\u0d12-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d54-\u0d57\u0d5f-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d81-\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2-\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81-\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ece\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18-\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1369-\u1371\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1715\u171f-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772-\u1773\u1780-\u17d3\u17d7\u17dc-\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u1820-\u1878\u1880-\u18aa\u18b0-\u18f5\u1900-\u191e\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19da\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b4c\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1cd0-\u1cd2\u1cd4-\u1cfa\u1d00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c-\u200d\u203f-\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099-\u309a\u309d-\u309f\u30a1-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0-\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua827\ua82c\ua840-\ua873\ua880-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua8fd-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\ua9e0-\ua9fe\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabea\uabec-\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufc5d\ufc64-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdf9\ufe00-\ufe0f\ufe20-\ufe2f\ufe33-\ufe34\ufe4d-\ufe4f\ufe71\ufe73\ufe77\ufe79\ufe7b\ufe7d\ufe7f-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff65-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\ud800\udc00-\ud800\udc0b\ud800\udc0d-\ud800\udc26\ud800\udc28-\ud800\udc3a\ud800\udc3c-\ud800\udc3d\ud800\udc3f-\ud800\udc4d\ud800\udc50-\ud800\udc5d\ud800\udc80-\ud800\udcfa\ud800\udd40-\ud800\udd74\ud800\uddfd\ud800\ude80-\ud800\ude9c\ud800\udea0-\ud800\uded0\ud800\udee0\ud800\udf00-\ud800\udf1f\ud800\udf2d-\ud800\udf4a\ud800\udf50-\ud800\udf7a\ud800\udf80-\ud800\udf9d\ud800\udfa0-\ud800\udfc3\ud800\udfc8-\ud800\udfcf\ud800\udfd1-\ud800\udfd5\ud801\udc00-\ud801\udc9d\ud801\udca0-\ud801\udca9\ud801\udcb0-\ud801\udcd3\ud801\udcd8-\ud801\udcfb\ud801\udd00-\ud801\udd27\ud801\udd30-\ud801\udd63\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud801\uddc0-\ud801\uddf3\ud801\ude00-\ud801\udf36\ud801\udf40-\ud801\udf55\ud801\udf60-\ud801\udf67\ud801\udf80-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud802\udc00-\ud802\udc05\ud802\udc08\ud802\udc0a-\ud802\udc35\ud802\udc37-\ud802\udc38\ud802\udc3c\ud802\udc3f-\ud802\udc55\ud802\udc60-\ud802\udc76\ud802\udc80-\ud802\udc9e\ud802\udce0-\ud802\udcf2\ud802\udcf4-\ud802\udcf5\ud802\udd00-\ud802\udd15\ud802\udd20-\ud802\udd39\ud802\udd80-\ud802\uddb7\ud802\uddbe-\ud802\uddbf\ud802\ude00-\ud802\ude03\ud802\ude05-\ud802\ude06\ud802\ude0c-\ud802\ude13\ud802\ude15-\ud802\ude17\ud802\ude19-\ud802\ude35\ud802\ude38-\ud802\ude3a\ud802\ude3f\ud802\ude60-\ud802\ude7c\ud802\ude80-\ud802\ude9c\ud802\udec0-\ud802\udec7\ud802\udec9-\ud802\udee6\ud802\udf00-\ud802\udf35\ud802\udf40-\ud802\udf55\ud802\udf60-\ud802\udf72\ud802\udf80-\ud802\udf91\ud803\udc00-\ud803\udc48\ud803\udc80-\ud803\udcb2\ud803\udcc0-\ud803\udcf2\ud803\udd00-\ud803\udd27\ud803\udd30-\ud803\udd39\ud803\udd40-\ud803\udd65\ud803\udd69-\ud803\udd6d\ud803\udd6f-\ud803\udd85\ud803\ude80-\ud803\udea9\ud803\udeab-\ud803\udeac\ud803\udeb0-\ud803\udeb1\ud803\udec2-\ud803\udec4\ud803\udefc-\ud803\udf1c\ud803\udf27\ud803\udf30-\ud803\udf50\ud803\udf70-\ud803\udf85\ud803\udfb0-\ud803\udfc4\ud803\udfe0-\ud803\udff6\ud804\udc00-\ud804\udc46\ud804\udc66-\ud804\udc75\ud804\udc7f-\ud804\udcba\ud804\udcc2\ud804\udcd0-\ud804\udce8\ud804\udcf0-\ud804\udcf9\ud804\udd00-\ud804\udd34\ud804\udd36-\ud804\udd3f\ud804\udd44-\ud804\udd47\ud804\udd50-\ud804\udd73\ud804\udd76\ud804\udd80-\ud804\uddc4\ud804\uddc9-\ud804\uddcc\ud804\uddce-\ud804\uddda\ud804\udddc\ud804\ude00-\ud804\ude11\ud804\ude13-\ud804\ude37\ud804\ude3e-\ud804\ude41\ud804\ude80-\ud804\ude86\ud804\ude88\ud804\ude8a-\ud804\ude8d\ud804\ude8f-\ud804\ude9d\ud804\ude9f-\ud804\udea8\ud804\udeb0-\ud804\udeea\ud804\udef0-\ud804\udef9\ud804\udf00-\ud804\udf03\ud804\udf05-\ud804\udf0c\ud804\udf0f-\ud804\udf10\ud804\udf13-\ud804\udf28\ud804\udf2a-\ud804\udf30\ud804\udf32-\ud804\udf33\ud804\udf35-\ud804\udf39\ud804\udf3b-\ud804\udf44\ud804\udf47-\ud804\udf48\ud804\udf4b-\ud804\udf4d\ud804\udf50\ud804\udf57\ud804\udf5d-\ud804\udf63\ud804\udf66-\ud804\udf6c\ud804\udf70-\ud804\udf74\ud804\udf80-\ud804\udf89\ud804\udf8b\ud804\udf8e\ud804\udf90-\ud804\udfb5\ud804\udfb7-\ud804\udfc0\ud804\udfc2\ud804\udfc5\ud804\udfc7-\ud804\udfca\ud804\udfcc-\ud804\udfd3\ud804\udfe1-\ud804\udfe2\ud805\udc00-\ud805\udc4a\ud805\udc50-\ud805\udc59\ud805\udc5e-\ud805\udc61\ud805\udc80-\ud805\udcc5\ud805\udcc7\ud805\udcd0-\ud805\udcd9\ud805\udd80-\ud805\uddb5\ud805\uddb8-\ud805\uddc0\ud805\uddd8-\ud805\udddd\ud805\ude00-\ud805\ude40\ud805\ude44\ud805\ude50-\ud805\ude59\ud805\ude80-\ud805\udeb8\ud805\udec0-\ud805\udec9\ud805\uded0-\ud805\udee3\ud805\udf00-\ud805\udf1a\ud805\udf1d-\ud805\udf2b\ud805\udf30-\ud805\udf39\ud805\udf40-\ud805\udf46\ud806\udc00-\ud806\udc3a\ud806\udca0-\ud806\udce9\ud806\udcff-\ud806\udd06\ud806\udd09\ud806\udd0c-\ud806\udd13\ud806\udd15-\ud806\udd16\ud806\udd18-\ud806\udd35\ud806\udd37-\ud806\udd38\ud806\udd3b-\ud806\udd43\ud806\udd50-\ud806\udd59\ud806\udda0-\ud806\udda7\ud806\uddaa-\ud806\uddd7\ud806\uddda-\ud806\udde1\ud806\udde3-\ud806\udde4\ud806\ude00-\ud806\ude3e\ud806\ude47\ud806\ude50-\ud806\ude99\ud806\ude9d\ud806\udeb0-\ud806\udef8\ud806\udfc0-\ud806\udfe0\ud806\udff0-\ud806\udff9\ud807\udc00-\ud807\udc08\ud807\udc0a-\ud807\udc36\ud807\udc38-\ud807\udc40\ud807\udc50-\ud807\udc59\ud807\udc72-\ud807\udc8f\ud807\udc92-\ud807\udca7\ud807\udca9-\ud807\udcb6\ud807\udd00-\ud807\udd06\ud807\udd08-\ud807\udd09\ud807\udd0b-\ud807\udd36\ud807\udd3a\ud807\udd3c-\ud807\udd3d\ud807\udd3f-\ud807\udd47\ud807\udd50-\ud807\udd59\ud807\udd60-\ud807\udd65\ud807\udd67-\ud807\udd68\ud807\udd6a-\ud807\udd8e\ud807\udd90-\ud807\udd91\ud807\udd93-\ud807\udd98\ud807\udda0-\ud807\udda9\ud807\udee0-\ud807\udef6\ud807\udf00-\ud807\udf10\ud807\udf12-\ud807\udf3a\ud807\udf3e-\ud807\udf42\ud807\udf50-\ud807\udf5a\ud807\udfb0\ud808\udc00-\ud808\udf99\ud809\udc00-\ud809\udc6e\ud809\udc80-\ud809\udd43\ud80b\udf90-\ud80b\udff0\ud80c\udc00-\ud80d\udc2f\ud80d\udc40-\ud80d\udc55\ud80d\udc60-\ud810\udffa\ud811\udc00-\ud811\ude46\ud818\udd00-\ud818\udd39\ud81a\udc00-\ud81a\ude38\ud81a\ude40-\ud81a\ude5e\ud81a\ude60-\ud81a\ude69\ud81a\ude70-\ud81a\udebe\ud81a\udec0-\ud81a\udec9\ud81a\uded0-\ud81a\udeed\ud81a\udef0-\ud81a\udef4\ud81a\udf00-\ud81a\udf36\ud81a\udf40-\ud81a\udf43\ud81a\udf50-\ud81a\udf59\ud81a\udf63-\ud81a\udf77\ud81a\udf7d-\ud81a\udf8f\ud81b\udd40-\ud81b\udd6c\ud81b\udd70-\ud81b\udd79\ud81b\ude40-\ud81b\ude7f\ud81b\udf00-\ud81b\udf4a\ud81b\udf4f-\ud81b\udf87\ud81b\udf8f-\ud81b\udf9f\ud81b\udfe0-\ud81b\udfe1\ud81b\udfe3-\ud81b\udfe4\ud81b\udff0-\ud81b\udff1\ud81c\udc00-\ud821\udff7\ud822\udc00-\ud823\udcd5\ud823\udcff-\ud823\udd08\ud82b\udff0-\ud82b\udff3\ud82b\udff5-\ud82b\udffb\ud82b\udffd-\ud82b\udffe\ud82c\udc00-\ud82c\udd22\ud82c\udd32\ud82c\udd50-\ud82c\udd52\ud82c\udd55\ud82c\udd64-\ud82c\udd67\ud82c\udd70-\ud82c\udefb\ud82f\udc00-\ud82f\udc6a\ud82f\udc70-\ud82f\udc7c\ud82f\udc80-\ud82f\udc88\ud82f\udc90-\ud82f\udc99\ud82f\udc9d-\ud82f\udc9e\ud833\udcf0-\ud833\udcf9\ud833\udf00-\ud833\udf2d\ud833\udf30-\ud833\udf46\ud834\udd65-\ud834\udd69\ud834\udd6d-\ud834\udd72\ud834\udd7b-\ud834\udd82\ud834\udd85-\ud834\udd8b\ud834\uddaa-\ud834\uddad\ud834\ude42-\ud834\ude44\ud835\udc00-\ud835\udc54\ud835\udc56-\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd1e-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd52-\ud835\udea5\ud835\udea8-\ud835\udec0\ud835\udec2-\ud835\udeda\ud835\udedc-\ud835\udefa\ud835\udefc-\ud835\udf14\ud835\udf16-\ud835\udf34\ud835\udf36-\ud835\udf4e\ud835\udf50-\ud835\udf6e\ud835\udf70-\ud835\udf88\ud835\udf8a-\ud835\udfa8\ud835\udfaa-\ud835\udfc2\ud835\udfc4-\ud835\udfcb\ud835\udfce-\ud835\udfff\ud836\ude00-\ud836\ude36\ud836\ude3b-\ud836\ude6c\ud836\ude75\ud836\ude84\ud836\ude9b-\ud836\ude9f\ud836\udea1-\ud836\udeaf\ud837\udf00-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud838\udc00-\ud838\udc06\ud838\udc08-\ud838\udc18\ud838\udc1b-\ud838\udc21\ud838\udc23-\ud838\udc24\ud838\udc26-\ud838\udc2a\ud838\udc30-\ud838\udc6d\ud838\udc8f\ud838\udd00-\ud838\udd2c\ud838\udd30-\ud838\udd3d\ud838\udd40-\ud838\udd49\ud838\udd4e\ud838\ude90-\ud838\udeae\ud838\udec0-\ud838\udef9\ud839\udcd0-\ud839\udcf9\ud839\uddd0-\ud839\uddfa\ud839\udfe0-\ud839\udfe6\ud839\udfe8-\ud839\udfeb\ud839\udfed-\ud839\udfee\ud839\udff0-\ud839\udffe\ud83a\udc00-\ud83a\udcc4\ud83a\udcd0-\ud83a\udcd6\ud83a\udd00-\ud83a\udd4b\ud83a\udd50-\ud83a\udd59\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21-\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51-\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61-\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb\ud83e\udff0-\ud83e\udff9\ud840\udc00-\ud869\udedf\ud869\udf00-\ud86d\udf39\ud86d\udf40-\ud86e\udc1d\ud86e\udc20-\ud873\udea1\ud873\udeb0-\ud87a\udfe0\ud87a\udff0-\ud87b\ude5d\ud87e\udc00-\ud87e\ude1d\ud880\udc00-\ud884\udf4a\ud884\udf50-\ud888\udfaf\udb40\udd00-\udb40\uddef] +Unicode_Default_Ignorable_Code_Point <- [\u00ad\u034f\u061c\u115f-\u1160\u17b4-\u17b5\u180b-\u180f\u200b-\u200f\u202a-\u202e\u2060-\u206f\u3164\ufe00-\ufe0f\ufeff\uffa0\ufff0-\ufff8\ud82f\udca0-\ud82f\udca3\ud834\udd73-\ud834\udd7a\udb40\udc00-\udb43\udfff] +Unicode_Grapheme_Extend <- [\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3\u09fe\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0afa-\u0aff\u0b01\u0b3c\u0b3e-\u0b3f\u0b41-\u0b44\u0b4d\u0b55-\u0b57\u0b62-\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c04\u0c3c\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf-\u0cc0\u0cc2\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d00-\u0d01\u0d3b-\u0d3c\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62-\u0d63\u0d81\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1715\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u180f\u1885-\u1886\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1ace\u1b00-\u1b03\u1b34-\u1b3d\u1b42-\u1b44\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf3\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9\u1dc0-\u1dff\u200c\u20d0-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099-\u309a\ua66f-\ua672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua82c\ua8c4-\ua8c5\ua8e0-\ua8f1\ua8ff\ua926-\ua92d\ua947-\ua951\ua953\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc-\ua9bd\ua9c0\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f\ud800\uddfd\ud800\udee0\ud800\udf76-\ud800\udf7a\ud802\ude01-\ud802\ude03\ud802\ude05-\ud802\ude06\ud802\ude0c-\ud802\ude0f\ud802\ude38-\ud802\ude3a\ud802\ude3f\ud802\udee5-\ud802\udee6\ud803\udd24-\ud803\udd27\ud803\udd69-\ud803\udd6d\ud803\udeab-\ud803\udeac\ud803\udefc-\ud803\udeff\ud803\udf46-\ud803\udf50\ud803\udf82-\ud803\udf85\ud804\udc01\ud804\udc38-\ud804\udc46\ud804\udc70\ud804\udc73-\ud804\udc74\ud804\udc7f-\ud804\udc81\ud804\udcb3-\ud804\udcb6\ud804\udcb9-\ud804\udcba\ud804\udcc2\ud804\udd00-\ud804\udd02\ud804\udd27-\ud804\udd2b\ud804\udd2d-\ud804\udd34\ud804\udd73\ud804\udd80-\ud804\udd81\ud804\uddb6-\ud804\uddbe\ud804\uddc0\ud804\uddc9-\ud804\uddcc\ud804\uddcf\ud804\ude2f-\ud804\ude31\ud804\ude34-\ud804\ude37\ud804\ude3e\ud804\ude41\ud804\udedf\ud804\udee3-\ud804\udeea\ud804\udf00-\ud804\udf01\ud804\udf3b-\ud804\udf3c\ud804\udf3e\ud804\udf40\ud804\udf4d\ud804\udf57\ud804\udf66-\ud804\udf6c\ud804\udf70-\ud804\udf74\ud804\udfb8\ud804\udfbb-\ud804\udfc0\ud804\udfc2\ud804\udfc5\ud804\udfc7-\ud804\udfc9\ud804\udfce-\ud804\udfd0\ud804\udfd2\ud804\udfe1-\ud804\udfe2\ud805\udc38-\ud805\udc3f\ud805\udc42-\ud805\udc44\ud805\udc46\ud805\udc5e\ud805\udcb0\ud805\udcb3-\ud805\udcb8\ud805\udcba\ud805\udcbd\ud805\udcbf-\ud805\udcc0\ud805\udcc2-\ud805\udcc3\ud805\uddaf\ud805\uddb2-\ud805\uddb5\ud805\uddbc-\ud805\uddbd\ud805\uddbf-\ud805\uddc0\ud805\udddc-\ud805\udddd\ud805\ude33-\ud805\ude3a\ud805\ude3d\ud805\ude3f-\ud805\ude40\ud805\udeab\ud805\udead\ud805\udeb0-\ud805\udeb7\ud805\udf1d\ud805\udf1f\ud805\udf22-\ud805\udf25\ud805\udf27-\ud805\udf2b\ud806\udc2f-\ud806\udc37\ud806\udc39-\ud806\udc3a\ud806\udd30\ud806\udd3b-\ud806\udd3e\ud806\udd43\ud806\uddd4-\ud806\uddd7\ud806\uddda-\ud806\udddb\ud806\udde0\ud806\ude01-\ud806\ude0a\ud806\ude33-\ud806\ude38\ud806\ude3b-\ud806\ude3e\ud806\ude47\ud806\ude51-\ud806\ude56\ud806\ude59-\ud806\ude5b\ud806\ude8a-\ud806\ude96\ud806\ude98-\ud806\ude99\ud807\udc30-\ud807\udc36\ud807\udc38-\ud807\udc3d\ud807\udc3f\ud807\udc92-\ud807\udca7\ud807\udcaa-\ud807\udcb0\ud807\udcb2-\ud807\udcb3\ud807\udcb5-\ud807\udcb6\ud807\udd31-\ud807\udd36\ud807\udd3a\ud807\udd3c-\ud807\udd3d\ud807\udd3f-\ud807\udd45\ud807\udd47\ud807\udd90-\ud807\udd91\ud807\udd95\ud807\udd97\ud807\udef3-\ud807\udef4\ud807\udf00-\ud807\udf01\ud807\udf36-\ud807\udf3a\ud807\udf40-\ud807\udf42\ud807\udf5a\ud80d\udc40\ud80d\udc47-\ud80d\udc55\ud818\udd1e-\ud818\udd29\ud818\udd2d-\ud818\udd2f\ud81a\udef0-\ud81a\udef4\ud81a\udf30-\ud81a\udf36\ud81b\udf4f\ud81b\udf8f-\ud81b\udf92\ud81b\udfe4\ud81b\udff0-\ud81b\udff1\ud82f\udc9d-\ud82f\udc9e\ud833\udf00-\ud833\udf2d\ud833\udf30-\ud833\udf46\ud834\udd65-\ud834\udd69\ud834\udd6d-\ud834\udd72\ud834\udd7b-\ud834\udd82\ud834\udd85-\ud834\udd8b\ud834\uddaa-\ud834\uddad\ud834\ude42-\ud834\ude44\ud836\ude00-\ud836\ude36\ud836\ude3b-\ud836\ude6c\ud836\ude75\ud836\ude84\ud836\ude9b-\ud836\ude9f\ud836\udea1-\ud836\udeaf\ud838\udc00-\ud838\udc06\ud838\udc08-\ud838\udc18\ud838\udc1b-\ud838\udc21\ud838\udc23-\ud838\udc24\ud838\udc26-\ud838\udc2a\ud838\udc8f\ud838\udd30-\ud838\udd36\ud838\udeae\ud838\udeec-\ud838\udeef\ud839\udcec-\ud839\udcef\ud839\uddee-\ud839\uddef\ud83a\udcd0-\ud83a\udcd6\ud83a\udd44-\ud83a\udd4a\udb40\udc20-\udb40\udc7f\udb40\udd00-\udb40\uddef] +Unicode_Grapheme_Base <- [\u0020-\u007e\u00a0-\u00ac\u00ae-\u02ff\u0370-\u0377\u037a-\u037f\u0384-\u038a\u038c\u038e-\u03a1\u03a3-\u0482\u048a-\u052f\u0531-\u0556\u0559-\u058a\u058d-\u058f\u05be\u05c0\u05c3\u05c6\u05d0-\u05ea\u05ef-\u05f4\u0606-\u060f\u061b\u061d-\u064a\u0660-\u066f\u0671-\u06d5\u06de\u06e5-\u06e6\u06e9\u06ee-\u070d\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07c0-\u07ea\u07f4-\u07fa\u07fe-\u0815\u081a\u0824\u0828\u0830-\u083e\u0840-\u0858\u085e\u0860-\u086a\u0870-\u088e\u08a0-\u08c9\u0903-\u0939\u093b\u093d-\u0940\u0949-\u094c\u094e-\u0950\u0958-\u0961\u0964-\u0980\u0982-\u0983\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09bf-\u09c0\u09c7-\u09c8\u09cb-\u09cc\u09ce\u09dc-\u09dd\u09df-\u09e1\u09e6-\u09fd\u0a03\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a3e-\u0a40\u0a59-\u0a5c\u0a5e\u0a66-\u0a6f\u0a72-\u0a74\u0a76\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd-\u0ac0\u0ac9\u0acb-\u0acc\u0ad0\u0ae0-\u0ae1\u0ae6-\u0af1\u0af9\u0b02-\u0b03\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d\u0b40\u0b47-\u0b48\u0b4b-\u0b4c\u0b5c-\u0b5d\u0b5f-\u0b61\u0b66-\u0b77\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbf\u0bc1-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd0\u0be6-\u0bfa\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c41-\u0c44\u0c58-\u0c5a\u0c5d\u0c60-\u0c61\u0c66-\u0c6f\u0c77-\u0c80\u0c82-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd-\u0cbe\u0cc1\u0cc3-\u0cc4\u0cdd-\u0cde\u0ce0-\u0ce1\u0ce6-\u0cef\u0cf1-\u0cf3\u0d02-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d3f-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d4e-\u0d4f\u0d54-\u0d56\u0d58-\u0d61\u0d66-\u0d7f\u0d82-\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dd0-\u0dd1\u0dd8-\u0dde\u0de6-\u0def\u0df2-\u0df4\u0e01-\u0e30\u0e32-\u0e33\u0e3f-\u0e46\u0e4f-\u0e5b\u0e81-\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2-\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0ed0-\u0ed9\u0edc-\u0edf\u0f00-\u0f17\u0f1a-\u0f34\u0f36\u0f38\u0f3a-\u0f47\u0f49-\u0f6c\u0f7f\u0f85\u0f88-\u0f8c\u0fbe-\u0fc5\u0fc7-\u0fcc\u0fce-\u0fda\u1000-\u102c\u1031\u1038\u103b-\u103c\u103f-\u1057\u105a-\u105d\u1061-\u1070\u1075-\u1081\u1083-\u1084\u1087-\u108c\u108e-\u109c\u109e-\u10c5\u10c7\u10cd\u10d0-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1360-\u137c\u1380-\u1399\u13a0-\u13f5\u13f8-\u13fd\u1400-\u169c\u16a0-\u16f8\u1700-\u1711\u171f-\u1731\u1735-\u1736\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17b6\u17be-\u17c5\u17c7-\u17c8\u17d4-\u17dc\u17e0-\u17e9\u17f0-\u17f9\u1800-\u180a\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1923-\u1926\u1929-\u192b\u1930-\u1931\u1933-\u1938\u1940\u1944-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19da\u19de-\u1a16\u1a19-\u1a1a\u1a1e-\u1a55\u1a57\u1a61\u1a63-\u1a64\u1a6d-\u1a72\u1a80-\u1a89\u1a90-\u1a99\u1aa0-\u1aad\u1b04-\u1b33\u1b3e-\u1b41\u1b45-\u1b4c\u1b4e-\u1b6a\u1b74-\u1b7f\u1b82-\u1ba1\u1ba6-\u1ba7\u1bae-\u1be5\u1be7\u1bea-\u1bec\u1bee\u1bfc-\u1c2b\u1c34-\u1c35\u1c3b-\u1c49\u1c4d-\u1c8a\u1c90-\u1cba\u1cbd-\u1cc7\u1cd3\u1ce1\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5-\u1cf7\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fc4\u1fc6-\u1fd3\u1fd6-\u1fdb\u1fdd-\u1fef\u1ff2-\u1ff4\u1ff6-\u1ffe\u2000-\u200a\u2010-\u2027\u202f-\u205f\u2070-\u2071\u2074-\u208e\u2090-\u209c\u20a0-\u20c0\u2100-\u218b\u2190-\u2429\u2440-\u244a\u2460-\u2b73\u2b76-\u2b95\u2b97-\u2cee\u2cf2-\u2cf3\u2cf9-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f-\u2d70\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e00-\u2e5d\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u2ff0-\u3029\u3030-\u303f\u3041-\u3096\u309b-\u30ff\u3105-\u312f\u3131-\u318e\u3190-\u31e5\u31ef-\u321e\u3220-\ua48c\ua490-\ua4c6\ua4d0-\ua62b\ua640-\ua66e\ua673\ua67e-\ua69d\ua6a0-\ua6ef\ua6f2-\ua6f7\ua700-\ua7cd\ua7d0-\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua824\ua827-\ua82b\ua830-\ua839\ua840-\ua877\ua880-\ua8c3\ua8ce-\ua8d9\ua8f2-\ua8fe\ua900-\ua925\ua92e-\ua946\ua952\ua95f-\ua97c\ua983-\ua9b2\ua9b4-\ua9b5\ua9ba-\ua9bb\ua9be-\ua9bf\ua9c1-\ua9cd\ua9cf-\ua9d9\ua9de-\ua9e4\ua9e6-\ua9fe\uaa00-\uaa28\uaa2f-\uaa30\uaa33-\uaa34\uaa40-\uaa42\uaa44-\uaa4b\uaa4d\uaa50-\uaa59\uaa5c-\uaa7b\uaa7d-\uaaaf\uaab1\uaab5-\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaaeb\uaaee-\uaaf5\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab6b\uab70-\uabe4\uabe6-\uabe7\uabe9-\uabec\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbc2\ufbd3-\ufd8f\ufd92-\ufdc7\ufdcf\ufdf0-\ufdff\ufe10-\ufe19\ufe30-\ufe52\ufe54-\ufe66\ufe68-\ufe6b\ufe70-\ufe74\ufe76-\ufefc\uff01-\uff9d\uffa0-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\uffe0-\uffe6\uffe8-\uffee\ufffc-\ufffd\ud800\udc00-\ud800\udc0b\ud800\udc0d-\ud800\udc26\ud800\udc28-\ud800\udc3a\ud800\udc3c-\ud800\udc3d\ud800\udc3f-\ud800\udc4d\ud800\udc50-\ud800\udc5d\ud800\udc80-\ud800\udcfa\ud800\udd00-\ud800\udd02\ud800\udd07-\ud800\udd33\ud800\udd37-\ud800\udd8e\ud800\udd90-\ud800\udd9c\ud800\udda0\ud800\uddd0-\ud800\uddfc\ud800\ude80-\ud800\ude9c\ud800\udea0-\ud800\uded0\ud800\udee1-\ud800\udefb\ud800\udf00-\ud800\udf23\ud800\udf2d-\ud800\udf4a\ud800\udf50-\ud800\udf75\ud800\udf80-\ud800\udf9d\ud800\udf9f-\ud800\udfc3\ud800\udfc8-\ud800\udfd5\ud801\udc00-\ud801\udc9d\ud801\udca0-\ud801\udca9\ud801\udcb0-\ud801\udcd3\ud801\udcd8-\ud801\udcfb\ud801\udd00-\ud801\udd27\ud801\udd30-\ud801\udd63\ud801\udd6f-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud801\uddc0-\ud801\uddf3\ud801\ude00-\ud801\udf36\ud801\udf40-\ud801\udf55\ud801\udf60-\ud801\udf67\ud801\udf80-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud802\udc00-\ud802\udc05\ud802\udc08\ud802\udc0a-\ud802\udc35\ud802\udc37-\ud802\udc38\ud802\udc3c\ud802\udc3f-\ud802\udc55\ud802\udc57-\ud802\udc9e\ud802\udca7-\ud802\udcaf\ud802\udce0-\ud802\udcf2\ud802\udcf4-\ud802\udcf5\ud802\udcfb-\ud802\udd1b\ud802\udd1f-\ud802\udd39\ud802\udd3f\ud802\udd80-\ud802\uddb7\ud802\uddbc-\ud802\uddcf\ud802\uddd2-\ud802\ude00\ud802\ude10-\ud802\ude13\ud802\ude15-\ud802\ude17\ud802\ude19-\ud802\ude35\ud802\ude40-\ud802\ude48\ud802\ude50-\ud802\ude58\ud802\ude60-\ud802\ude9f\ud802\udec0-\ud802\udee4\ud802\udeeb-\ud802\udef6\ud802\udf00-\ud802\udf35\ud802\udf39-\ud802\udf55\ud802\udf58-\ud802\udf72\ud802\udf78-\ud802\udf91\ud802\udf99-\ud802\udf9c\ud802\udfa9-\ud802\udfaf\ud803\udc00-\ud803\udc48\ud803\udc80-\ud803\udcb2\ud803\udcc0-\ud803\udcf2\ud803\udcfa-\ud803\udd23\ud803\udd30-\ud803\udd39\ud803\udd40-\ud803\udd65\ud803\udd6e-\ud803\udd85\ud803\udd8e-\ud803\udd8f\ud803\ude60-\ud803\ude7e\ud803\ude80-\ud803\udea9\ud803\udead\ud803\udeb0-\ud803\udeb1\ud803\udec2-\ud803\udec4\ud803\udf00-\ud803\udf27\ud803\udf30-\ud803\udf45\ud803\udf51-\ud803\udf59\ud803\udf70-\ud803\udf81\ud803\udf86-\ud803\udf89\ud803\udfb0-\ud803\udfcb\ud803\udfe0-\ud803\udff6\ud804\udc00\ud804\udc02-\ud804\udc37\ud804\udc47-\ud804\udc4d\ud804\udc52-\ud804\udc6f\ud804\udc71-\ud804\udc72\ud804\udc75\ud804\udc82-\ud804\udcb2\ud804\udcb7-\ud804\udcb8\ud804\udcbb-\ud804\udcbc\ud804\udcbe-\ud804\udcc1\ud804\udcd0-\ud804\udce8\ud804\udcf0-\ud804\udcf9\ud804\udd03-\ud804\udd26\ud804\udd2c\ud804\udd36-\ud804\udd47\ud804\udd50-\ud804\udd72\ud804\udd74-\ud804\udd76\ud804\udd82-\ud804\uddb5\ud804\uddbf\ud804\uddc1-\ud804\uddc8\ud804\uddcd-\ud804\uddce\ud804\uddd0-\ud804\udddf\ud804\udde1-\ud804\uddf4\ud804\ude00-\ud804\ude11\ud804\ude13-\ud804\ude2e\ud804\ude32-\ud804\ude33\ud804\ude38-\ud804\ude3d\ud804\ude3f-\ud804\ude40\ud804\ude80-\ud804\ude86\ud804\ude88\ud804\ude8a-\ud804\ude8d\ud804\ude8f-\ud804\ude9d\ud804\ude9f-\ud804\udea9\ud804\udeb0-\ud804\udede\ud804\udee0-\ud804\udee2\ud804\udef0-\ud804\udef9\ud804\udf02-\ud804\udf03\ud804\udf05-\ud804\udf0c\ud804\udf0f-\ud804\udf10\ud804\udf13-\ud804\udf28\ud804\udf2a-\ud804\udf30\ud804\udf32-\ud804\udf33\ud804\udf35-\ud804\udf39\ud804\udf3d\ud804\udf3f\ud804\udf41-\ud804\udf44\ud804\udf47-\ud804\udf48\ud804\udf4b-\ud804\udf4c\ud804\udf50\ud804\udf5d-\ud804\udf63\ud804\udf80-\ud804\udf89\ud804\udf8b\ud804\udf8e\ud804\udf90-\ud804\udfb5\ud804\udfb7\ud804\udfb9-\ud804\udfba\ud804\udfca\ud804\udfcc-\ud804\udfcd\ud804\udfd1\ud804\udfd3-\ud804\udfd5\ud804\udfd7-\ud804\udfd8\ud805\udc00-\ud805\udc37\ud805\udc40-\ud805\udc41\ud805\udc45\ud805\udc47-\ud805\udc5b\ud805\udc5d\ud805\udc5f-\ud805\udc61\ud805\udc80-\ud805\udcaf\ud805\udcb1-\ud805\udcb2\ud805\udcb9\ud805\udcbb-\ud805\udcbc\ud805\udcbe\ud805\udcc1\ud805\udcc4-\ud805\udcc7\ud805\udcd0-\ud805\udcd9\ud805\udd80-\ud805\uddae\ud805\uddb0-\ud805\uddb1\ud805\uddb8-\ud805\uddbb\ud805\uddbe\ud805\uddc1-\ud805\udddb\ud805\ude00-\ud805\ude32\ud805\ude3b-\ud805\ude3c\ud805\ude3e\ud805\ude41-\ud805\ude44\ud805\ude50-\ud805\ude59\ud805\ude60-\ud805\ude6c\ud805\ude80-\ud805\udeaa\ud805\udeac\ud805\udeae-\ud805\udeaf\ud805\udeb8-\ud805\udeb9\ud805\udec0-\ud805\udec9\ud805\uded0-\ud805\udee3\ud805\udf00-\ud805\udf1a\ud805\udf1e\ud805\udf20-\ud805\udf21\ud805\udf26\ud805\udf30-\ud805\udf46\ud806\udc00-\ud806\udc2e\ud806\udc38\ud806\udc3b\ud806\udca0-\ud806\udcf2\ud806\udcff-\ud806\udd06\ud806\udd09\ud806\udd0c-\ud806\udd13\ud806\udd15-\ud806\udd16\ud806\udd18-\ud806\udd2f\ud806\udd31-\ud806\udd35\ud806\udd37-\ud806\udd38\ud806\udd3f-\ud806\udd42\ud806\udd44-\ud806\udd46\ud806\udd50-\ud806\udd59\ud806\udda0-\ud806\udda7\ud806\uddaa-\ud806\uddd3\ud806\udddc-\ud806\udddf\ud806\udde1-\ud806\udde4\ud806\ude00\ud806\ude0b-\ud806\ude32\ud806\ude39-\ud806\ude3a\ud806\ude3f-\ud806\ude46\ud806\ude50\ud806\ude57-\ud806\ude58\ud806\ude5c-\ud806\ude89\ud806\ude97\ud806\ude9a-\ud806\udea2\ud806\udeb0-\ud806\udef8\ud806\udf00-\ud806\udf09\ud806\udfc0-\ud806\udfe1\ud806\udff0-\ud806\udff9\ud807\udc00-\ud807\udc08\ud807\udc0a-\ud807\udc2f\ud807\udc3e\ud807\udc40-\ud807\udc45\ud807\udc50-\ud807\udc6c\ud807\udc70-\ud807\udc8f\ud807\udca9\ud807\udcb1\ud807\udcb4\ud807\udd00-\ud807\udd06\ud807\udd08-\ud807\udd09\ud807\udd0b-\ud807\udd30\ud807\udd46\ud807\udd50-\ud807\udd59\ud807\udd60-\ud807\udd65\ud807\udd67-\ud807\udd68\ud807\udd6a-\ud807\udd8e\ud807\udd93-\ud807\udd94\ud807\udd96\ud807\udd98\ud807\udda0-\ud807\udda9\ud807\udee0-\ud807\udef2\ud807\udef5-\ud807\udef8\ud807\udf02-\ud807\udf10\ud807\udf12-\ud807\udf35\ud807\udf3e-\ud807\udf3f\ud807\udf43-\ud807\udf59\ud807\udfb0\ud807\udfc0-\ud807\udff1\ud807\udfff-\ud808\udf99\ud809\udc00-\ud809\udc6e\ud809\udc70-\ud809\udc74\ud809\udc80-\ud809\udd43\ud80b\udf90-\ud80b\udff2\ud80c\udc00-\ud80d\udc2f\ud80d\udc41-\ud80d\udc46\ud80d\udc60-\ud810\udffa\ud811\udc00-\ud811\ude46\ud818\udd00-\ud818\udd1d\ud818\udd2a-\ud818\udd2c\ud818\udd30-\ud818\udd39\ud81a\udc00-\ud81a\ude38\ud81a\ude40-\ud81a\ude5e\ud81a\ude60-\ud81a\ude69\ud81a\ude6e-\ud81a\udebe\ud81a\udec0-\ud81a\udec9\ud81a\uded0-\ud81a\udeed\ud81a\udef5\ud81a\udf00-\ud81a\udf2f\ud81a\udf37-\ud81a\udf45\ud81a\udf50-\ud81a\udf59\ud81a\udf5b-\ud81a\udf61\ud81a\udf63-\ud81a\udf77\ud81a\udf7d-\ud81a\udf8f\ud81b\udd40-\ud81b\udd79\ud81b\ude40-\ud81b\ude9a\ud81b\udf00-\ud81b\udf4a\ud81b\udf50-\ud81b\udf87\ud81b\udf93-\ud81b\udf9f\ud81b\udfe0-\ud81b\udfe3\ud81c\udc00-\ud821\udff7\ud822\udc00-\ud823\udcd5\ud823\udcff-\ud823\udd08\ud82b\udff0-\ud82b\udff3\ud82b\udff5-\ud82b\udffb\ud82b\udffd-\ud82b\udffe\ud82c\udc00-\ud82c\udd22\ud82c\udd32\ud82c\udd50-\ud82c\udd52\ud82c\udd55\ud82c\udd64-\ud82c\udd67\ud82c\udd70-\ud82c\udefb\ud82f\udc00-\ud82f\udc6a\ud82f\udc70-\ud82f\udc7c\ud82f\udc80-\ud82f\udc88\ud82f\udc90-\ud82f\udc99\ud82f\udc9c\ud82f\udc9f\ud833\udc00-\ud833\udcf9\ud833\udd00-\ud833\udeb3\ud833\udf50-\ud833\udfc3\ud834\udc00-\ud834\udcf5\ud834\udd00-\ud834\udd26\ud834\udd29-\ud834\udd64\ud834\udd6a-\ud834\udd6c\ud834\udd83-\ud834\udd84\ud834\udd8c-\ud834\udda9\ud834\uddae-\ud834\uddea\ud834\ude00-\ud834\ude41\ud834\ude45\ud834\udec0-\ud834\uded3\ud834\udee0-\ud834\udef3\ud834\udf00-\ud834\udf56\ud834\udf60-\ud834\udf78\ud835\udc00-\ud835\udc54\ud835\udc56-\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd1e-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd52-\ud835\udea5\ud835\udea8-\ud835\udfcb\ud835\udfce-\ud836\uddff\ud836\ude37-\ud836\ude3a\ud836\ude6d-\ud836\ude74\ud836\ude76-\ud836\ude83\ud836\ude85-\ud836\ude8b\ud837\udf00-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud838\udc30-\ud838\udc6d\ud838\udd00-\ud838\udd2c\ud838\udd37-\ud838\udd3d\ud838\udd40-\ud838\udd49\ud838\udd4e-\ud838\udd4f\ud838\ude90-\ud838\udead\ud838\udec0-\ud838\udeeb\ud838\udef0-\ud838\udef9\ud838\udeff\ud839\udcd0-\ud839\udceb\ud839\udcf0-\ud839\udcf9\ud839\uddd0-\ud839\udded\ud839\uddf0-\ud839\uddfa\ud839\uddff\ud839\udfe0-\ud839\udfe6\ud839\udfe8-\ud839\udfeb\ud839\udfed-\ud839\udfee\ud839\udff0-\ud839\udffe\ud83a\udc00-\ud83a\udcc4\ud83a\udcc7-\ud83a\udccf\ud83a\udd00-\ud83a\udd43\ud83a\udd4b\ud83a\udd50-\ud83a\udd59\ud83a\udd5e-\ud83a\udd5f\ud83b\udc71-\ud83b\udcb4\ud83b\udd01-\ud83b\udd3d\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21-\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51-\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61-\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb\ud83b\udef0-\ud83b\udef1\ud83c\udc00-\ud83c\udc2b\ud83c\udc30-\ud83c\udc93\ud83c\udca0-\ud83c\udcae\ud83c\udcb1-\ud83c\udcbf\ud83c\udcc1-\ud83c\udccf\ud83c\udcd1-\ud83c\udcf5\ud83c\udd00-\ud83c\uddad\ud83c\udde6-\ud83c\ude02\ud83c\ude10-\ud83c\ude3b\ud83c\ude40-\ud83c\ude48\ud83c\ude50-\ud83c\ude51\ud83c\ude60-\ud83c\ude65\ud83c\udf00-\ud83d\uded7\ud83d\udedc-\ud83d\udeec\ud83d\udef0-\ud83d\udefc\ud83d\udf00-\ud83d\udf76\ud83d\udf7b-\ud83d\udfd9\ud83d\udfe0-\ud83d\udfeb\ud83d\udff0\ud83e\udc00-\ud83e\udc0b\ud83e\udc10-\ud83e\udc47\ud83e\udc50-\ud83e\udc59\ud83e\udc60-\ud83e\udc87\ud83e\udc90-\ud83e\udcad\ud83e\udcb0-\ud83e\udcbb\ud83e\udcc0-\ud83e\udcc1\ud83e\udd00-\ud83e\ude53\ud83e\ude60-\ud83e\ude6d\ud83e\ude70-\ud83e\ude7c\ud83e\ude80-\ud83e\ude89\ud83e\ude8f-\ud83e\udec6\ud83e\udece-\ud83e\udedc\ud83e\udedf-\ud83e\udee9\ud83e\udef0-\ud83e\udef8\ud83e\udf00-\ud83e\udf92\ud83e\udf94-\ud83e\udff9\ud840\udc00-\ud869\udedf\ud869\udf00-\ud86d\udf39\ud86d\udf40-\ud86e\udc1d\ud86e\udc20-\ud873\udea1\ud873\udeb0-\ud87a\udfe0\ud87a\udff0-\ud87b\ude5d\ud87e\udc00-\ud87e\ude1d\ud880\udc00-\ud884\udf4a\ud884\udf50-\ud888\udfaf] diff --git a/src/subprojects/packcc/import/char/unicode_general_category.peg b/src/subprojects/packcc/import/char/unicode_general_category.peg new file mode 100644 index 00000000..6c81d6c0 --- /dev/null +++ b/src/subprojects/packcc/import/char/unicode_general_category.peg @@ -0,0 +1,53 @@ +# This file was generated using the script 'unicode_general_category.py'. + +# This file is hereby placed in the public domain. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AS IS AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Unicode_Letter <- Unicode_Cased_Letter / Unicode_Modifier_Letter / Unicode_Other_Letter +Unicode_Cased_Letter <- Unicode_Uppercase_Letter / Unicode_Lowercase_Letter / Unicode_Titlecase_Letter +Unicode_Mark <- Unicode_Nonspacing_Mark / Unicode_Spacing_Mark / Unicode_Enclosing_Mark +Unicode_Number <- Unicode_Decimal_Number / Unicode_Letter_Number / Unicode_Other_Number +Unicode_Punctuation <- Unicode_Connector_Punctuation / Unicode_Dash_Punctuation / Unicode_Open_Punctuation / Unicode_Close_Punctuation / Unicode_Initial_Punctuation / Unicode_Final_Punctuation / Unicode_Other_Punctuation +Unicode_Symbol <- Unicode_Math_Symbol / Unicode_Currency_Symbol / Unicode_Modifier_Symbol / Unicode_Other_Symbol +Unicode_Separator <- Unicode_Space_Separator / Unicode_Line_Separator / Unicode_Paragraph_Separator +Unicode_Other <- Unicode_Control / Unicode_Format / Unicode_Private_Use + +Unicode_Uppercase_Letter <- [\u0041-\u005a\u00c0-\u00d6\u00d8-\u00de\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u037f\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0528\u052a\u052c\u052e\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u13a0-\u13f5\u1c89\u1c90-\u1cba\u1cbd-\u1cbf\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2f\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua698\ua69a\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua796\ua798\ua79a\ua79c\ua79e\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa-\ua7ae\ua7b0-\ua7b4\ua7b6\ua7b8\ua7ba\ua7bc\ua7be\ua7c0\ua7c2\ua7c4-\ua7c7\ua7c9\ua7cb-\ua7cc\ua7d0\ua7d6\ua7d8\ua7da\ua7dc\ua7f5\uff21-\uff3a\ud801\udc00-\ud801\udc27\ud801\udcb0-\ud801\udcd3\ud801\udd70-\ud801\udd7a\ud801\udd7c-\ud801\udd8a\ud801\udd8c-\ud801\udd92\ud801\udd94-\ud801\udd95\ud803\udc80-\ud803\udcb2\ud803\udd50-\ud803\udd65\ud806\udca0-\ud806\udcbf\ud81b\ude40-\ud81b\ude5f\ud835\udc00-\ud835\udc19\ud835\udc34-\ud835\udc4d\ud835\udc68-\ud835\udc81\ud835\udc9c\ud835\udc9e-\ud835\udc9f\ud835\udca2\ud835\udca5-\ud835\udca6\ud835\udca9-\ud835\udcac\ud835\udcae-\ud835\udcb5\ud835\udcd0-\ud835\udce9\ud835\udd04-\ud835\udd05\ud835\udd07-\ud835\udd0a\ud835\udd0d-\ud835\udd14\ud835\udd16-\ud835\udd1c\ud835\udd38-\ud835\udd39\ud835\udd3b-\ud835\udd3e\ud835\udd40-\ud835\udd44\ud835\udd46\ud835\udd4a-\ud835\udd50\ud835\udd6c-\ud835\udd85\ud835\udda0-\ud835\uddb9\ud835\uddd4-\ud835\udded\ud835\ude08-\ud835\ude21\ud835\ude3c-\ud835\ude55\ud835\ude70-\ud835\ude89\ud835\udea8-\ud835\udec0\ud835\udee2-\ud835\udefa\ud835\udf1c-\ud835\udf34\ud835\udf56-\ud835\udf6e\ud835\udf90-\ud835\udfa8\ud835\udfca\ud83a\udd00-\ud83a\udd21] +Unicode_Lowercase_Letter <- [\u0061-\u007a\u00b5\u00df-\u00f6\u00f8-\u00ff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0529\u052b\u052d\u052f\u0560-\u0588\u10d0-\u10fa\u10fd-\u10ff\u13f8-\u13fd\u1c80-\u1c88\u1c8a\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5f\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua699\ua69b\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793-\ua795\ua797\ua799\ua79b\ua79d\ua79f\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7af\ua7b5\ua7b7\ua7b9\ua7bb\ua7bd\ua7bf\ua7c1\ua7c3\ua7c8\ua7ca\ua7cd\ua7d1\ua7d3\ua7d5\ua7d7\ua7d9\ua7db\ua7f6\ua7fa\uab30-\uab5a\uab60-\uab68\uab70-\uabbf\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\ud801\udc28-\ud801\udc4f\ud801\udcd8-\ud801\udcfb\ud801\udd97-\ud801\udda1\ud801\udda3-\ud801\uddb1\ud801\uddb3-\ud801\uddb9\ud801\uddbb-\ud801\uddbc\ud803\udcc0-\ud803\udcf2\ud803\udd70-\ud803\udd85\ud806\udcc0-\ud806\udcdf\ud81b\ude60-\ud81b\ude7f\ud835\udc1a-\ud835\udc33\ud835\udc4e-\ud835\udc54\ud835\udc56-\ud835\udc67\ud835\udc82-\ud835\udc9b\ud835\udcb6-\ud835\udcb9\ud835\udcbb\ud835\udcbd-\ud835\udcc3\ud835\udcc5-\ud835\udccf\ud835\udcea-\ud835\udd03\ud835\udd1e-\ud835\udd37\ud835\udd52-\ud835\udd6b\ud835\udd86-\ud835\udd9f\ud835\uddba-\ud835\uddd3\ud835\uddee-\ud835\ude07\ud835\ude22-\ud835\ude3b\ud835\ude56-\ud835\ude6f\ud835\ude8a-\ud835\udea5\ud835\udec2-\ud835\udeda\ud835\udedc-\ud835\udee1\ud835\udefc-\ud835\udf14\ud835\udf16-\ud835\udf1b\ud835\udf36-\ud835\udf4e\ud835\udf50-\ud835\udf55\ud835\udf70-\ud835\udf88\ud835\udf8a-\ud835\udf8f\ud835\udfaa-\ud835\udfc2\ud835\udfc4-\ud835\udfc9\ud835\udfcb\ud837\udf00-\ud837\udf09\ud837\udf0b-\ud837\udf1e\ud837\udf25-\ud837\udf2a\ud83a\udd22-\ud83a\udd43] +Unicode_Titlecase_Letter <- [\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc] +Unicode_Modifier_Letter <- [\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u08c9\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua69c-\ua69d\ua717-\ua71f\ua770\ua788\ua7f2-\ua7f4\ua7f8-\ua7f9\ua9cf\ua9e6\uaa70\uaadd\uaaf3-\uaaf4\uab5c-\uab5f\uab69\uff70\uff9e-\uff9f\ud801\udf80-\ud801\udf85\ud801\udf87-\ud801\udfb0\ud801\udfb2-\ud801\udfba\ud803\udd4e\ud803\udd6f\ud81a\udf40-\ud81a\udf43\ud81b\udd40-\ud81b\udd42\ud81b\udd6b-\ud81b\udd6c\ud81b\udf93-\ud81b\udf9f\ud81b\udfe0-\ud81b\udfe1\ud81b\udfe3\ud82b\udff0-\ud82b\udff3\ud82b\udff5-\ud82b\udffb\ud82b\udffd-\ud82b\udffe\ud838\udc30-\ud838\udc6d\ud838\udd37-\ud838\udd3d\ud839\udceb\ud83a\udd4b] +Unicode_Other_Letter <- [\u00aa\u00ba\u01bb\u01c0-\u01c3\u0294\u05d0-\u05ea\u05ef-\u05f2\u0620-\u063f\u0641-\u064a\u066e-\u066f\u0671-\u06d3\u06d5\u06ee-\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u0800-\u0815\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c8\u0904-\u0939\u093d\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u09fc\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0-\u0ae1\u0af9\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60-\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd-\u0cde\u0ce0-\u0ce1\u0cf1-\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32-\u0e33\u0e40-\u0e45\u0e81-\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2-\u0eb3\u0ebd\u0ec0-\u0ec4\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065-\u1066\u106e-\u1070\u1075-\u1081\u108e\u1100-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16f1-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17dc\u1820-\u1842\u1844-\u1878\u1880-\u1884\u1887-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae-\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c77\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5-\u1cf6\u1cfa\u2135-\u2138\u2d30-\u2d67\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3006\u303c\u3041-\u3096\u309f\u30a1-\u30fa\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400\u4dbf\u4e00\u9fff-\ua014\ua016-\ua48c\ua4d0-\ua4f7\ua500-\ua60b\ua610-\ua61f\ua62a-\ua62b\ua66e\ua6a0-\ua6e5\ua78f\ua7f7\ua7fb-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd-\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9e0-\ua9e4\ua9e7-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa6f\uaa71-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5-\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadc\uaae0-\uaaea\uaaf2\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff66-\uff6f\uff71-\uff9d\uffa0-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\ud800\udc00-\ud800\udc0b\ud800\udc0d-\ud800\udc26\ud800\udc28-\ud800\udc3a\ud800\udc3c-\ud800\udc3d\ud800\udc3f-\ud800\udc4d\ud800\udc50-\ud800\udc5d\ud800\udc80-\ud800\udcfa\ud800\ude80-\ud800\ude9c\ud800\udea0-\ud800\uded0\ud800\udf00-\ud800\udf1f\ud800\udf2d-\ud800\udf40\ud800\udf42-\ud800\udf49\ud800\udf50-\ud800\udf75\ud800\udf80-\ud800\udf9d\ud800\udfa0-\ud800\udfc3\ud800\udfc8-\ud800\udfcf\ud801\udc50-\ud801\udc9d\ud801\udd00-\ud801\udd27\ud801\udd30-\ud801\udd63\ud801\uddc0-\ud801\uddf3\ud801\ude00-\ud801\udf36\ud801\udf40-\ud801\udf55\ud801\udf60-\ud801\udf67\ud802\udc00-\ud802\udc05\ud802\udc08\ud802\udc0a-\ud802\udc35\ud802\udc37-\ud802\udc38\ud802\udc3c\ud802\udc3f-\ud802\udc55\ud802\udc60-\ud802\udc76\ud802\udc80-\ud802\udc9e\ud802\udce0-\ud802\udcf2\ud802\udcf4-\ud802\udcf5\ud802\udd00-\ud802\udd15\ud802\udd20-\ud802\udd39\ud802\udd80-\ud802\uddb7\ud802\uddbe-\ud802\uddbf\ud802\ude00\ud802\ude10-\ud802\ude13\ud802\ude15-\ud802\ude17\ud802\ude19-\ud802\ude35\ud802\ude60-\ud802\ude7c\ud802\ude80-\ud802\ude9c\ud802\udec0-\ud802\udec7\ud802\udec9-\ud802\udee4\ud802\udf00-\ud802\udf35\ud802\udf40-\ud802\udf55\ud802\udf60-\ud802\udf72\ud802\udf80-\ud802\udf91\ud803\udc00-\ud803\udc48\ud803\udd00-\ud803\udd23\ud803\udd4a-\ud803\udd4d\ud803\udd4f\ud803\ude80-\ud803\udea9\ud803\udeb0-\ud803\udeb1\ud803\udec2-\ud803\udec4\ud803\udf00-\ud803\udf1c\ud803\udf27\ud803\udf30-\ud803\udf45\ud803\udf70-\ud803\udf81\ud803\udfb0-\ud803\udfc4\ud803\udfe0-\ud803\udff6\ud804\udc03-\ud804\udc37\ud804\udc71-\ud804\udc72\ud804\udc75\ud804\udc83-\ud804\udcaf\ud804\udcd0-\ud804\udce8\ud804\udd03-\ud804\udd26\ud804\udd44\ud804\udd47\ud804\udd50-\ud804\udd72\ud804\udd76\ud804\udd83-\ud804\uddb2\ud804\uddc1-\ud804\uddc4\ud804\uddda\ud804\udddc\ud804\ude00-\ud804\ude11\ud804\ude13-\ud804\ude2b\ud804\ude3f-\ud804\ude40\ud804\ude80-\ud804\ude86\ud804\ude88\ud804\ude8a-\ud804\ude8d\ud804\ude8f-\ud804\ude9d\ud804\ude9f-\ud804\udea8\ud804\udeb0-\ud804\udede\ud804\udf05-\ud804\udf0c\ud804\udf0f-\ud804\udf10\ud804\udf13-\ud804\udf28\ud804\udf2a-\ud804\udf30\ud804\udf32-\ud804\udf33\ud804\udf35-\ud804\udf39\ud804\udf3d\ud804\udf50\ud804\udf5d-\ud804\udf61\ud804\udf80-\ud804\udf89\ud804\udf8b\ud804\udf8e\ud804\udf90-\ud804\udfb5\ud804\udfb7\ud804\udfd1\ud804\udfd3\ud805\udc00-\ud805\udc34\ud805\udc47-\ud805\udc4a\ud805\udc5f-\ud805\udc61\ud805\udc80-\ud805\udcaf\ud805\udcc4-\ud805\udcc5\ud805\udcc7\ud805\udd80-\ud805\uddae\ud805\uddd8-\ud805\udddb\ud805\ude00-\ud805\ude2f\ud805\ude44\ud805\ude80-\ud805\udeaa\ud805\udeb8\ud805\udf00-\ud805\udf1a\ud805\udf40-\ud805\udf46\ud806\udc00-\ud806\udc2b\ud806\udcff-\ud806\udd06\ud806\udd09\ud806\udd0c-\ud806\udd13\ud806\udd15-\ud806\udd16\ud806\udd18-\ud806\udd2f\ud806\udd3f\ud806\udd41\ud806\udda0-\ud806\udda7\ud806\uddaa-\ud806\uddd0\ud806\udde1\ud806\udde3\ud806\ude00\ud806\ude0b-\ud806\ude32\ud806\ude3a\ud806\ude50\ud806\ude5c-\ud806\ude89\ud806\ude9d\ud806\udeb0-\ud806\udef8\ud806\udfc0-\ud806\udfe0\ud807\udc00-\ud807\udc08\ud807\udc0a-\ud807\udc2e\ud807\udc40\ud807\udc72-\ud807\udc8f\ud807\udd00-\ud807\udd06\ud807\udd08-\ud807\udd09\ud807\udd0b-\ud807\udd30\ud807\udd46\ud807\udd60-\ud807\udd65\ud807\udd67-\ud807\udd68\ud807\udd6a-\ud807\udd89\ud807\udd98\ud807\udee0-\ud807\udef2\ud807\udf02\ud807\udf04-\ud807\udf10\ud807\udf12-\ud807\udf33\ud807\udfb0\ud808\udc00-\ud808\udf99\ud809\udc80-\ud809\udd43\ud80b\udf90-\ud80b\udff0\ud80c\udc00-\ud80d\udc2f\ud80d\udc41-\ud80d\udc46\ud80d\udc60-\ud810\udffa\ud811\udc00-\ud811\ude46\ud818\udd00-\ud818\udd1d\ud81a\udc00-\ud81a\ude38\ud81a\ude40-\ud81a\ude5e\ud81a\ude70-\ud81a\udebe\ud81a\uded0-\ud81a\udeed\ud81a\udf00-\ud81a\udf2f\ud81a\udf63-\ud81a\udf77\ud81a\udf7d-\ud81a\udf8f\ud81b\udd43-\ud81b\udd6a\ud81b\udf00-\ud81b\udf4a\ud81b\udf50\ud81c\udc00\ud821\udff7\ud822\udc00-\ud823\udcd5\ud823\udcff-\ud823\udd00\ud823\udd08\ud82c\udc00-\ud82c\udd22\ud82c\udd32\ud82c\udd50-\ud82c\udd52\ud82c\udd55\ud82c\udd64-\ud82c\udd67\ud82c\udd70-\ud82c\udefb\ud82f\udc00-\ud82f\udc6a\ud82f\udc70-\ud82f\udc7c\ud82f\udc80-\ud82f\udc88\ud82f\udc90-\ud82f\udc99\ud837\udf0a\ud838\udd00-\ud838\udd2c\ud838\udd4e\ud838\ude90-\ud838\udead\ud838\udec0-\ud838\udeeb\ud839\udcd0-\ud839\udcea\ud839\uddd0-\ud839\udded\ud839\uddf0\ud839\udfe0-\ud839\udfe6\ud839\udfe8-\ud839\udfeb\ud839\udfed-\ud839\udfee\ud839\udff0-\ud839\udffe\ud83a\udc00-\ud83a\udcc4\ud83b\ude00-\ud83b\ude03\ud83b\ude05-\ud83b\ude1f\ud83b\ude21-\ud83b\ude22\ud83b\ude24\ud83b\ude27\ud83b\ude29-\ud83b\ude32\ud83b\ude34-\ud83b\ude37\ud83b\ude39\ud83b\ude3b\ud83b\ude42\ud83b\ude47\ud83b\ude49\ud83b\ude4b\ud83b\ude4d-\ud83b\ude4f\ud83b\ude51-\ud83b\ude52\ud83b\ude54\ud83b\ude57\ud83b\ude59\ud83b\ude5b\ud83b\ude5d\ud83b\ude5f\ud83b\ude61-\ud83b\ude62\ud83b\ude64\ud83b\ude67-\ud83b\ude6a\ud83b\ude6c-\ud83b\ude72\ud83b\ude74-\ud83b\ude77\ud83b\ude79-\ud83b\ude7c\ud83b\ude7e\ud83b\ude80-\ud83b\ude89\ud83b\ude8b-\ud83b\ude9b\ud83b\udea1-\ud83b\udea3\ud83b\udea5-\ud83b\udea9\ud83b\udeab-\ud83b\udebb\ud840\udc00\ud869\udedf\ud869\udf00\ud86d\udf39\ud86d\udf40\ud86e\udc1d\ud86e\udc20\ud873\udea1\ud873\udeb0\ud87a\udfe0\ud87a\udff0\ud87b\ude5d\ud87e\udc00-\ud87e\ude1d\ud880\udc00\ud884\udf4a\ud884\udf50\ud888\udfaf] +Unicode_Nonspacing_Mark <- [\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2-\u09e3\u09fe\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0afa-\u0aff\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b55-\u0b56\u0b62-\u0b63\u0b82\u0bc0\u0bcd\u0c00\u0c04\u0c3c\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc6\u0ccc-\u0ccd\u0ce2-\u0ce3\u0d00-\u0d01\u0d3b-\u0d3c\u0d41-\u0d44\u0d4d\u0d62-\u0d63\u0d81\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1733\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u180f\u1885-\u1886\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9\u1dc0-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u3099-\u309a\ua66f\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua82c\ua8c4-\ua8c5\ua8e0-\ua8f1\ua8ff\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc-\ua9bd\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ud800\uddfd\ud800\udee0\ud800\udf76-\ud800\udf7a\ud802\ude01-\ud802\ude03\ud802\ude05-\ud802\ude06\ud802\ude0c-\ud802\ude0f\ud802\ude38-\ud802\ude3a\ud802\ude3f\ud802\udee5-\ud802\udee6\ud803\udd24-\ud803\udd27\ud803\udd69-\ud803\udd6d\ud803\udeab-\ud803\udeac\ud803\udefc-\ud803\udeff\ud803\udf46-\ud803\udf50\ud803\udf82-\ud803\udf85\ud804\udc01\ud804\udc38-\ud804\udc46\ud804\udc70\ud804\udc73-\ud804\udc74\ud804\udc7f-\ud804\udc81\ud804\udcb3-\ud804\udcb6\ud804\udcb9-\ud804\udcba\ud804\udcc2\ud804\udd00-\ud804\udd02\ud804\udd27-\ud804\udd2b\ud804\udd2d-\ud804\udd34\ud804\udd73\ud804\udd80-\ud804\udd81\ud804\uddb6-\ud804\uddbe\ud804\uddc9-\ud804\uddcc\ud804\uddcf\ud804\ude2f-\ud804\ude31\ud804\ude34\ud804\ude36-\ud804\ude37\ud804\ude3e\ud804\ude41\ud804\udedf\ud804\udee3-\ud804\udeea\ud804\udf00-\ud804\udf01\ud804\udf3b-\ud804\udf3c\ud804\udf40\ud804\udf66-\ud804\udf6c\ud804\udf70-\ud804\udf74\ud804\udfbb-\ud804\udfc0\ud804\udfce\ud804\udfd0\ud804\udfd2\ud804\udfe1-\ud804\udfe2\ud805\udc38-\ud805\udc3f\ud805\udc42-\ud805\udc44\ud805\udc46\ud805\udc5e\ud805\udcb3-\ud805\udcb8\ud805\udcba\ud805\udcbf-\ud805\udcc0\ud805\udcc2-\ud805\udcc3\ud805\uddb2-\ud805\uddb5\ud805\uddbc-\ud805\uddbd\ud805\uddbf-\ud805\uddc0\ud805\udddc-\ud805\udddd\ud805\ude33-\ud805\ude3a\ud805\ude3d\ud805\ude3f-\ud805\ude40\ud805\udeab\ud805\udead\ud805\udeb0-\ud805\udeb5\ud805\udeb7\ud805\udf1d\ud805\udf1f\ud805\udf22-\ud805\udf25\ud805\udf27-\ud805\udf2b\ud806\udc2f-\ud806\udc37\ud806\udc39-\ud806\udc3a\ud806\udd3b-\ud806\udd3c\ud806\udd3e\ud806\udd43\ud806\uddd4-\ud806\uddd7\ud806\uddda-\ud806\udddb\ud806\udde0\ud806\ude01-\ud806\ude0a\ud806\ude33-\ud806\ude38\ud806\ude3b-\ud806\ude3e\ud806\ude47\ud806\ude51-\ud806\ude56\ud806\ude59-\ud806\ude5b\ud806\ude8a-\ud806\ude96\ud806\ude98-\ud806\ude99\ud807\udc30-\ud807\udc36\ud807\udc38-\ud807\udc3d\ud807\udc3f\ud807\udc92-\ud807\udca7\ud807\udcaa-\ud807\udcb0\ud807\udcb2-\ud807\udcb3\ud807\udcb5-\ud807\udcb6\ud807\udd31-\ud807\udd36\ud807\udd3a\ud807\udd3c-\ud807\udd3d\ud807\udd3f-\ud807\udd45\ud807\udd47\ud807\udd90-\ud807\udd91\ud807\udd95\ud807\udd97\ud807\udef3-\ud807\udef4\ud807\udf00-\ud807\udf01\ud807\udf36-\ud807\udf3a\ud807\udf40\ud807\udf42\ud807\udf5a\ud80d\udc40\ud80d\udc47-\ud80d\udc55\ud818\udd1e-\ud818\udd29\ud818\udd2d-\ud818\udd2f\ud81a\udef0-\ud81a\udef4\ud81a\udf30-\ud81a\udf36\ud81b\udf4f\ud81b\udf8f-\ud81b\udf92\ud81b\udfe4\ud82f\udc9d-\ud82f\udc9e\ud833\udf00-\ud833\udf2d\ud833\udf30-\ud833\udf46\ud834\udd67-\ud834\udd69\ud834\udd7b-\ud834\udd82\ud834\udd85-\ud834\udd8b\ud834\uddaa-\ud834\uddad\ud834\ude42-\ud834\ude44\ud836\ude00-\ud836\ude36\ud836\ude3b-\ud836\ude6c\ud836\ude75\ud836\ude84\ud836\ude9b-\ud836\ude9f\ud836\udea1-\ud836\udeaf\ud838\udc00-\ud838\udc06\ud838\udc08-\ud838\udc18\ud838\udc1b-\ud838\udc21\ud838\udc23-\ud838\udc24\ud838\udc26-\ud838\udc2a\ud838\udc8f\ud838\udd30-\ud838\udd36\ud838\udeae\ud838\udeec-\ud838\udeef\ud839\udcec-\ud839\udcef\ud839\uddee-\ud839\uddef\ud83a\udcd0-\ud83a\udcd6\ud83a\udd44-\ud83a\udd4a\udb40\udd00-\udb40\uddef] +Unicode_Spacing_Mark <- [\u0903\u093b\u093e-\u0940\u0949-\u094c\u094e-\u094f\u0982-\u0983\u09be-\u09c0\u09c7-\u09c8\u09cb-\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb-\u0acc\u0b02-\u0b03\u0b3e\u0b40\u0b47-\u0b48\u0b4b-\u0b4c\u0b57\u0bbe-\u0bbf\u0bc1-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82-\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7-\u0cc8\u0cca-\u0ccb\u0cd5-\u0cd6\u0cf3\u0d02-\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82-\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2-\u0df3\u0f3e-\u0f3f\u0f7f\u102b-\u102c\u1031\u1038\u103b-\u103c\u1056-\u1057\u1062-\u1064\u1067-\u106d\u1083-\u1084\u1087-\u108c\u108f\u109a-\u109c\u1715\u1734\u17b6\u17be-\u17c5\u17c7-\u17c8\u1923-\u1926\u1929-\u192b\u1930-\u1931\u1933-\u1938\u1a19-\u1a1a\u1a55\u1a57\u1a61\u1a63-\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43-\u1b44\u1b82\u1ba1\u1ba6-\u1ba7\u1baa\u1be7\u1bea-\u1bec\u1bee\u1bf2-\u1bf3\u1c24-\u1c2b\u1c34-\u1c35\u1ce1\u1cf7\u302e-\u302f\ua823-\ua824\ua827\ua880-\ua881\ua8b4-\ua8c3\ua952-\ua953\ua983\ua9b4-\ua9b5\ua9ba-\ua9bb\ua9be-\ua9c0\uaa2f-\uaa30\uaa33-\uaa34\uaa4d\uaa7b\uaa7d\uaaeb\uaaee-\uaaef\uaaf5\uabe3-\uabe4\uabe6-\uabe7\uabe9-\uabea\uabec\ud804\udc00\ud804\udc02\ud804\udc82\ud804\udcb0-\ud804\udcb2\ud804\udcb7-\ud804\udcb8\ud804\udd2c\ud804\udd45-\ud804\udd46\ud804\udd82\ud804\uddb3-\ud804\uddb5\ud804\uddbf-\ud804\uddc0\ud804\uddce\ud804\ude2c-\ud804\ude2e\ud804\ude32-\ud804\ude33\ud804\ude35\ud804\udee0-\ud804\udee2\ud804\udf02-\ud804\udf03\ud804\udf3e-\ud804\udf3f\ud804\udf41-\ud804\udf44\ud804\udf47-\ud804\udf48\ud804\udf4b-\ud804\udf4d\ud804\udf57\ud804\udf62-\ud804\udf63\ud804\udfb8-\ud804\udfba\ud804\udfc2\ud804\udfc5\ud804\udfc7-\ud804\udfca\ud804\udfcc-\ud804\udfcd\ud804\udfcf\ud805\udc35-\ud805\udc37\ud805\udc40-\ud805\udc41\ud805\udc45\ud805\udcb0-\ud805\udcb2\ud805\udcb9\ud805\udcbb-\ud805\udcbe\ud805\udcc1\ud805\uddaf-\ud805\uddb1\ud805\uddb8-\ud805\uddbb\ud805\uddbe\ud805\ude30-\ud805\ude32\ud805\ude3b-\ud805\ude3c\ud805\ude3e\ud805\udeac\ud805\udeae-\ud805\udeaf\ud805\udeb6\ud805\udf1e\ud805\udf20-\ud805\udf21\ud805\udf26\ud806\udc2c-\ud806\udc2e\ud806\udc38\ud806\udd30-\ud806\udd35\ud806\udd37-\ud806\udd38\ud806\udd3d\ud806\udd40\ud806\udd42\ud806\uddd1-\ud806\uddd3\ud806\udddc-\ud806\udddf\ud806\udde4\ud806\ude39\ud806\ude57-\ud806\ude58\ud806\ude97\ud807\udc2f\ud807\udc3e\ud807\udca9\ud807\udcb1\ud807\udcb4\ud807\udd8a-\ud807\udd8e\ud807\udd93-\ud807\udd94\ud807\udd96\ud807\udef5-\ud807\udef6\ud807\udf03\ud807\udf34-\ud807\udf35\ud807\udf3e-\ud807\udf3f\ud807\udf41\ud818\udd2a-\ud818\udd2c\ud81b\udf51-\ud81b\udf87\ud81b\udff0-\ud81b\udff1\ud834\udd65-\ud834\udd66\ud834\udd6d-\ud834\udd72] +Unicode_Enclosing_Mark <- [\u0488-\u0489\u1abe\u20dd-\u20e0\u20e2-\u20e4\ua670-\ua672] +Unicode_Decimal_Number <- [\u0030-\u0039\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0de6-\u0def\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\ua9f0-\ua9f9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19\ud801\udca0-\ud801\udca9\ud803\udd30-\ud803\udd39\ud803\udd40-\ud803\udd49\ud804\udc66-\ud804\udc6f\ud804\udcf0-\ud804\udcf9\ud804\udd36-\ud804\udd3f\ud804\uddd0-\ud804\uddd9\ud804\udef0-\ud804\udef9\ud805\udc50-\ud805\udc59\ud805\udcd0-\ud805\udcd9\ud805\ude50-\ud805\ude59\ud805\udec0-\ud805\udec9\ud805\uded0-\ud805\udee3\ud805\udf30-\ud805\udf39\ud806\udce0-\ud806\udce9\ud806\udd50-\ud806\udd59\ud806\udff0-\ud806\udff9\ud807\udc50-\ud807\udc59\ud807\udd50-\ud807\udd59\ud807\udda0-\ud807\udda9\ud807\udf50-\ud807\udf59\ud818\udd30-\ud818\udd39\ud81a\ude60-\ud81a\ude69\ud81a\udec0-\ud81a\udec9\ud81a\udf50-\ud81a\udf59\ud81b\udd70-\ud81b\udd79\ud833\udcf0-\ud833\udcf9\ud835\udfce-\ud835\udfff\ud838\udd40-\ud838\udd49\ud838\udef0-\ud838\udef9\ud839\udcf0-\ud839\udcf9\ud839\uddf1-\ud839\uddfa\ud83a\udd50-\ud83a\udd59\ud83e\udff0-\ud83e\udff9] +Unicode_Letter_Number <- [\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef\ud800\udd40-\ud800\udd74\ud800\udf41\ud800\udf4a\ud800\udfd1-\ud800\udfd5\ud809\udc00-\ud809\udc6e] +Unicode_Other_Number <- [\u00b2-\u00b3\u00b9\u00bc-\u00be\u09f4-\u09f9\u0b72-\u0b77\u0bf0-\u0bf2\u0c78-\u0c7e\u0d58-\u0d5e\u0d70-\u0d78\u0f2a-\u0f33\u1369-\u137c\u17f0-\u17f9\u19da\u2070\u2074-\u2079\u2080-\u2089\u2150-\u215f\u2189\u2460-\u249b\u24ea-\u24ff\u2776-\u2793\u2cfd\u3192-\u3195\u3220-\u3229\u3248-\u324f\u3251-\u325f\u3280-\u3289\u32b1-\u32bf\ua830-\ua835\ud800\udd07-\ud800\udd33\ud800\udd75-\ud800\udd78\ud800\udd8a-\ud800\udd8b\ud800\udee1-\ud800\udefb\ud800\udf20-\ud800\udf23\ud802\udc58-\ud802\udc5f\ud802\udc79-\ud802\udc7f\ud802\udca7-\ud802\udcaf\ud802\udcfb-\ud802\udcff\ud802\udd16-\ud802\udd1b\ud802\uddbc-\ud802\uddbd\ud802\uddc0-\ud802\uddcf\ud802\uddd2-\ud802\uddff\ud802\ude40-\ud802\ude48\ud802\ude7d-\ud802\ude7e\ud802\ude9d-\ud802\ude9f\ud802\udeeb-\ud802\udeef\ud802\udf58-\ud802\udf5f\ud802\udf78-\ud802\udf7f\ud802\udfa9-\ud802\udfaf\ud803\udcfa-\ud803\udcff\ud803\ude60-\ud803\ude7e\ud803\udf1d-\ud803\udf26\ud803\udf51-\ud803\udf54\ud803\udfc5-\ud803\udfcb\ud804\udc52-\ud804\udc65\ud804\udde1-\ud804\uddf4\ud805\udf3a-\ud805\udf3b\ud806\udcea-\ud806\udcf2\ud807\udc5a-\ud807\udc6c\ud807\udfc0-\ud807\udfd4\ud81a\udf5b-\ud81a\udf61\ud81b\ude80-\ud81b\ude96\ud834\udec0-\ud834\uded3\ud834\udee0-\ud834\udef3\ud834\udf60-\ud834\udf78\ud83a\udcc7-\ud83a\udccf\ud83b\udc71-\ud83b\udcab\ud83b\udcad-\ud83b\udcaf\ud83b\udcb1-\ud83b\udcb4\ud83b\udd01-\ud83b\udd2d\ud83b\udd2f-\ud83b\udd3d\ud83c\udd00-\ud83c\udd0c] +Unicode_Connector_Punctuation <- [\u005f\u203f-\u2040\u2054\ufe33-\ufe34\ufe4d-\ufe4f\uff3f] +Unicode_Dash_Punctuation <- [\u002d\u058a\u05be\u1400\u1806\u2010-\u2015\u2e17\u2e1a\u2e3a-\u2e3b\u2e40\u2e5d\u301c\u3030\u30a0\ufe31-\ufe32\ufe58\ufe63\uff0d\ud803\udd6e\ud803\udead] +Unicode_Open_Punctuation <- [\u0028\u005b\u007b\u0f3a\u0f3c\u169b\u201a\u201e\u2045\u207d\u208d\u2308\u230a\u2329\u2768\u276a\u276c\u276e\u2770\u2772\u2774\u27c5\u27e6\u27e8\u27ea\u27ec\u27ee\u2983\u2985\u2987\u2989\u298b\u298d\u298f\u2991\u2993\u2995\u2997\u29d8\u29da\u29fc\u2e22\u2e24\u2e26\u2e28\u2e42\u2e55\u2e57\u2e59\u2e5b\u3008\u300a\u300c\u300e\u3010\u3014\u3016\u3018\u301a\u301d\ufd3f\ufe17\ufe35\ufe37\ufe39\ufe3b\ufe3d\ufe3f\ufe41\ufe43\ufe47\ufe59\ufe5b\ufe5d\uff08\uff3b\uff5b\uff5f\uff62] +Unicode_Close_Punctuation <- [\u0029\u005d\u007d\u0f3b\u0f3d\u169c\u2046\u207e\u208e\u2309\u230b\u232a\u2769\u276b\u276d\u276f\u2771\u2773\u2775\u27c6\u27e7\u27e9\u27eb\u27ed\u27ef\u2984\u2986\u2988\u298a\u298c\u298e\u2990\u2992\u2994\u2996\u2998\u29d9\u29db\u29fd\u2e23\u2e25\u2e27\u2e29\u2e56\u2e58\u2e5a\u2e5c\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\u301e-\u301f\ufd3e\ufe18\ufe36\ufe38\ufe3a\ufe3c\ufe3e\ufe40\ufe42\ufe44\ufe48\ufe5a\ufe5c\ufe5e\uff09\uff3d\uff5d\uff60\uff63] +Unicode_Initial_Punctuation <- [\u00ab\u2018\u201b-\u201c\u201f\u2039\u2e02\u2e04\u2e09\u2e0c\u2e1c\u2e20] +Unicode_Final_Punctuation <- [\u00bb\u2019\u201d\u203a\u2e03\u2e05\u2e0a\u2e0d\u2e1d\u2e21] +Unicode_Other_Punctuation <- [\u0021-\u0023\u0025-\u0027\u002a\u002c\u002e-\u002f\u003a-\u003b\u003f-\u0040\u005c\u00a1\u00a7\u00b6-\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3-\u05f4\u0609-\u060a\u060c-\u060d\u061b\u061d-\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964-\u0965\u0970\u09fd\u0a76\u0af0\u0c77\u0c84\u0df4\u0e4f\u0e5a-\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9-\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166e\u16eb-\u16ed\u1735-\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944-\u1945\u1a1e-\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b4e-\u1b4f\u1b5a-\u1b60\u1b7d-\u1b7f\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e-\u1c7f\u1cc0-\u1cc7\u1cd3\u2016-\u2017\u2020-\u2027\u2030-\u2038\u203b-\u203e\u2041-\u2043\u2047-\u2051\u2053\u2055-\u205e\u2cf9-\u2cfc\u2cfe-\u2cff\u2d70\u2e00-\u2e01\u2e06-\u2e08\u2e0b\u2e0e-\u2e16\u2e18-\u2e19\u2e1b\u2e1e-\u2e1f\u2e2a-\u2e2e\u2e30-\u2e39\u2e3c-\u2e3f\u2e41\u2e43-\u2e4f\u2e52-\u2e54\u3001-\u3003\u303d\u30fb\ua4fe-\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce-\ua8cf\ua8f8-\ua8fa\ua8fc\ua92e-\ua92f\ua95f\ua9c1-\ua9cd\ua9de-\ua9df\uaa5c-\uaa5f\uaade-\uaadf\uaaf0-\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45-\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a-\ufe6b\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e-\uff0f\uff1a-\uff1b\uff1f-\uff20\uff3c\uff61\uff64-\uff65\ud800\udd00-\ud800\udd02\ud800\udf9f\ud800\udfd0\ud801\udd6f\ud802\udc57\ud802\udd1f\ud802\udd3f\ud802\ude50-\ud802\ude58\ud802\ude7f\ud802\udef0-\ud802\udef6\ud802\udf39-\ud802\udf3f\ud802\udf99-\ud802\udf9c\ud803\udf55-\ud803\udf59\ud803\udf86-\ud803\udf89\ud804\udc47-\ud804\udc4d\ud804\udcbb-\ud804\udcbc\ud804\udcbe-\ud804\udcc1\ud804\udd40-\ud804\udd43\ud804\udd74-\ud804\udd75\ud804\uddc5-\ud804\uddc8\ud804\uddcd\ud804\udddb\ud804\udddd-\ud804\udddf\ud804\ude38-\ud804\ude3d\ud804\udea9\ud804\udfd4-\ud804\udfd5\ud804\udfd7-\ud804\udfd8\ud805\udc4b-\ud805\udc4f\ud805\udc5a-\ud805\udc5b\ud805\udc5d\ud805\udcc6\ud805\uddc1-\ud805\uddd7\ud805\ude41-\ud805\ude43\ud805\ude60-\ud805\ude6c\ud805\udeb9\ud805\udf3c-\ud805\udf3e\ud806\udc3b\ud806\udd44-\ud806\udd46\ud806\udde2\ud806\ude3f-\ud806\ude46\ud806\ude9a-\ud806\ude9c\ud806\ude9e-\ud806\udea2\ud806\udf00-\ud806\udf09\ud806\udfe1\ud807\udc41-\ud807\udc45\ud807\udc70-\ud807\udc71\ud807\udef7-\ud807\udef8\ud807\udf43-\ud807\udf4f\ud807\udfff\ud809\udc70-\ud809\udc74\ud80b\udff1-\ud80b\udff2\ud81a\ude6e-\ud81a\ude6f\ud81a\udef5\ud81a\udf37-\ud81a\udf3b\ud81a\udf44\ud81b\udd6d-\ud81b\udd6f\ud81b\ude97-\ud81b\ude9a\ud81b\udfe2\ud82f\udc9f\ud836\ude87-\ud836\ude8b\ud839\uddff\ud83a\udd5e-\ud83a\udd5f] +Unicode_Math_Symbol <- [\u002b\u003c-\u003e\u007c\u007e\u00ac\u00b1\u00d7\u00f7\u03f6\u0606-\u0608\u2044\u2052\u207a-\u207c\u208a-\u208c\u2118\u2140-\u2144\u214b\u2190-\u2194\u219a-\u219b\u21a0\u21a3\u21a6\u21ae\u21ce-\u21cf\u21d2\u21d4\u21f4-\u22ff\u2320-\u2321\u237c\u239b-\u23b3\u23dc-\u23e1\u25b7\u25c1\u25f8-\u25ff\u266f\u27c0-\u27c4\u27c7-\u27e5\u27f0-\u27ff\u2900-\u2982\u2999-\u29d7\u29dc-\u29fb\u29fe-\u2aff\u2b30-\u2b44\u2b47-\u2b4c\ufb29\ufe62\ufe64-\ufe66\uff0b\uff1c-\uff1e\uff5c\uff5e\uffe2\uffe9-\uffec\ud803\udd8e-\ud803\udd8f\ud835\udec1\ud835\udedb\ud835\udefb\ud835\udf15\ud835\udf35\ud835\udf4f\ud835\udf6f\ud835\udf89\ud835\udfa9\ud835\udfc3\ud83b\udef0-\ud83b\udef1] +Unicode_Currency_Symbol <- [\u0024\u00a2-\u00a5\u058f\u060b\u07fe-\u07ff\u09f2-\u09f3\u09fb\u0af1\u0bf9\u0e3f\u17db\u20a0-\u20c0\ua838\ufdfc\ufe69\uff04\uffe0-\uffe1\uffe5-\uffe6\ud807\udfdd-\ud807\udfe0\ud838\udeff\ud83b\udcb0] +Unicode_Modifier_Symbol <- [\u005e\u0060\u00a8\u00af\u00b4\u00b8\u02c2-\u02c5\u02d2-\u02df\u02e5-\u02eb\u02ed\u02ef-\u02ff\u0375\u0384-\u0385\u0888\u1fbd\u1fbf-\u1fc1\u1fcd-\u1fcf\u1fdd-\u1fdf\u1fed-\u1fef\u1ffd-\u1ffe\u309b-\u309c\ua700-\ua716\ua720-\ua721\ua789-\ua78a\uab5b\uab6a-\uab6b\ufbb2-\ufbc2\uff3e\uff40\uffe3\ud83c\udffb-\ud83c\udfff] +Unicode_Other_Symbol <- [\u00a6\u00a9\u00ae\u00b0\u0482\u058d-\u058e\u060e-\u060f\u06de\u06e9\u06fd-\u06fe\u07f6\u09fa\u0b70\u0bf3-\u0bf8\u0bfa\u0c7f\u0d4f\u0d79\u0f01-\u0f03\u0f13\u0f15-\u0f17\u0f1a-\u0f1f\u0f34\u0f36\u0f38\u0fbe-\u0fc5\u0fc7-\u0fcc\u0fce-\u0fcf\u0fd5-\u0fd8\u109e-\u109f\u1390-\u1399\u166d\u1940\u19de-\u19ff\u1b61-\u1b6a\u1b74-\u1b7c\u2100-\u2101\u2103-\u2106\u2108-\u2109\u2114\u2116-\u2117\u211e-\u2123\u2125\u2127\u2129\u212e\u213a-\u213b\u214a\u214c-\u214d\u214f\u218a-\u218b\u2195-\u2199\u219c-\u219f\u21a1-\u21a2\u21a4-\u21a5\u21a7-\u21ad\u21af-\u21cd\u21d0-\u21d1\u21d3\u21d5-\u21f3\u2300-\u2307\u230c-\u231f\u2322-\u2328\u232b-\u237b\u237d-\u239a\u23b4-\u23db\u23e2-\u2429\u2440-\u244a\u249c-\u24e9\u2500-\u25b6\u25b8-\u25c0\u25c2-\u25f7\u2600-\u266e\u2670-\u2767\u2794-\u27bf\u2800-\u28ff\u2b00-\u2b2f\u2b45-\u2b46\u2b4d-\u2b73\u2b76-\u2b95\u2b97-\u2bff\u2ce5-\u2cea\u2e50-\u2e51\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u2ff0-\u2fff\u3004\u3012-\u3013\u3020\u3036-\u3037\u303e-\u303f\u3190-\u3191\u3196-\u319f\u31c0-\u31e5\u31ef\u3200-\u321e\u322a-\u3247\u3250\u3260-\u327f\u328a-\u32b0\u32c0-\u33ff\u4dc0-\u4dff\ua490-\ua4c6\ua828-\ua82b\ua836-\ua837\ua839\uaa77-\uaa79\ufd40-\ufd4f\ufdcf\ufdfd-\ufdff\uffe4\uffe8\uffed-\uffee\ufffc-\ufffd\ud800\udd37-\ud800\udd3f\ud800\udd79-\ud800\udd89\ud800\udd8c-\ud800\udd8e\ud800\udd90-\ud800\udd9c\ud800\udda0\ud800\uddd0-\ud800\uddfc\ud802\udc77-\ud802\udc78\ud802\udec8\ud805\udf3f\ud807\udfd5-\ud807\udfdc\ud807\udfe1-\ud807\udff1\ud81a\udf3c-\ud81a\udf3f\ud81a\udf45\ud82f\udc9c\ud833\udc00-\ud833\udcef\ud833\udd00-\ud833\udeb3\ud833\udf50-\ud833\udfc3\ud834\udc00-\ud834\udcf5\ud834\udd00-\ud834\udd26\ud834\udd29-\ud834\udd64\ud834\udd6a-\ud834\udd6c\ud834\udd83-\ud834\udd84\ud834\udd8c-\ud834\udda9\ud834\uddae-\ud834\uddea\ud834\ude00-\ud834\ude41\ud834\ude45\ud834\udf00-\ud834\udf56\ud836\udc00-\ud836\uddff\ud836\ude37-\ud836\ude3a\ud836\ude6d-\ud836\ude74\ud836\ude76-\ud836\ude83\ud836\ude85-\ud836\ude86\ud838\udd4f\ud83b\udcac\ud83b\udd2e\ud83c\udc00-\ud83c\udc2b\ud83c\udc30-\ud83c\udc93\ud83c\udca0-\ud83c\udcae\ud83c\udcb1-\ud83c\udcbf\ud83c\udcc1-\ud83c\udccf\ud83c\udcd1-\ud83c\udcf5\ud83c\udd0d-\ud83c\uddad\ud83c\udde6-\ud83c\ude02\ud83c\ude10-\ud83c\ude3b\ud83c\ude40-\ud83c\ude48\ud83c\ude50-\ud83c\ude51\ud83c\ude60-\ud83c\ude65\ud83c\udf00-\ud83c\udffa\ud83d\udc00-\ud83d\uded7\ud83d\udedc-\ud83d\udeec\ud83d\udef0-\ud83d\udefc\ud83d\udf00-\ud83d\udf76\ud83d\udf7b-\ud83d\udfd9\ud83d\udfe0-\ud83d\udfeb\ud83d\udff0\ud83e\udc00-\ud83e\udc0b\ud83e\udc10-\ud83e\udc47\ud83e\udc50-\ud83e\udc59\ud83e\udc60-\ud83e\udc87\ud83e\udc90-\ud83e\udcad\ud83e\udcb0-\ud83e\udcbb\ud83e\udcc0-\ud83e\udcc1\ud83e\udd00-\ud83e\ude53\ud83e\ude60-\ud83e\ude6d\ud83e\ude70-\ud83e\ude7c\ud83e\ude80-\ud83e\ude89\ud83e\ude8f-\ud83e\udec6\ud83e\udece-\ud83e\udedc\ud83e\udedf-\ud83e\udee9\ud83e\udef0-\ud83e\udef8\ud83e\udf00-\ud83e\udf92\ud83e\udf94-\ud83e\udfef] +Unicode_Space_Separator <- [\u0020\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000] +Unicode_Line_Separator <- [\u2028] +Unicode_Paragraph_Separator <- [\u2029] +Unicode_Control <- [\u0000-\u001f\u007f-\u009f] +Unicode_Format <- [\u00ad\u0600-\u0605\u061c\u06dd\u070f\u0890-\u0891\u08e2\u180e\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u206f\ufeff\ufff9-\ufffb\ud804\udcbd\ud804\udccd\ud80d\udc30-\ud80d\udc3f\ud82f\udca0-\ud82f\udca3\ud834\udd73-\ud834\udd7a\udb40\udc01\udb40\udc20-\udb40\udc7f] +Unicode_Private_Use <- [\ue000\uf8ff\udb80\udc00\udbbf\udffd\udbc0\udc00\udbff\udffd] diff --git a/src/subprojects/packcc/import/code/README.md b/src/subprojects/packcc/import/code/README.md new file mode 100644 index 00000000..3a8f6999 --- /dev/null +++ b/src/subprojects/packcc/import/code/README.md @@ -0,0 +1,310 @@ +# Import File of Utility Codes + +## Overview + +In this directory, currently one import file that provides utility codes is stored. + +## Import File + +### `code/pcc_ast.peg` + +#### Synopsis + +An import file that provides codes to make it easier to build an AST (abstract syntax tree). + +#### Usage + +The usage procedure is shown below. + +1. Import `code/pcc_ast.peg` **after the last `%header` section** in the PEG file if any. + ``` + %import "code/pcc_ast.peg" + ``` +2. Set the designated data types as follows: + ``` + %value "pcc_ast_node_t *" + + %auxil "pcc_ast_manager_t *" + ``` +3. Create an AST node using either of the following functions in every rule action. + - `pcc_ast_node_t *pcc_ast_node__create_0(void);` + + Returns a newly created nullary node. + - `pcc_ast_node_t *pcc_ast_node__create_1(pcc_ast_node_t *node);` + + Returns a newly created unary node with one child node specified by the argument `node`. + - `pcc_ast_node_t *pcc_ast_node__create_2(pcc_ast_node_t *node0, pcc_ast_node_t *node1);` + + Returns a newly created binary node with two child nodes specified by the argument `node0` and `node1`. + - `pcc_ast_node_t *pcc_ast_node__create_3(pcc_ast_node_t *node0, pcc_ast_node_t *node1, pcc_ast_node_t *node2);` + + Returns a newly created ternary node with three child nodes specified by the argument `node0`, `node1`, and `node2`. + - `pcc_ast_node_t *pcc_ast_node__create_v(void);` + + Returns a newly created variadic node initially with no child node. + - `pcc_ast_node_t *pcc_ast_node__add_child(pcc_ast_node_t *obj, pcc_ast_node_t *node);` + + Adds a child node specified by the argument `node` to the variadic node `obj`. + + Can be used for `obj` as a variadic node only. + + An example is shown below. + ``` + rule0 <- l:rule1 '+' r:rule1 { $$ = pcc_ast_node__create_2(l, r); } + rule1 <- [0-9]+ { $$ = pcc_ast_node__create_0(); } + ``` +4. Call the generated parser API functions as follows: + ```c + pcc_ast_manager_t mgr; + pcc_ast_manager__initialize(&mgr); + { + pcc_context_t *ctx = pcc_create(&mgr); + pcc_ast_node_t *ast = NULL; /* ast: the root node of the AST */ + while (pcc_parse(ctx, &ast)) { + /* ... do something needed here */ + pcc_ast_node__destroy(ast); + } + pcc_destroy(ctx); + } + pcc_ast_manager__finalize(&mgr); + ``` + This code can be executed safely with no memory leak (if "_do something needed here_" does not bring memory leaks). + +#### Customization + +To build a meaningful AST, customization of the node is needed. +By defining the macro `PCC_AST_NODE_CUSTOM_DATA_DEFINED` in a `%header` section before `%import "code/pcc_ast.peg"`, +the node member variable `custom` whose data type is `pcc_ast_node_custom_data_t` is enabled for storing node custom data. +The concrete usage procedure is shown below. + +1. Define the data type of the node custom data in a PEG file. + ```c + %header { + #define PCC_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */ + + typedef struct node_custom_data_tag { /* <-- node custom data type */ + /* ... define member variables as needed */ + } pcc_ast_node_custom_data_t; + } + ``` + An example is as follows. + ```c + %header { + #define PCC_AST_NODE_CUSTOM_DATA_DEFINED + + typedef struct text_data_tag { + char *text; + } pcc_ast_node_custom_data_t; + } + ``` + Make sure that this `%header` section is located before `%import "code/pcc_ast.peg"`. +2. Set a node custom data value in every rule action as needed. + An example is as follows. + ```c + rule0 <- l:rule1 '+' r:rule1 { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("+"); } + rule1 <- < [0-9]+ > { $$ = pcc_ast_node__create_0(); $$->custom.text = strdup($1); } + ``` +3. Implement the initialization and finalization functions for the node custom data. + - `void pcc_ast_node_custom_data__initialize(pcc_ast_node_custom_data_t *obj);` + + Initializes the node custom data `obj`. + - `void pcc_ast_node_custom_data__finalize(pcc_ast_node_custom_data_t *obj);` + + Finalizes the node custom data `obj`. + + An example is as follows. + ```c + void pcc_ast_node_custom_data__initialize(pcc_ast_node_custom_data_t *obj) { + obj->text = NULL; + } + + void pcc_ast_node_custom_data__finalize(pcc_ast_node_custom_data_t *obj) { + free(obj->text); + } + ``` + +#### Macros + +Some macros are prepared to customize the behavior of memory allocation for AST nodes. +The macro definition should be **in `%source` section** in the PEG source. + +The following macros are available. + +**`PCC_AST_MALLOC(`**_mgr_**`,`**_size_**`)`** + +The function macro to allocate a memory block. +The pointer to the instance of `pcc_ast_manager_t` that was passed to the API function `pcc_create()` can be retrieved from the argument _auxil_. +It can be ignored if the instance does not concern memory allocation. +The argument _size_ is the number of bytes to allocate. +This macro must return a pointer to the allocated memory block, or `NULL` if no sufficient memory is available. + +The default is defined as `PCC_MALLOC(mgr, size)`, which is used in the generated parser. + +**`PCC_AST_REALLOC(`**_mgr_**`,`**_ptr_**`,`**_size_**`)`** + +The function macro to reallocate the existing memory block. +The pointer to the instance of `pcc_ast_manager_t` that was passed to the API function `pcc_create()` can be retrieved from the argument _auxil_. +It can be ignored if the instance does not concern memory allocation. +The argument _ptr_ is the pointer to the previously allocated memory block. +The argument _size_ is the new number of bytes to reallocate. +This macro must return a pointer to the reallocated memory block, or `NULL` if no sufficient memory is available. +The contents of the memory block should be left unchanged in any case even if the reallocation fails. + +The default is defined as `PCC_REALLOC(mgr, ptr, size)`, which is used in the generated parser. + +**`PCC_AST_FREE(`**_mgr_**`,`**_ptr_**`)`** + +The function macro to free the existing memory block. +The pointer to the instance of `pcc_ast_manager_t` that was passed to the API function `pcc_create()` can be retrieved from the argument _auxil_. +It can be ignored if the instance does not concern memory allocation. +The argument _ptr_ is the pointer to the previously allocated memory block. +This macro need not return a value. + +The default is defined as `PCC_FREE(mgr, ptr)`, which is used in the generated parser. + +**`PCC_AST_NODE_ARRAY_MIN_SIZE`** + +The initial size (the number of nods) of the node arrays used in AST nodes. +The arrays are expanded as needed. +The default is `4`. + +#### Example + +An example which builds an AST and dumps it is shown here. +This example accepts the same inputs as [*Desktop Calculator*](../../examples/calc.peg). + +```c +%prefix "calc" + +%value "pcc_ast_node_t *" # <-- must be set + +%auxil "pcc_ast_manager_t *" # <-- must be set + +%header { +#define PCC_AST_NODE_CUSTOM_DATA_DEFINED /* <-- enables node custom data */ + +typedef struct text_data_tag { /* <-- node custom data type */ + char *text; +} pcc_ast_node_custom_data_t; +} + +%source { +#include +#include +} + +statement <- _ e:expression _ EOL { $$ = e; } + / ( !EOL . )* EOL { $$ = NULL; } + +expression <- e:term { $$ = e; } + +term <- l:term _ '+' _ r:factor { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("+"); } + / l:term _ '-' _ r:factor { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("-"); } + / e:factor { $$ = e; } + +factor <- l:factor _ '*' _ r:unary { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("*"); } + / l:factor _ '/' _ r:unary { $$ = pcc_ast_node__create_2(l, r); $$->custom.text = strdup("/"); } + / e:unary { $$ = e; } + +unary <- '+' _ e:unary { $$ = pcc_ast_node__create_1(e); $$->custom.text = strdup("+"); } + / '-' _ e:unary { $$ = pcc_ast_node__create_1(e); $$->custom.text = strdup("-"); } + / e:primary { $$ = e; } + +primary <- < [0-9]+ > { $$ = pcc_ast_node__create_0(); $$->custom.text = strdup($1); } + / '(' _ e:expression _ ')' { $$ = e; } + +_ <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' / ';' + +%import "code/pcc_ast.peg" # <-- provides AST build functions + +%% +void pcc_ast_node_custom_data__initialize(pcc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */ + obj->text = NULL; +} + +void pcc_ast_node_custom_data__finalize(pcc_ast_node_custom_data_t *obj) { /* <-- must be implemented when enabling node custom data */ + free(obj->text); +} + +static void dump_ast(const pcc_ast_node_t *obj, int depth) { + if (obj) { + switch (obj->type) { + case PCC_AST_NODE_TYPE_NULLARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "nullary", obj->custom.text); + break; + case PCC_AST_NODE_TYPE_UNARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "unary", obj->custom.text); + dump_ast(obj->data.unary.node, depth + 1); + break; + case PCC_AST_NODE_TYPE_BINARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "binary", obj->custom.text); + dump_ast(obj->data.binary.node[0], depth + 1); + dump_ast(obj->data.binary.node[1], depth + 1); + break; + case PCC_AST_NODE_TYPE_TERNARY: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "ternary", obj->custom.text); + dump_ast(obj->data.ternary.node[0], depth + 1); + dump_ast(obj->data.ternary.node[1], depth + 1); + dump_ast(obj->data.ternary.node[2], depth + 1); + break; + case PCC_AST_NODE_TYPE_VARIADIC: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "variadic", obj->custom.text); + { + size_t i; + for (i = 0; i < obj->data.variadic.len; i++) { + dump_ast(obj->data.variadic.node[i], depth + 1); + } + } + break; + default: + printf("%*s%s: \"%s\"\n", 2 * depth, "", "(unknown)", obj->custom.text); + break; + } + } + else { + printf("%*s(null)\n", 2 * depth, ""); + } +} + +int main(int argc, char **argv) { + pcc_ast_manager_t mgr; + pcc_ast_manager__initialize(&mgr); + { + calc_context_t *ctx = calc_create(&mgr); + pcc_ast_node_t *ast = NULL; + while (calc_parse(ctx, &ast)) { + dump_ast(ast, 0); + pcc_ast_node__destroy(ast); + } + calc_destroy(ctx); + } + pcc_ast_manager__finalize(&mgr); + return 0; +} +``` + +An execution example is as follows. + +``` +$ ./ast-calc↵ +1+2*(3+4*(5+6))↵ +binary: "+" + nullary: "1" + binary: "*" + nullary: "2" + binary: "+" + nullary: "3" + binary: "*" + nullary: "4" + binary: "+" + nullary: "5" + nullary: "6" +5*6*7*8/(1*2*3*4)↵ +binary: "/" + binary: "*" + binary: "*" + binary: "*" + nullary: "5" + nullary: "6" + nullary: "7" + nullary: "8" + binary: "*" + binary: "*" + binary: "*" + nullary: "1" + nullary: "2" + nullary: "3" + nullary: "4" +``` diff --git a/src/subprojects/packcc/import/code/pcc_ast.peg b/src/subprojects/packcc/import/code/pcc_ast.peg new file mode 100644 index 00000000..50be7361 --- /dev/null +++ b/src/subprojects/packcc/import/code/pcc_ast.peg @@ -0,0 +1,413 @@ +# Copyright (c) 2024 Arihiro Yoshida. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# AST utility import file: version 2.0.0 + +%header { +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ${prefix}_ast_manager_tag ${prefix}_ast_manager_t; +typedef struct ${prefix}_ast_node_tag ${prefix}_ast_node_t; + +typedef enum ${prefix}_ast_node_type_tag { + ${PREFIX}_AST_NODE_TYPE_NULLARY, + ${PREFIX}_AST_NODE_TYPE_UNARY, + ${PREFIX}_AST_NODE_TYPE_BINARY, + ${PREFIX}_AST_NODE_TYPE_TERNARY, + ${PREFIX}_AST_NODE_TYPE_VARIADIC +} ${prefix}_ast_node_type_t; + +typedef struct ${prefix}_ast_node_single_tag { + ${prefix}_ast_node_t *node; +} ${prefix}_ast_node_single_t; + +typedef struct ${prefix}_ast_node_double_tag { + ${prefix}_ast_node_t *node[2]; +} ${prefix}_ast_node_double_t; + +typedef struct ${prefix}_ast_node_triple_tag { + ${prefix}_ast_node_t *node[3]; +} ${prefix}_ast_node_triple_t; + +typedef struct ${prefix}_ast_node_array_tag { + ${prefix}_ast_node_t **node; + size_t max, len; +} ${prefix}_ast_node_array_t; + +typedef union ${prefix}_ast_node_data_tag { + ${prefix}_ast_node_single_t unary; + ${prefix}_ast_node_double_t binary; + ${prefix}_ast_node_triple_t ternary; + ${prefix}_ast_node_array_t variadic; +} ${prefix}_ast_node_data_t; + +struct ${prefix}_ast_node_tag { + ${prefix}_ast_manager_t *manager; + ${prefix}_ast_node_t *next; /* the next element in the doubly linked list of managed nodes */ + ${prefix}_ast_node_t *prev; /* the previous element in the doubly linked list of managed nodes */ + ${prefix}_ast_node_t *parent; + ${prefix}_ast_node_type_t type; + ${prefix}_ast_node_data_t data; +#ifdef ${PREFIX}_AST_NODE_CUSTOM_DATA_DEFINED + ${prefix}_ast_node_custom_data_t custom; +#endif +}; + +struct ${prefix}_ast_manager_tag { + ${prefix}_ast_node_t *first; /* the first element in the doubly linked list of managed nodes */ +#ifdef ${PREFIX}_AST_MANAGER_CUSTOM_DATA_DEFINED + ${prefix}_ast_manager_custom_data_t custom; +#endif +}; + +void ${prefix}_ast_manager__initialize(${prefix}_ast_manager_t *obj); +void ${prefix}_ast_manager__finalize(${prefix}_ast_manager_t *obj); + +void ${prefix}_ast_node_array__initialize(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_array_t *obj); +void ${prefix}_ast_node_array__finalize(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_array_t *obj); +void ${prefix}_ast_node_array__add(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_array_t *obj, ${prefix}_ast_node_t *node); + +${prefix}_ast_node_t *${prefix}_ast_node__create_nullary(${prefix}_ast_manager_t *mgr); +${prefix}_ast_node_t *${prefix}_ast_node__create_unary(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_t *node); +${prefix}_ast_node_t *${prefix}_ast_node__create_binary(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_t *node0, ${prefix}_ast_node_t *node1); +${prefix}_ast_node_t *${prefix}_ast_node__create_ternary(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_t *node0, ${prefix}_ast_node_t *node1, ${prefix}_ast_node_t *node2); +${prefix}_ast_node_t *${prefix}_ast_node__create_variadic(${prefix}_ast_manager_t *mgr); +${prefix}_ast_node_t *${prefix}_ast_node__add_child(${prefix}_ast_node_t *obj, ${prefix}_ast_node_t *node); /* for variadic node only */ +void ${prefix}_ast_node__destroy(${prefix}_ast_node_t *obj); + +#ifdef ${PREFIX}_AST_MANAGER_CUSTOM_DATA_DEFINED +void ${prefix}_ast_manager_custom_data__initialize(${prefix}_ast_manager_custom_data_t *obj); +void ${prefix}_ast_manager_custom_data__finalize(${prefix}_ast_manager_custom_data_t *obj); +#else +#define ${prefix}_ast_manager_custom_data__initialize(obj) ((void)0) +#define ${prefix}_ast_manager_custom_data__finalize(obj) ((void)0) +#endif + +#ifdef ${PREFIX}_AST_NODE_CUSTOM_DATA_DEFINED +void ${prefix}_ast_node_custom_data__initialize(${prefix}_ast_node_custom_data_t *obj); +void ${prefix}_ast_node_custom_data__finalize(${prefix}_ast_node_custom_data_t *obj); +#else +#define ${prefix}_ast_node_custom_data__initialize(obj) ((void)0) +#define ${prefix}_ast_node_custom_data__finalize(obj) ((void)0) +#endif + +#ifdef __cplusplus +} +#endif +} + +%source { +#define ${prefix}_ast_node__create_0() ${prefix}_ast_node__create_nullary(auxil) +#define ${prefix}_ast_node__create_1(node) ${prefix}_ast_node__create_unary(auxil, node) +#define ${prefix}_ast_node__create_2(node0, node1) ${prefix}_ast_node__create_binary(auxil, node0, node1) +#define ${prefix}_ast_node__create_3(node0, node1, node2) ${prefix}_ast_node__create_ternary(auxil, node0, node1, node2) +#define ${prefix}_ast_node__create_v() ${prefix}_ast_node__create_variadic(auxil) +} + +%% +#include + +#ifndef PCC_AST_NODE_ARRAY_MIN_SIZE +#define PCC_AST_NODE_ARRAY_MIN_SIZE 4 +#endif + +#ifndef PCC_AST_MALLOC +#define PCC_AST_MALLOC(mgr, size) PCC_MALLOC(mgr, size) +#endif + +#ifndef PCC_AST_REALLOC +#define PCC_AST_REALLOC(mgr, ptr, size) PCC_REALLOC(mgr, ptr, size) +#endif + +#ifndef PCC_AST_FREE +#define PCC_AST_FREE(mgr, ptr) PCC_FREE(mgr, ptr) +#endif + +void ${prefix}_ast_manager__initialize(${prefix}_ast_manager_t *obj) { + obj->first = NULL; + ${prefix}_ast_manager_custom_data__initialize(&(obj->custom)); +} + +void ${prefix}_ast_manager__finalize(${prefix}_ast_manager_t *obj) { + ${prefix}_ast_manager_custom_data__finalize(&(obj->custom)); + while (obj->first) { + assert(obj->first->manager == obj); + ${prefix}_ast_node__destroy(obj->first); + } +} + +void ${prefix}_ast_node_array__initialize(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_array_t *obj) { + obj->len = 0; + obj->max = 0; + obj->node = NULL; +} + +void ${prefix}_ast_node_array__finalize(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_array_t *obj) { + while (obj->len > 0) { + obj->len--; + ${prefix}_ast_node__destroy(obj->node[obj->len]); + } + PCC_AST_FREE(mgr, obj->node); +} + +void ${prefix}_ast_node_array__add(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_array_t *obj, ${prefix}_ast_node_t *node) { + if (obj->max <= obj->len) { + const size_t n = obj->len + 1; + size_t m = obj->max; + if (m == 0) m = PCC_AST_NODE_ARRAY_MIN_SIZE; + while (m < n && m != 0) m <<= 1; + if (m == 0) m = n; + obj->node = (${prefix}_ast_node_t **)PCC_AST_REALLOC(mgr, obj->node, sizeof(${prefix}_ast_node_t *) * m); + obj->max = m; + } + obj->node[obj->len++] = node; +} + +static void ${prefix}_ast_node__unlink_parent_(${prefix}_ast_node_t *obj) { + if (obj->parent) { + switch (obj->parent->type) { + case ${PREFIX}_AST_NODE_TYPE_NULLARY: + assert(((void)"Nullary node illegally linked as a parent", 0)); + break; + case ${PREFIX}_AST_NODE_TYPE_UNARY: + if (obj->parent->data.unary.node == obj) + obj->parent->data.unary.node = NULL; + else + assert(((void)"parent node with no backward link", 0)); + break; + case ${PREFIX}_AST_NODE_TYPE_BINARY: + { + size_t i; + for (i = 0; i < 2; i++) { + if (obj->parent->data.binary.node[i] == obj) break; + } + if (i < 2) + obj->parent->data.binary.node[i] = NULL; + else + assert(((void)"parent node with no backward link", 0)); + } + break; + case ${PREFIX}_AST_NODE_TYPE_TERNARY: + { + size_t i; + for (i = 0; i < 3; i++) { + if (obj->parent->data.ternary.node[i] == obj) break; + } + if (i < 3) + obj->parent->data.ternary.node[i] = NULL; + else + assert(((void)"parent node with no backward link", 0)); + } + break; + case ${PREFIX}_AST_NODE_TYPE_VARIADIC: + { + const size_t n = obj->parent->data.variadic.len; + size_t i; + for (i = 0; i < n; i++) { + if (obj->parent->data.variadic.node[i] == obj) break; + } + if (i < n) + obj->parent->data.variadic.node[i] = NULL; + else + assert(((void)"parent node with no backward link", 0)); + } + break; + default: + assert(((void)"Node type unknown", 0)); + break; + } + obj->parent = NULL; + } +} + +static ${prefix}_ast_node_t *${prefix}_ast_node__create_(${prefix}_ast_manager_t *mgr) { + ${prefix}_ast_node_t *const obj = (${prefix}_ast_node_t *)PCC_AST_MALLOC(mgr, sizeof(${prefix}_ast_node_t)); + obj->manager = mgr; + if (mgr->first) { + obj->next = mgr->first; + assert(((void)"Inconsistency in the doubly linked list of managed nodes", obj->next->prev == NULL)); + obj->next->prev = obj; + } + else { + obj->next = NULL; + } + obj->prev = NULL; + mgr->first = obj; + obj->parent = NULL; + return obj; +} + +${prefix}_ast_node_t *${prefix}_ast_node__create_nullary(${prefix}_ast_manager_t *mgr) { + ${prefix}_ast_node_t *const obj = ${prefix}_ast_node__create_(mgr); + obj->type = ${PREFIX}_AST_NODE_TYPE_NULLARY; + ${prefix}_ast_node_custom_data__initialize(&(obj->custom)); + return obj; +} + +${prefix}_ast_node_t *${prefix}_ast_node__create_unary(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_t *node) { + ${prefix}_ast_node_t *const obj = ${prefix}_ast_node__create_(mgr); + obj->type = ${PREFIX}_AST_NODE_TYPE_UNARY; + obj->data.unary.node = node; + if (node) { + ${prefix}_ast_node__unlink_parent_(node); + node->parent = obj; + } + ${prefix}_ast_node_custom_data__initialize(&(obj->custom)); + return obj; +} + +${prefix}_ast_node_t *${prefix}_ast_node__create_binary(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_t *node0, ${prefix}_ast_node_t *node1) { + ${prefix}_ast_node_t *const obj = ${prefix}_ast_node__create_(mgr); + obj->type = ${PREFIX}_AST_NODE_TYPE_BINARY; + obj->data.binary.node[0] = node0; + obj->data.binary.node[1] = node1; + { + size_t i = 0; + for (i = 0; i < 2; i++) { + ${prefix}_ast_node_t *const node = obj->data.binary.node[i]; + if (node) { + ${prefix}_ast_node__unlink_parent_(node); + node->parent = obj; + } + } + } + ${prefix}_ast_node_custom_data__initialize(&(obj->custom)); + return obj; +} + +${prefix}_ast_node_t *${prefix}_ast_node__create_ternary(${prefix}_ast_manager_t *mgr, ${prefix}_ast_node_t *node0, ${prefix}_ast_node_t *node1, ${prefix}_ast_node_t *node2) { + ${prefix}_ast_node_t *const obj = ${prefix}_ast_node__create_(mgr); + obj->type = ${PREFIX}_AST_NODE_TYPE_TERNARY; + obj->data.ternary.node[0] = node0; + obj->data.ternary.node[1] = node1; + obj->data.ternary.node[2] = node2; + { + size_t i = 0; + for (i = 0; i < 3; i++) { + ${prefix}_ast_node_t *const node = obj->data.ternary.node[i]; + if (node) { + ${prefix}_ast_node__unlink_parent_(node); + node->parent = obj; + } + } + } + ${prefix}_ast_node_custom_data__initialize(&(obj->custom)); + return obj; +} + +${prefix}_ast_node_t *${prefix}_ast_node__create_variadic(${prefix}_ast_manager_t *mgr) { + ${prefix}_ast_node_t *const obj = ${prefix}_ast_node__create_(mgr); + obj->type = ${PREFIX}_AST_NODE_TYPE_VARIADIC; + ${prefix}_ast_node_array__initialize(mgr, &(obj->data.variadic)); + ${prefix}_ast_node_custom_data__initialize(&(obj->custom)); + return obj; +} + +${prefix}_ast_node_t *${prefix}_ast_node__add_child(${prefix}_ast_node_t *obj, ${prefix}_ast_node_t *node) { + if (obj->type == ${PREFIX}_AST_NODE_TYPE_VARIADIC) { + ${prefix}_ast_node_array__add(obj->manager, &(obj->data.variadic), node); + if (node) { + ${prefix}_ast_node__unlink_parent_(node); + node->parent = obj; + } + } + else { + assert(((void)"Attempted to add node to non-variadic node", obj->next->prev == NULL)); + } + return obj; +} + +void ${prefix}_ast_node__destroy(${prefix}_ast_node_t *obj) { + if (obj) { + ${prefix}_ast_node_custom_data__finalize(&(obj->custom)); + switch (obj->type) { + case ${PREFIX}_AST_NODE_TYPE_NULLARY: + break; + case ${PREFIX}_AST_NODE_TYPE_UNARY: + { + ${prefix}_ast_node_t *const node = obj->data.unary.node; + if (node) { + assert(node->parent == obj); + node->parent = NULL; + ${prefix}_ast_node__destroy(node); + } + } + break; + case ${PREFIX}_AST_NODE_TYPE_BINARY: + { + size_t i; + for (i = 0; i < 2; i++) { + ${prefix}_ast_node_t *const node = obj->data.binary.node[i]; + if (node) { + assert(node->parent == obj); + node->parent = NULL; + ${prefix}_ast_node__destroy(node); + } + } + } + break; + case ${PREFIX}_AST_NODE_TYPE_TERNARY: + { + size_t i; + for (i = 0; i < 3; i++) { + ${prefix}_ast_node_t *const node = obj->data.ternary.node[i]; + if (node) { + assert(node->parent == obj); + node->parent = NULL; + ${prefix}_ast_node__destroy(node); + } + } + } + break; + case ${PREFIX}_AST_NODE_TYPE_VARIADIC: + while (obj->data.variadic.len > 0) { + const size_t i = --obj->data.variadic.len; + ${prefix}_ast_node_t *const node = obj->data.variadic.node[i]; + if (node) { + assert(node->parent == obj); + node->parent = NULL; + ${prefix}_ast_node__destroy(node); + obj->data.variadic.node[i] = NULL; + } + } + ${prefix}_ast_node_array__finalize(obj->manager, &(obj->data.variadic)); + break; + default: + assert(((void)"Node type unknown", 0)); + break; + } + ${prefix}_ast_node__unlink_parent_(obj); + if (obj->prev) { + assert(obj->prev->next == obj); + obj->prev->next = obj->next; + } + else { + assert(obj->manager->first == obj); + obj->manager->first = obj->next; + } + if (obj->next) { + assert(obj->next->prev == obj); + obj->next->prev = obj->prev; + } + PCC_AST_FREE(obj->manager, obj); + } +} diff --git a/src/subprojects/packcc/meson.build b/src/subprojects/packcc/meson.build new file mode 100644 index 00000000..54617322 --- /dev/null +++ b/src/subprojects/packcc/meson.build @@ -0,0 +1,15 @@ +project('packcc', + ['c'], + version: '2.2.0', + meson_version: '>=1.0', + default_options: ['c_std=gnu89', 'optimization=2']) + +packcc_exe = executable('packcc', 'src/packcc.c', + c_args: ['-fsigned-char', '-Wall', '-Wextra', + '-Wno-unused-parameter', '-Wno-overlength-strings', + '-pedantic'], + install: not meson.is_subproject()) + +# Register the fallback the parent resolves through this wrap's [provide] +# section: find_program('packcc'). +meson.override_find_program('packcc', packcc_exe) diff --git a/src/subprojects/packcc/misc/README.md b/src/subprojects/packcc/misc/README.md new file mode 100644 index 00000000..975e34fd --- /dev/null +++ b/src/subprojects/packcc/misc/README.md @@ -0,0 +1,37 @@ +# Miscellaneous Tools + +## Overview + +In this directory, miscellaneous tools shown below are stored. + +## Tools + +### `unicode_general_category.py` + +#### Synopsis + +A Python script to generate a PEG file defining rules to match Unicode characters with the respective _general category properties_. +It needs internet access for fetching Unicode data from https://www.unicode.org/ . + +The Python module `requests` is required. + +#### Usage + +~~~sh +$ python unicode_general_category.py > ../import/char/unicode_general_category.peg +~~~ + +### `unicode_derived_core.py` + +#### Synopsis + +A Python script to generate a PEG file defining rules to match Unicode characters with the respective _derived core properties_. +It needs internet access for fetching Unicode data from https://www.unicode.org/ . + +The Python module `requests` is required. + +#### Usage + +~~~sh +$ python unicode_derived_core.py > ../import/char/unicode_derived_core.peg +~~~ diff --git a/src/subprojects/packcc/misc/unicode_derived_core.py b/src/subprojects/packcc/misc/unicode_derived_core.py new file mode 100644 index 00000000..bcf37be4 --- /dev/null +++ b/src/subprojects/packcc/misc/unicode_derived_core.py @@ -0,0 +1,118 @@ +#!/usr/bin/python3 + +# Copyright (c) 2024-2025 Arihiro Yoshida. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import os +import requests +import re + +ucd_url = 'https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt' +ucd_dp_list = [ # Grapheme_Link is deprecated; Indic_Conjunct_Break is unsupported. + 'Math', + 'Alphabetic', + 'Lowercase', + 'Uppercase', + 'Cased', + 'Case_Ignorable', + 'Changes_When_Lowercased', + 'Changes_When_Uppercased', + 'Changes_When_Titlecased', + 'Changes_When_Casefolded', + 'Changes_When_Casemapped', + 'ID_Start', + 'ID_Continue', + 'XID_Start', + 'XID_Continue', + 'Default_Ignorable_Code_Point', + 'Grapheme_Extend', + 'Grapheme_Base' +] + +def get_unicode_data(): + res = requests.get(ucd_url, stream=True) + res.raise_for_status() + txt = '' + for chunk in res.iter_content(chunk_size=1024*1024): + txt += chunk.decode() + return txt + +def escape_as_utf16_hex(hex): + code = int(hex, 16) + if code > 0x10ffff: + raise ValueError + return f'\\u{code:04x}' if code <= 0xffff else f'\\u{0xd800 | ((code - 0x10000) >> 10):04x}\\u{0xdc00 | (code & 0x3ff):04x}' + +def generate_rules(dat): + str = ( + '# This file was generated using the script \'' + os.path.basename(__file__) + '\'.\n' + '\n' + '# This file is hereby placed in the public domain.\n' + '#\n' + '# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\n' + '# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n' + '# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n' + '# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\n' + '# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n' + '# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n' + '# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n' + '# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n' + '# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n' + '# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n' + '# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n' + '\n' + ) + for dp in ucd_dp_list: + if dp not in dat: + continue + cc = '' + cs = '' + cp = '' + for c in dat[dp]: + if cs == '': + cs = c[0] + elif int(c[0], 16) - int(cp, 16) != 1: + cc += escape_as_utf16_hex(cs) + if cs != cp: + cc += '-' + escape_as_utf16_hex(cp) + cs = c[0] + cp = c[1] + if cs != '': + cc += escape_as_utf16_hex(cs) + if cs != cp: + cc += '-' + escape_as_utf16_hex(cp) + str += 'Unicode_' + dp + ' <- [' + cc + ']\n' + return str + +def main(): + pat = re.compile(r'^([0-9a-fA-F]+)(?:\.\.([0-9a-fA-F]+))?\s*;\s*([0-9a-zA-Z_]+)') + dat = {} + for ent in get_unicode_data().splitlines(): + res = pat.search(ent) + if res is None: + continue + pro = res.group(3) + if pro not in dat: + dat[pro] = [] + dat[pro] += [(res.group(1), res.group(1) if res.group(2) is None else res.group(2))] + print(generate_rules(dat), end='') + +if __name__ == '__main__': + main() diff --git a/src/subprojects/packcc/misc/unicode_general_category.py b/src/subprojects/packcc/misc/unicode_general_category.py new file mode 100644 index 00000000..7eceea67 --- /dev/null +++ b/src/subprojects/packcc/misc/unicode_general_category.py @@ -0,0 +1,141 @@ +#!/usr/bin/python3 + +# Copyright (c) 2024-2025 Arihiro Yoshida. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import os +import requests +import re + +ucd_url = 'https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt' +ucd_gc_list = [ + 'Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Mn', 'Mc', 'Me', 'Nd', 'Nl', 'No', + 'Pc', 'Pd', 'Ps', 'Pe', 'Pi', 'Pf', 'Po', 'Sm', 'Sc', 'Sk', 'So', + 'Zs', 'Zl', 'Zp', 'Cc', 'Cf', 'Co', 'Cn' +] +ucd_gc_dict = { + 'Lu': 'Uppercase_Letter', + 'Ll': 'Lowercase_Letter', + 'Lt': 'Titlecase_Letter', + 'Lm': 'Modifier_Letter', + 'Lo': 'Other_Letter', + 'Mn': 'Nonspacing_Mark', + 'Mc': 'Spacing_Mark', + 'Me': 'Enclosing_Mark', + 'Nd': 'Decimal_Number', + 'Nl': 'Letter_Number', + 'No': 'Other_Number', + 'Pc': 'Connector_Punctuation', + 'Pd': 'Dash_Punctuation', + 'Ps': 'Open_Punctuation', + 'Pe': 'Close_Punctuation', + 'Pi': 'Initial_Punctuation', + 'Pf': 'Final_Punctuation', + 'Po': 'Other_Punctuation', + 'Sm': 'Math_Symbol', + 'Sc': 'Currency_Symbol', + 'Sk': 'Modifier_Symbol', + 'So': 'Other_Symbol', + 'Zs': 'Space_Separator', + 'Zl': 'Line_Separator', + 'Zp': 'Paragraph_Separator', + 'Cc': 'Control', + 'Cf': 'Format', + 'Co': 'Private_Use', + 'Cn': 'Unassigned' +} + +def get_unicode_data(): + res = requests.get(ucd_url, stream=True) + res.raise_for_status() + txt = '' + for chunk in res.iter_content(chunk_size=1024*1024): + txt += chunk.decode() + return txt + +def escape_as_utf16_hex(hex): + code = int(hex, 16) + if code > 0x10ffff: + raise ValueError + return f'\\u{code:04x}' if code <= 0xffff else f'\\u{0xd800 | ((code - 0x10000) >> 10):04x}\\u{0xdc00 | (code & 0x3ff):04x}' + +def generate_rules(dat): + str = ( + '# This file was generated using the script \'' + os.path.basename(__file__) + '\'.\n' + '\n' + '# This file is hereby placed in the public domain.\n' + '#\n' + '# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\n' + '# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n' + '# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n' + '# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\n' + '# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n' + '# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n' + '# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n' + '# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n' + '# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n' + '# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n' + '# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n' + '\n' + 'Unicode_Letter <- Unicode_Cased_Letter / Unicode_Modifier_Letter / Unicode_Other_Letter\n' + 'Unicode_Cased_Letter <- Unicode_Uppercase_Letter / Unicode_Lowercase_Letter / Unicode_Titlecase_Letter\n' + 'Unicode_Mark <- Unicode_Nonspacing_Mark / Unicode_Spacing_Mark / Unicode_Enclosing_Mark\n' + 'Unicode_Number <- Unicode_Decimal_Number / Unicode_Letter_Number / Unicode_Other_Number\n' + 'Unicode_Punctuation <- Unicode_Connector_Punctuation / Unicode_Dash_Punctuation / Unicode_Open_Punctuation / Unicode_Close_Punctuation / Unicode_Initial_Punctuation / Unicode_Final_Punctuation / Unicode_Other_Punctuation\n' + 'Unicode_Symbol <- Unicode_Math_Symbol / Unicode_Currency_Symbol / Unicode_Modifier_Symbol / Unicode_Other_Symbol\n' + 'Unicode_Separator <- Unicode_Space_Separator / Unicode_Line_Separator / Unicode_Paragraph_Separator\n' + 'Unicode_Other <- Unicode_Control / Unicode_Format / Unicode_Private_Use\n' # The category 'Unassigned' is excluded because currently it has no character. + '\n' + ) + for gc in ucd_gc_list: + if gc not in dat: + continue + cc = '' + cs = '' + cp = '' + for c in dat[gc]: + if cs == '': + cs = c + elif int(c, 16) - int(cp, 16) != 1: + cc += escape_as_utf16_hex(cs) + if cs != cp: + cc += '-' + escape_as_utf16_hex(cp) + cs = c + cp = c + if cs != '': + cc += escape_as_utf16_hex(cs) + if cs != cp: + cc += '-' + escape_as_utf16_hex(cp) + str += 'Unicode_' + ucd_gc_dict[gc] + ' <- [' + cc + ']\n' + return str + +def main(): + pat = re.compile(r'^([0-9a-fA-F]+);[^;]*;([0-9a-zA-Z_]+);') + dat = {} + for ent in get_unicode_data().splitlines(): + res = pat.search(ent) + cat = res.group(2) + if cat not in dat: + dat[cat] = [] + dat[cat] += [res.group(1)] + print(generate_rules(dat), end='') + +if __name__ == '__main__': + main() diff --git a/src/subprojects/packcc/src/packcc.c b/src/subprojects/packcc/src/packcc.c new file mode 100644 index 00000000..37864ca8 --- /dev/null +++ b/src/subprojects/packcc/src/packcc.c @@ -0,0 +1,5877 @@ +/* + * PackCC: a packrat parser generator for C. + * + * Copyright (c) 2014, 2019-2025 Arihiro Yoshida. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * The algorithm is based on the paper "Packrat Parsers Can Support Left Recursion" + * authored by A. Warth, J. R. Douglass, and T. Millstein. + * + * The specification is determined by referring to peg/leg developed by Ian Piumarta. + */ + +#ifdef _MSC_VER +#define _CRT_NONSTDC_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#ifdef _DEBUG +#define _CRTDBG_MAP_ALLOC +#include +#endif +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +#if defined __GNUC__ && defined _WIN32 /* MinGW */ +#ifndef PCC_USE_SYSTEM_STRNLEN +#define strnlen(str, maxlen) strnlen_(str, maxlen) +static size_t strnlen_(const char *str, size_t maxlen) { + size_t i; + for (i = 0; i < maxlen && str[i]; i++); + return i; +} +#endif /* !PCC_USE_SYSTEM_STRNLEN */ +#endif /* defined __GNUC__ && defined _WIN32 */ +#endif /* !_MSC_VER */ + +#ifdef _MSC_VER +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#define unlink _unlink +#else +#include /* for unlink() */ +#endif + +#ifdef _WIN32 /* Windows including MSVC and MinGW */ +#include /* _get_osfhandle() */ +/* NOTE: The header "fileapi.h" causes a compiler error due to an illegal anonymous union. */ +#define DECLSPEC_IMPORT __declspec(dllimport) +#define WINAPI __stdcall +#define S_OK 0 +#define CSIDL_PROFILE 0x0028 +#define CSIDL_COMMON_APPDATA 0x0023 +#define SHGFP_TYPE_DEFAULT 1 +#define MAX_PATH 260 +typedef int BOOL; +typedef unsigned long DWORD; +typedef char *LPSTR; +typedef long HRESULT; +typedef void *HANDLE; +typedef void *HWND; +typedef struct _FILETIME { + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME; +typedef struct _BY_HANDLE_FILE_INFORMATION { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD dwVolumeSerialNumber; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD nNumberOfLinks; + DWORD nFileIndexHigh; + DWORD nFileIndexLow; +} BY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION; +DECLSPEC_IMPORT BOOL WINAPI GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation); +DECLSPEC_IMPORT HRESULT WINAPI SHGetFolderPathA(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath); +#else /* !_WIN32 */ +#include /* for fstat() */ +#endif + +#if !defined __has_attribute || defined _MSC_VER +#define __attribute__(x) +#endif + +#undef TRUE /* to avoid macro definition conflicts with the system header file of IBM AIX */ +#undef FALSE + +#ifdef _MSC_VER +#define IMPORT_DIR_SYSTEM "packcc/import" /* should be a relative path */ +#else +#define IMPORT_DIR_SYSTEM "/usr/share/packcc/import" /* should be an absolute path */ +#endif + +#define IMPORT_DIR_USER ".packcc/import" + +#ifdef _WIN32 /* Windows including MSVC and MinGW (MinGW automatically converts paths to those in Windows style) */ +#define PATH_SEP ';' +#else +#define PATH_SEP ':' +#endif + +#define ENVVAR_IMPORT_PATH "PCC_IMPORT_PATH" + +#define WEBSITE "https://github.com/arithy/packcc" + +#define VERSION "2.2.0" + +#ifndef BUFFER_MIN_SIZE +#define BUFFER_MIN_SIZE 256 +#endif +#ifndef ARRAY_MIN_SIZE +#define ARRAY_MIN_SIZE 2 +#endif + +#define SUBST_MARKER '$' + +#define VOID_VALUE (~(size_t)0) + +#ifdef _WIN64 /* 64-bit Windows including MSVC and MinGW-w64 */ +#define FMT_LU "%llu" +typedef unsigned long long ulong_t; +/* NOTE: "%llu" and "long long" are not C89-compliant, but we cannot help using them to deal with a 64-bit integer value in 64-bit Windows. */ +#else +#define FMT_LU "%lu" +typedef unsigned long ulong_t; +#endif +/* FMT_LU and ulong_t are used to print size_t values safely (ex. printf(FMT_LU "\n", (ulong_t)value);) */ +/* NOTE: Neither "%zu" nor is used since PackCC complies with the C89 standard as much as possible. */ + +typedef enum bool_tag { + FALSE = 0, + TRUE +} bool_t; + +#ifdef _WIN32 /* Windows including MSVC and MinGW */ +typedef BY_HANDLE_FILE_INFORMATION file_id_t; +#else +typedef struct stat file_id_t; +#endif + +typedef struct file_id_array_tag { + file_id_t *buf; + size_t max; + size_t len; +} file_id_array_t; + +typedef struct file_pos_tag { + char *path; /* the file path name */ + size_t line; /* the line number (0-based); VOID_VALUE if not available */ + size_t col; /* the column number (0-based); VOID_VALUE if not available */ +} file_pos_t; + +typedef struct stream_tag { + FILE *file; /* the file stream; just a reference */ + const char *path; /* the file path name */ + size_t line; /* the current line number (0-based); line counting is disabled if VOID_VALUE */ +} stream_t; + +typedef struct char_array_tag { + char *buf; + size_t max; + size_t len; +} char_array_t; + +typedef struct string_array_tag { + char **buf; + size_t max; + size_t len; +} string_array_t; + +typedef struct code_block_tag { + char *text; + size_t len; + file_pos_t fpos; +} code_block_t; + +typedef struct code_block_array_tag { + code_block_t *buf; + size_t max; + size_t len; +} code_block_array_t; + +typedef enum node_type_tag { + NODE_RULE = 0, + NODE_REFERENCE, + NODE_STRING, + NODE_CHARCLASS, + NODE_POSITION, + NODE_QUANTITY, + NODE_PREDICATE, + NODE_SEQUENCE, + NODE_ALTERNATE, + NODE_CAPTURE, + NODE_EXPAND, + NODE_ACTION, + NODE_ERROR +} node_type_t; + +typedef struct node_tag node_t; + +typedef struct node_array_tag { + node_t **buf; + size_t max; + size_t len; +} node_array_t; + +typedef struct node_const_array_tag { + const node_t **buf; + size_t max; + size_t len; +} node_const_array_t; + +typedef struct node_hash_table_tag { + const node_t **buf; + size_t max; + size_t mod; +} node_hash_table_t; + +typedef struct node_rule_tag { + char *name; + node_t *expr; + int ref; /* mutable under make_rulehash(), link_references(), and unreference_rules_from_unused_rule() */ + bool_t used; /* mutable under mark_rules_if_used() */ + node_const_array_t vars; + node_const_array_t capts; + node_const_array_t codes; + file_pos_t fpos; +} node_rule_t; + +typedef struct node_reference_tag { + char *var; /* NULL if no variable name */ + size_t index; + char *name; + const node_t *rule; + file_pos_t fpos; +} node_reference_t; + +typedef struct node_string_tag { + char *value; +} node_string_t; + +typedef struct node_charclass_tag { + char *value; /* NULL means any character */ +} node_charclass_t; + +typedef struct node_position_tag { + size_t value; +} node_position_t; + +typedef struct node_quantity_tag { + int min; + int max; + node_t *expr; +} node_quantity_t; + +typedef struct node_predicate_tag { + bool_t neg; + node_t *expr; +} node_predicate_t; + +typedef struct node_sequence_tag { + node_array_t nodes; +} node_sequence_t; + +typedef struct node_alternate_tag { + node_array_t nodes; +} node_alternate_t; + +typedef struct node_capture_tag { + node_t *expr; + size_t index; +} node_capture_t; + +typedef struct node_expand_tag { + size_t index; + file_pos_t fpos; +} node_expand_t; + +typedef struct node_action_tag { + code_block_t code; + size_t index; + node_const_array_t vars; + node_const_array_t capts; +} node_action_t; + +typedef struct node_error_tag { + node_t *expr; + code_block_t code; + size_t index; + node_const_array_t vars; + node_const_array_t capts; +} node_error_t; + +typedef union node_data_tag { + node_rule_t rule; + node_reference_t reference; + node_string_t string; + node_charclass_t charclass; + node_position_t position; + node_quantity_t quantity; + node_predicate_t predicate; + node_sequence_t sequence; + node_alternate_t alternate; + node_capture_t capture; + node_expand_t expand; + node_action_t action; + node_error_t error; +} node_data_t; + +struct node_tag { + node_type_t type; + node_data_t data; +}; + +typedef struct options_tag { + bool_t ascii; /* UTF-8 support is disabled if true */ + bool_t lines; /* #line directives are output if true */ + bool_t debug; /* debug information is output if true */ +} options_t; + +typedef enum code_flag_tag { + CODE_FLAG__NONE = 0, + CODE_FLAG__UTF8_CHARCLASS_USED = 1 +} code_flag_t; + +typedef struct subst_entry_tag { + char *istr; /* the string to be replaced */ + char *ostr; /* the string to be used for replacement */ +} subst_entry_t; + +typedef struct subst_map_tag { + subst_entry_t *buf; + size_t max; + size_t len; +} subst_map_t; + +typedef struct input_state_tag input_state_t; + +struct input_state_tag { + char *path; /* the path name of the PEG file being parsed; "" if stdin */ + FILE *file; /* the input file stream of the PEG file */ + bool_t ascii; /* UTF-8 support is disabled if true */ + code_flag_t flags; /* the bitwise flags to control code generation; updated during PEG parsing */ + size_t errnum; /* the current number of PEG parsing errors */ + size_t linenum; /* the current line number (0-based) */ + size_t charnum; /* the number of characters in the current line that are already flushed (0-based, UTF-8 support if not disabled) */ + size_t linepos; /* the beginning position in the PEG file of the current line */ + size_t bufpos; /* the position in the PEG file of the first character currently buffered */ + size_t bufcur; /* the current parsing position in the character buffer */ + char_array_t buffer; /* the character buffer */ + input_state_t *parent; /* the input state of the parent PEG file that imports the input; just a reference */ +}; + +typedef struct context_tag { + char *spath; /* the path name of the C source file being generated */ + char *hpath; /* the path name of the C header file being generated */ + char *hid; /* the macro name for the include guard of the C header file */ + char *vtype; /* the type name of the data output by the parsing API function (NULL means the default) */ + char *atype; /* the type name of the user-defined data passed to the parser creation API function (NULL means the default) */ + char *prefix; /* the prefix of the API function names (NULL means the default) */ + const string_array_t *dirs; /* the path names of directories to search for import files */ + options_t opts; /* the options */ + code_flag_t flags; /* the bitwise flags to control code generation; updated during PEG parsing */ + size_t errnum; /* the current number of PEG parsing errors */ + input_state_t *input; /* the current input state */ + file_id_array_t done; /* the unique identifiers of the PEG file already parsed or being parsed */ + subst_map_t subst; /* the text substitution data */ + node_array_t rules; /* the PEG rules */ + node_hash_table_t rulehash; /* the hash table to accelerate access of desired PEG rules */ + code_block_array_t esource; /* the code blocks from %earlysource and %earlycommon directives to be added into the generated source file */ + code_block_array_t eheader; /* the code blocks from %earlyheader and %earlycommon directives to be added into the generated header file */ + code_block_array_t source; /* the code blocks from %source and %common directives to be added into the generated source file */ + code_block_array_t header; /* the code blocks from %header and %common directives to be added into the generated header file */ + code_block_array_t fsource; /* the code fragments after %% directive to be added into the generated source file */ +} context_t; + +typedef struct generate_tag { + stream_t *stream; + const node_t *rule; + int label; + bool_t ascii; +} generate_t; + +typedef enum string_flag_tag { + STRING_FLAG__NONE = 0, + STRING_FLAG__NOTEMPTY = 1, + STRING_FLAG__NOTVOID = 2, + STRING_FLAG__IDENTIFIER = 4 +} string_flag_t; + +typedef enum code_reach_tag { + CODE_REACH__BOTH = 0, + CODE_REACH__ALWAYS_SUCCEED = 1, + CODE_REACH__ALWAYS_FAIL = -1 +} code_reach_t; + +static const char *g_cmdname = "packcc"; /* replaced later with actual one */ + +__attribute__((format(printf, 1, 2))) +static int print_error(const char *format, ...) { + int n; + va_list a; + va_start(a, format); + n = fprintf(stderr, "%s: ", g_cmdname); + if (n >= 0) { + const int k = vfprintf(stderr, format, a); + if (k < 0) n = k; else n += k; + } + va_end(a); + return n; +} + +static FILE *fopen_rb_e(const char *path) { + FILE *const f = fopen(path, "rb"); + if (f == NULL) { + print_error("Cannot open file to read: %s\n", path); + exit(2); + } + return f; +} + +static FILE *fopen_wt_e(const char *path) { + FILE *const f = fopen(path, "wt"); + if (f == NULL) { + print_error("Cannot open file to write: %s\n", path); + exit(2); + } + return f; +} + +static int fclose_e(FILE *file, const char *path) { + const int r = fclose(file); + if (r == EOF) { + print_error("File closing error: %s\n", path); + exit(2); + } + return r; +} + +static int fgetc_e(FILE *file, const char *path) { + const int c = fgetc(file); + if (c == EOF && ferror(file)) { + print_error("File read error: %s\n", path); + exit(2); + } + return c; +} + +static void *malloc_e(size_t size) { + void *const p = malloc(size); + if (p == NULL) { + print_error("Out of memory\n"); + exit(3); + } + return p; +} + +static void *realloc_e(void *ptr, size_t size) { + void *const p = realloc(ptr, size); + if (p == NULL) { + print_error("Out of memory\n"); + exit(3); + } + return p; +} + +static char *strdup_e(const char *str) { + const size_t m = strlen(str); + char *const s = (char *)malloc_e(m + 1); + memcpy(s, str, m); + s[m] = '\0'; + return s; +} + +static char *strndup_e(const char *str, size_t len) { + const size_t m = strnlen(str, len); + char *const s = (char *)malloc_e(m + 1); + memcpy(s, str, m); + s[m] = '\0'; + return s; +} + +static char *to_uppercase(char *str) { + size_t i; + for (i = 0; str[i]; i++) { + if (str[i] >= 'a' && str[i] <= 'z') str[i] -= 'a' - 'A'; + } + return str; +} + +static size_t string_to_size_t(const char *str) { +#define N (~(size_t)0 / 10) +#define M (~(size_t)0 - 10 * N) + size_t n = 0, i, k; + for (i = 0; str[i]; i++) { + const char c = str[i]; + if (c < '0' || c > '9') return VOID_VALUE; + k = (size_t)(c - '0'); + if (n >= N && k > M) return VOID_VALUE; /* overflow */ + n = k + 10 * n; + } + return n; +#undef N +#undef M +} + +static size_t find_first_trailing_space(const char *str, size_t start, size_t end, size_t *next) { + size_t j = start, i; + for (i = start; i < end; i++) { + switch (str[i]) { + case ' ': + case '\v': + case '\f': + case '\t': + continue; + case '\n': + if (next) *next = i + 1; + return j; + case '\r': + if (i + 1 < end && str[i + 1] == '\n') i++; + if (next) *next = i + 1; + return j; + default: + j = i + 1; + } + } + if (next) *next = end; + return j; +} + +static size_t count_indent_spaces(const char *str, size_t start, size_t end, size_t *next) { + size_t n = 0, i; + for (i = start; i < end; i++) { + switch (str[i]) { + case ' ': + case '\v': + case '\f': + n++; + break; + case '\t': + n = (n + 8) & ~7; + break; + default: + if (next) *next = i; + return n; + } + } + if (next) *next = end; + return n; +} + +static bool_t is_filled_string(const char *str) { + size_t i; + for (i = 0; str[i]; i++) { + if ( + str[i] != ' ' && + str[i] != '\v' && + str[i] != '\f' && + str[i] != '\t' && + str[i] != '\n' && + str[i] != '\r' + ) return TRUE; + } + return FALSE; +} + +static bool_t is_identifier_string(const char *str) { + size_t i; + if (!( + (str[0] >= 'a' && str[0] <= 'z') || + (str[0] >= 'A' && str[0] <= 'Z') || + str[0] == '_' + )) return FALSE; + for (i = 1; str[i]; i++) { + if (!( + (str[i] >= 'a' && str[i] <= 'z') || + (str[i] >= 'A' && str[i] <= 'Z') || + (str[i] >= '0' && str[i] <= '9') || + str[i] == '_' + )) return FALSE; + } + return TRUE; +} + +static bool_t is_pointer_type(const char *str) { + const size_t n = strlen(str); + return (n > 0 && str[n - 1] == '*') ? TRUE : FALSE; +} + +static bool_t is_valid_utf8_string(const char *str) { + int k = 1, n = 0, u = 0; + size_t i; + for (i = 0; str[i]; i++) { + const int c = (int)(unsigned char)str[i]; + switch (k) { + case 1: + if (c >= 0x80) { + n = ((c & 0xe0) == 0xc0) ? 2 : + ((c & 0xf0) == 0xe0) ? 3 : + ((c & 0xf8) == 0xf0) ? 4 : + ((c & 0xfc) == 0xf8) ? 5 : + ((c & 0xfe) == 0xfc) ? 6 : 0; + if (n < 1) return FALSE; + k = n; + u = c & ((1 << (7 - n)) - 1); + } + break; + case 2: + case 3: + case 4: + case 5: + case 6: + if ((c & 0xc0) == 0x80) { + u = (u << 6) | (c & 0x3f); + k--; + if (k == 1) { + if ( + (n == 2 && u < 0x00000080) || + (n == 3 && u < 0x00000800) || + (n == 4 && u < 0x00010000) || + (n == 5 && u < 0x00200000) || + (n == 6 && u < 0x04000000) + ) return FALSE; + u = 0; + n = 0; + } + } + else { + return FALSE; + } + break; + default: + assert(((void)"unexpected control flow", 0)); + return FALSE; /* never reached */ + } + } + return (k == 1) ? TRUE : FALSE; +} + +static size_t utf8_to_utf32(const char *seq, int *out) { /* with checking UTF-8 validity */ + int u; + size_t i; + const int c = (int)(unsigned char)seq[0]; + const size_t n = (c < 0x80) ? 1 : + ((c & 0xe0) == 0xc0) ? 2 : + ((c & 0xf0) == 0xe0) ? 3 : + ((c & 0xf8) == 0xf0) ? 4 : + ((c & 0xfc) == 0xf8) ? 5 : + ((c & 0xfe) == 0xfc) ? 6 : 0; + if (n < 1) { /* invalid code sequence */ + if (out) *out = 0xfffd; + return 1; + } + u = (n <= 1) ? c : (c & ((1 << (7 - n)) - 1)); + for (i = 1; i < n; i++) { + const int d = (int)(unsigned char)seq[i]; + if ((d & 0xc0) != 0x80) { /* not a continuation byte */ + if (out) *out = 0xfffd; + return 1; + } + u = (u << 6) | (d & 0x3f); + } + if ( + (n == 2 && u < 0x00000080) || + (n == 3 && u < 0x00000800) || + (n == 4 && u < 0x00010000) || + (n == 5 && u < 0x00200000) || + (n == 6 && u < 0x04000000) + ) { /* invalidly encoded */ + if (out) *out = 0xfffd; + return 1; + } + if (out) *out = u; + return n; +} + +static bool_t unescape_string(char *str, bool_t cls) { /* cls: TRUE if used for character class matching */ + bool_t b = TRUE; + size_t i, j; + for (j = 0, i = 0; str[i]; i++) { + if (str[i] == '\\') { + i++; + switch (str[i]) { + case '\0': str[j++] = '\\'; str[j] = '\0'; return FALSE; + case '\'': str[j++] = '\''; break; + case '\"': str[j++] = '\"'; break; + case '0': str[j++] = '\x00'; break; + case 'a': str[j++] = '\x07'; break; + case 'b': str[j++] = '\x08'; break; + case 'f': str[j++] = '\x0c'; break; + case 'n': str[j++] = '\x0a'; break; + case 'r': str[j++] = '\x0d'; break; + case 't': str[j++] = '\x09'; break; + case 'v': str[j++] = '\x0b'; break; + case 'x': + { + char s = 0, c; + size_t k; + for (k = 0; k < 2; k++) { + char d; + c = str[i + k + 1]; + d = (c >= '0' && c <= '9') ? c - '0' : + (c >= 'a' && c <= 'f') ? c - 'a' + 10 : + (c >= 'A' && c <= 'F') ? c - 'A' + 10 : -1; + if (d < 0) break; + s = (s << 4) | d; + } + if (k < 2) { + const size_t l = i + k; + str[j++] = '\\'; str[j++] = 'x'; + while (i <= l) str[j++] = str[++i]; + if (c == '\0') return FALSE; + b = FALSE; + continue; + } + str[j++] = s; + i += 2; + } + break; + case 'u': + { + int s = 0, t = 0; + char c; + size_t k; + for (k = 0; k < 4; k++) { + char d; + c = str[i + k + 1]; + d = (c >= '0' && c <= '9') ? c - '0' : + (c >= 'a' && c <= 'f') ? c - 'a' + 10 : + (c >= 'A' && c <= 'F') ? c - 'A' + 10 : -1; + if (d < 0) break; + s = (s << 4) | d; + } + if (k < 4 || (s & 0xfc00) == 0xdc00) { /* invalid character or invalid surrogate code point */ + const size_t l = i + k; + str[j++] = '\\'; str[j++] = 'u'; + while (i <= l) str[j++] = str[++i]; + if (c == '\0') return FALSE; + b = FALSE; + continue; + } + if ((s & 0xfc00) == 0xd800) { /* surrogate pair */ + for (k = 4; k < 10; k++) { + c = str[i + k + 1]; + if (k == 4) { + if (c != '\\') break; + } + else if (k == 5) { + if (c != 'u') break; + } + else { + const char d = + (c >= '0' && c <= '9') ? c - '0' : + (c >= 'a' && c <= 'f') ? c - 'a' + 10 : + (c >= 'A' && c <= 'F') ? c - 'A' + 10 : -1; + if (d < 0) break; + t = (t << 4) | d; + } + } + if (k < 10 || (t & 0xfc00) != 0xdc00) { /* invalid character or invalid surrogate code point */ + const size_t l = i + 4; /* NOTE: Not i + k to redo with recovery. */ + str[j++] = '\\'; str[j++] = 'u'; + while (i <= l) str[j++] = str[++i]; + b = FALSE; + continue; + } + } + { + const int u = t ? ((((s & 0x03ff) + 0x0040) << 10) | (t & 0x03ff)) : s; + if (u < 0x0080) { + str[j++] = (char)u; + } + else if (u < 0x0800) { + str[j++] = (char)(0xc0 | (u >> 6)); + str[j++] = (char)(0x80 | (u & 0x3f)); + } + else if (u < 0x010000) { + str[j++] = (char)(0xe0 | (u >> 12)); + str[j++] = (char)(0x80 | ((u >> 6) & 0x3f)); + str[j++] = (char)(0x80 | (u & 0x3f)); + } + else if (u < 0x110000) { + str[j++] = (char)(0xf0 | (u >> 18)); + str[j++] = (char)(0x80 | ((u >> 12) & 0x3f)); + str[j++] = (char)(0x80 | ((u >> 6) & 0x3f)); + str[j++] = (char)(0x80 | (u & 0x3f)); + } + else { /* never reached theoretically; in case */ + const size_t l = i + 10; + str[j++] = '\\'; str[j++] = 'u'; + while (i <= l) str[j++] = str[++i]; + b = FALSE; + continue; + } + } + i += t ? 10 : 4; + } + break; + case '\n': break; + case '\r': if (str[i + 1] == '\n') i++; break; + case '\\': + if (cls) str[j++] = '\\'; /* left for character class matching (ex. considering [\^\]\\]) */ + str[j++] = '\\'; + break; + default: str[j++] = '\\'; str[j++] = str[i]; + } + } + else { + str[j++] = str[i]; + } + } + str[j] = '\0'; + return b; +} + +static const char *escape_character(char ch, char (*buf)[5]) { + switch (ch) { + case '\x00': strncpy(*buf, "\\0", 5); break; + case '\x07': strncpy(*buf, "\\a", 5); break; + case '\x08': strncpy(*buf, "\\b", 5); break; + case '\x0c': strncpy(*buf, "\\f", 5); break; + case '\x0a': strncpy(*buf, "\\n", 5); break; + case '\x0d': strncpy(*buf, "\\r", 5); break; + case '\x09': strncpy(*buf, "\\t", 5); break; + case '\x0b': strncpy(*buf, "\\v", 5); break; + case '\\': strncpy(*buf, "\\\\", 5); break; + case '\'': strncpy(*buf, "\\\'", 5); break; + case '\"': strncpy(*buf, "\\\"", 5); break; + default: + if (ch >= '\x20' && ch < '\x7f') + snprintf(*buf, 5, "%c", ch); + else + snprintf(*buf, 5, "\\x%02x", (int)(unsigned char)ch); + } + (*buf)[4] = '\0'; + return *buf; +} + +static void remove_leading_blanks(char *str) { + size_t i, j; + for (i = 0; str[i]; i++) { + if ( + str[i] != ' ' && + str[i] != '\v' && + str[i] != '\f' && + str[i] != '\t' && + str[i] != '\n' && + str[i] != '\r' + ) break; + } + for (j = 0; str[i]; i++) { + str[j++] = str[i]; + } + str[j] = '\0'; +} + +static void remove_trailing_blanks(char *str) { + size_t i, j; + for (j = 0, i = 0; str[i]; i++) { + if ( + str[i] != ' ' && + str[i] != '\v' && + str[i] != '\f' && + str[i] != '\t' && + str[i] != '\n' && + str[i] != '\r' + ) j = i + 1; + } + str[j] = '\0'; +} + +static size_t find_trailing_blanks(const char *str) { + size_t i, j; + for (j = 0, i = 0; str[i]; i++) { + if ( + str[i] != ' ' && + str[i] != '\v' && + str[i] != '\f' && + str[i] != '\t' && + str[i] != '\n' && + str[i] != '\r' + ) j = i + 1; + } + return j; +} + +static size_t count_characters(const char *str, size_t start, size_t end) { + /* UTF-8 multibyte character support but without checking UTF-8 validity */ + size_t n = 0, i = start; + while (i < end) { + const int c = (int)(unsigned char)str[i]; + if (c == 0) break; + n++; + i += (c < 0x80) ? 1 : + ((c & 0xe0) == 0xc0) ? 2 : + ((c & 0xf0) == 0xe0) ? 3 : + ((c & 0xf8) == 0xf0) ? 4 : + ((c & 0xfc) == 0xf8) ? 5 : + ((c & 0xfe) == 0xfc) ? 6 : /* invalid code */ 1; + } + return n; +} + +static void make_header_identifier(char *str) { + size_t i; + for (i = 0; str[i]; i++) { + str[i] = + ((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= '0' && str[i] <= '9')) ? str[i] : + (str[i] >= 'a' && str[i] <= 'z') ? str[i] - 'a' + 'A' : '_'; + } +} + +static void file_pos__init(file_pos_t *pos) { + pos->path = NULL; + pos->line = VOID_VALUE; + pos->col = VOID_VALUE; +} + +static void file_pos__set(file_pos_t *pos, const char *path, size_t line, size_t col) { + free(pos->path); + pos->path = path ? strdup_e(path) : NULL; + pos->line = line; + pos->col = col; +} + +static void file_pos__term(file_pos_t *pos) { + free(pos->path); +} + +static void file_id__get(FILE *file, const char *path, file_id_t *id) { +#ifdef _WIN32 /* Windows including MSVC and MinGW */ + const int f = _fileno(file); + if (f <= 2) { /* standard input/output/error */ + id->dwVolumeSerialNumber = ~(DWORD)0; + id->nFileIndexHigh = 0; + id->nFileIndexLow = f; + return; + } + if (GetFileInformationByHandle((HANDLE)_get_osfhandle(f), id) == 0) { + print_error("Cannot get file information: %s\n", path); + exit(2); + } +#else + if (fstat(fileno(file), id) != 0) { + print_error("Cannot get file information: %s\n", path); + exit(2); + } +#endif +} + +static bool_t file_id__equals(const file_id_t *id0, const file_id_t *id1) { +#ifdef _WIN32 /* Windows including MSVC and MinGW */ + return ( + id0->dwVolumeSerialNumber == id1->dwVolumeSerialNumber && + id0->nFileIndexHigh == id1->nFileIndexHigh && + id0->nFileIndexLow == id1->nFileIndexLow + ) ? TRUE : FALSE; +#else + return (id0->st_dev == id1->st_dev && id0->st_ino == id1->st_ino) ? TRUE : FALSE; +#endif +} + +static stream_t stream__wrap(FILE *file, const char *path, size_t line) { + stream_t s; + s.file = file; + s.path = path; + s.line = line; + return s; +} + +static int stream__putc(stream_t *stream, int c) { + const int r = fputc(c, stream->file); + if (r == EOF) { + print_error("File write error: %s\n", stream->path); + exit(2); + } + if (stream->line != VOID_VALUE) { + if (c == '\n') stream->line++; + } + return r; +} + +static int stream__puts(stream_t *stream, const char *s) { + const int r = fputs(s, stream->file); + if (r == EOF) { + print_error("File write error: %s\n", stream->path); + exit(2); + } + if (stream->line != VOID_VALUE) { + size_t i = 0; + for (i = 0; s[i]; i++) { + if (s[i] == '\n') stream->line++; + } + } + return r; +} + +__attribute__((format(printf, 2, 3))) +static int stream__printf(stream_t *stream, const char *format, ...) { + if (stream->line != VOID_VALUE) { +#define M 1024 + char s[M], *p = NULL; + int n = 0; + size_t l = 0; + { + va_list a; + va_start(a, format); + n = vsnprintf(NULL, 0, format, a); + va_end(a); + if (n < 0) { + print_error("Internal error [%d]\n", __LINE__); + exit(2); + } + l = (size_t)n + 1; + } + p = (l > M) ? (char *)malloc_e(l) : s; + { + va_list a; + va_start(a, format); + n = vsnprintf(p, l, format, a); + va_end(a); + if (n < 0 || (size_t)n >= l) { + print_error("Internal error [%d]\n", __LINE__); + exit(2); + } + } + stream__puts(stream, p); + if (p != s) free(p); + return n; +#undef M + } + else { + int n; + va_list a; + va_start(a, format); + n = vfprintf(stream->file, format, a); + va_end(a); + if (n < 0) { + print_error("File write error: %s\n", stream->path); + exit(2); + } + return n; + } +} + +static void stream__write_characters(stream_t *stream, char ch, size_t len) { + size_t i; + if (len == VOID_VALUE) return; /* for safety */ + for (i = 0; i < len; i++) stream__putc(stream, ch); +} + +static bool_t can_character_follow_action_variable_(char ch) { + return ( + ch != SUBST_MARKER && ch != '_' && !(ch >= 'A' && ch <= 'Z') && !(ch >= 'a' && ch <= 'z') && !(ch >= '0' && ch<= '9') + ) ? TRUE : FALSE; +} + +static void stream__write_text(stream_t *stream, const char *ptr, size_t len, bool_t isact, const subst_map_t *subst) { + size_t i; + if (len == VOID_VALUE) return; /* for safety */ + for (i = 0; i < len; i++) { + if (ptr[i] == '\r') { + if (i + 1 < len && ptr[i + 1] == '\n') i++; + stream__putc(stream, '\n'); + } + else if (ptr[i] == SUBST_MARKER) { + bool_t b = FALSE; + size_t j = i + 1; + if (j < len) { + char c = ptr[j++]; + if (isact && c == SUBST_MARKER) { /* "$$" */ + if (j >= len || can_character_follow_action_variable_(ptr[j])) { + stream__putc(stream, '_'); + stream__putc(stream, '_'); + b = TRUE; i++; + } + } + else if (isact && c == '0') { /* "$0" */ + if (j < len && (ptr[j] == 's' || ptr[j] == 'e')) j++; + if (j >= len || can_character_follow_action_variable_(ptr[j])) { + stream__putc(stream, '_'); + while (i + 1 < j) stream__putc(stream, ptr[++i]); + b = TRUE; + } + } + else if (isact && c >= '1' && c <= '9') { /* "$n" (n: a string to express a natural number) */ + while (j < len && ptr[j] >= '0' && ptr[j] <= '9') j++; + if (j < len && (ptr[j] == 's' || ptr[j] == 'e')) j++; + if (j >= len || can_character_follow_action_variable_(ptr[j])) { + stream__putc(stream, '_'); + while (i + 1 < j) stream__putc(stream, ptr[++i]); + b = TRUE; + } + } + else if (subst && c == '{') { /* "${str}" (str: a string to be replaced) */ + size_t is; + for (is = 0; is < subst->len; is++) { + const subst_entry_t *const p = &subst->buf[is]; + size_t k; + for (k = 0; p->istr[k] && j + k < len && p->istr[k] == ptr[j + k]; k++); + if (!p->istr[k] && j + k < len && ptr[j + k] == '}') { + size_t l; + for (l = 0; p->ostr[l]; l++) stream__putc(stream, p->ostr[l]); + b = TRUE; i = j + k; + break; + } + } + } + } + if (!b) stream__putc(stream, '$'); + } + else { + stream__putc(stream, ptr[i]); + } + } +} + +static void stream__write_escaped_string(stream_t *stream, const char *ptr, size_t len) { + char s[5]; + size_t i; + if (len == VOID_VALUE) return; /* for safety */ + for (i = 0; i < len; i++) { + stream__puts(stream, escape_character(ptr[i], &s)); + } +} + +static void stream__write_line_directive(stream_t *stream, const char *path, size_t lineno) { + stream__printf(stream, "#line " FMT_LU " \"", (ulong_t)(lineno + 1)); + stream__write_escaped_string(stream, path, strlen(path)); + stream__puts(stream, "\"\n"); +} + +static void stream__write_code_block( + stream_t *stream, const char *ptr, size_t len, size_t indent, const char *path, size_t lineno, bool_t isact, const subst_map_t *subst +) { + bool_t b = FALSE; + size_t i, j, k; + if (len == VOID_VALUE) return; /* for safety */ + j = find_first_trailing_space(ptr, 0, len, &k); + for (i = 0; i < j; i++) { + if ( + ptr[i] != ' ' && + ptr[i] != '\v' && + ptr[i] != '\f' && + ptr[i] != '\t' + ) break; + } + if (i < j) { + if (stream->line != VOID_VALUE) + stream__write_line_directive(stream, path, lineno); + if (ptr[i] != '#') + stream__write_characters(stream, ' ', indent); + stream__write_text(stream, ptr + i, j - i, isact, subst); + stream__putc(stream, '\n'); + b = TRUE; + } + else { + lineno++; + } + if (k < len) { + size_t m = VOID_VALUE; + size_t h; + for (i = k; i < len; i = h) { + j = find_first_trailing_space(ptr, i, len, &h); + if (i < j) { + if (stream->line != VOID_VALUE && !b) + stream__write_line_directive(stream, path, lineno); + if (ptr[i] != '#') { + const size_t l = count_indent_spaces(ptr, i, j, NULL); + if (m == VOID_VALUE || m > l) m = l; + } + b = TRUE; + } + else { + if (!b) { + k = h; + lineno++; + } + } + } + for (i = k; i < len; i = h) { + j = find_first_trailing_space(ptr, i, len, &h); + if (i < j) { + const size_t l = count_indent_spaces(ptr, i, j, &i); + if (ptr[i] != '#') { + assert(m != VOID_VALUE); /* m must have a valid value */ + assert(l >= m); + stream__write_characters(stream, ' ', l - m + indent); + } + stream__write_text(stream, ptr + i, j - i, isact, subst); + stream__putc(stream, '\n'); + b = TRUE; + } + else if (h < len) { + stream__putc(stream, '\n'); + } + } + } + if (stream->line != VOID_VALUE && b) + stream__write_line_directive(stream, stream->path, stream->line + 1); +} + +static void stream__write_footer(stream_t *stream, const char *ptr, size_t len, const char *path, size_t lineno, const subst_map_t *subst) { + bool_t b = FALSE; + size_t i, j, k; + if (len == VOID_VALUE) return; /* for safety */ + j = find_first_trailing_space(ptr, 0, len, &k); + for (i = 0; i < j; i++) { + if ( + ptr[i] != ' ' && + ptr[i] != '\v' && + ptr[i] != '\f' && + ptr[i] != '\t' + ) break; + } + if (i < j) { + if (stream->line != VOID_VALUE) + stream__write_line_directive(stream, path, lineno); + stream__write_text(stream, ptr + i, j - i, FALSE, subst); + stream__putc(stream, '\n'); + b = TRUE; + } + else { + lineno++; + } + if (k < len) { + size_t h; + for (i = k; i < len; i = h) { + j = find_first_trailing_space(ptr, i, len, &h); + if (i < j) { + if (stream->line != VOID_VALUE && !b) + stream__write_line_directive(stream, path, lineno); + b = TRUE; + break; + } + else { + if (!b) { + k = h; + lineno++; + } + } + } + for (i = k; i < len; i = h) { + j = find_first_trailing_space(ptr, i, len, &h); + if (i < j) { + stream__write_text(stream, ptr + i, j - i, FALSE, subst); + stream__putc(stream, '\n'); + } + else if (h < len) { + stream__putc(stream, '\n'); + } + } + } +} + +static char *get_home_directory(void) { +#ifdef _MSC_VER + char s[MAX_PATH]; + return (SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_DEFAULT, s) == S_OK) ? strdup_e(s) : NULL; +#else + const char *const s = getenv("HOME"); + return (s && s[0]) ? strdup_e(s) : NULL; +#endif +} + +#ifdef _MSC_VER + +static char *get_appdata_directory(void) { + char s[MAX_PATH]; + return (SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_DEFAULT, s) == S_OK) ? strdup_e(s) : NULL; +} + +#endif /* _MSC_VER */ + +static bool_t is_absolute_path(const char *path) { +#ifdef _WIN32 + return ( + path[0] == '\\' || + (((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) && path[1] == ':') + ) ? TRUE : FALSE; +#else + return (path[0] == '/') ? TRUE : FALSE; +#endif +} + +static const char *extract_filename(const char *path) { + size_t i = strlen(path); + while (i > 0) { + i--; +#ifdef _WIN32 + if (strchr("/\\:", path[i])) return path + i + 1; +#else + if (path[i] == '/') return path + i + 1; +#endif + } + return path; +} + +static char *replace_filename(const char *path, const char *name) { + const char *const p = extract_filename(path); + const size_t m = p - path; + const size_t n = strlen(name); + char *const s = (char *)malloc_e(m + n + 1); + memcpy(s, path, m); + memcpy(s + m, name, n + 1); + return s; +} + +static char *add_filename(const char *path, const char *name) { + const size_t m = strlen(path); + const size_t n = strlen(name); +#ifdef _WIN32 + const size_t d = (m > 0 && strchr("/\\:", path[m - 1]) == NULL) ? 1 : 0; +#else + const size_t d = (m > 0 && path[m - 1] != '/') ? 1 : 0; +#endif + char *const s = (char *)malloc_e(m + d + n + 1); + memcpy(s, path, m); + if (d) s[m] = '/'; + memcpy(s + m + d, name, n + 1); + return s; +} + +static const char *extract_fileext(const char *path) { + const size_t n = strlen(path); + size_t i = n; + while (i > 0) { + i--; +#ifdef _WIN32 + if (strchr("/\\:", path[i])) break; +#else + if (path[i] == '/') break; +#endif + if (path[i] == '.') return path + i; + } + return path + n; +} + +static char *replace_fileext(const char *path, const char *ext) { + const char *const p = extract_fileext(path); + const size_t m = p - path; + const size_t n = strlen(ext); + char *const s = (char *)malloc_e(m + n + 2); + memcpy(s, path, m); + s[m] = '.'; + memcpy(s + m + 1, ext, n + 1); + return s; +} + +static char *add_fileext(const char *path, const char *ext) { + const size_t m = strlen(path); + const size_t n = strlen(ext); + char *const s = (char *)malloc_e(m + n + 2); + memcpy(s, path, m); + s[m] = '.'; + memcpy(s + m + 1, ext, n + 1); + return s; +} + +static size_t hash_string(const char *str) { + size_t i, h = 0; + for (i = 0; str[i]; i++) { + h = h * 31 + str[i]; + } + return h; +} + +static size_t populate_bits(size_t x) { + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; +#if (defined __SIZEOF_SIZE_T__ && __SIZEOF_SIZE_T__ == 8) /* gcc or clang */ || defined _WIN64 /* MSVC */ + x |= x >> 32; +#endif + return x; +} + +static size_t column_number(const input_state_t *input) { /* 0-based */ + assert(input->bufpos + input->bufcur >= input->linepos); + if (input->ascii) + return input->charnum + input->bufcur - ((input->linepos > input->bufpos) ? input->linepos - input->bufpos : 0); + else + return input->charnum + count_characters( + input->buffer.buf, (input->linepos > input->bufpos) ? input->linepos - input->bufpos : 0, input->bufcur + ); +} + +static void file_id_array__init(file_id_array_t *array) { + array->len = 0; + array->max = 0; + array->buf = NULL; +} + +static bool_t file_id_array__add_if_not_yet(file_id_array_t *array, const file_id_t *id) { + size_t i; + for (i = 0; i < array->len; i++) { + if (file_id__equals(id, &(array->buf[i]))) return FALSE; /* already added */ + } + if (array->max <= array->len) { + const size_t n = array->len + 1; + size_t m = array->max; + if (m == 0) m = BUFFER_MIN_SIZE; + while (m < n && m != 0) m <<= 1; + if (m == 0) m = n; /* in case of shift overflow */ + array->buf = (file_id_t *)realloc_e(array->buf, sizeof(file_id_t) * m); + array->max = m; + } + array->buf[array->len++] = *id; + return TRUE; /* newly added */ +} + +static void file_id_array__term(file_id_array_t *array) { + free(array->buf); +} + +static void char_array__init(char_array_t *array) { + array->len = 0; + array->max = 0; + array->buf = NULL; +} + +static void char_array__add(char_array_t *array, char ch) { + if (array->max <= array->len) { + const size_t n = array->len + 1; + size_t m = array->max; + if (m == 0) m = BUFFER_MIN_SIZE; + while (m < n && m != 0) m <<= 1; + if (m == 0) m = n; /* in case of shift overflow */ + array->buf = (char *)realloc_e(array->buf, m); + array->max = m; + } + array->buf[array->len++] = ch; +} + +static void char_array__term(char_array_t *array) { + free(array->buf); +} + +static void string_array__init(string_array_t *array) { + array->len = 0; + array->max = 0; + array->buf = NULL; +} + +static void string_array__add(string_array_t *array, const char *str, size_t len) { + if (array->max <= array->len) { + const size_t n = array->len + 1; + size_t m = array->max; + if (m == 0) m = BUFFER_MIN_SIZE; + while (m < n && m != 0) m <<= 1; + if (m == 0) m = n; /* in case of shift overflow */ + array->buf = (char **)realloc_e(array->buf, sizeof(char *) * m); + array->max = m; + } + array->buf[array->len++] = (len == VOID_VALUE) ? strdup_e(str) : strndup_e(str, len); +} + +static void string_array__term(string_array_t *array) { + size_t i; + for (i = 0; i < array->len; i++) free(array->buf[i]); + free(array->buf); +} + +static void code_block__init(code_block_t *code) { + code->text = NULL; + code->len = 0; + file_pos__init(&code->fpos); +} + +static void code_block__term(code_block_t *code) { + file_pos__term(&code->fpos); + free(code->text); +} + +static void code_block_array__init(code_block_array_t *array) { + array->len = 0; + array->max = 0; + array->buf = NULL; +} + +static code_block_t *code_block_array__create_entry(code_block_array_t *array) { + if (array->max <= array->len) { + const size_t n = array->len + 1; + size_t m = array->max; + if (m == 0) m = ARRAY_MIN_SIZE; + while (m < n && m != 0) m <<= 1; + if (m == 0) m = n; /* in case of shift overflow */ + array->buf = (code_block_t *)realloc_e(array->buf, sizeof(code_block_t) * m); + array->max = m; + } + code_block__init(&array->buf[array->len]); + return &array->buf[array->len++]; +} + +static void code_block_array__term(code_block_array_t *array) { + while (array->len > 0) { + array->len--; + code_block__term(&array->buf[array->len]); + } + free(array->buf); +} + +static void node_array__init(node_array_t *array) { + array->len = 0; + array->max = 0; + array->buf = NULL; +} + +static void node_array__add(node_array_t *array, node_t *node) { + if (array->max <= array->len) { + const size_t n = array->len + 1; + size_t m = array->max; + if (m == 0) m = ARRAY_MIN_SIZE; + while (m < n && m != 0) m <<= 1; + if (m == 0) m = n; /* in case of shift overflow */ + array->buf = (node_t **)realloc_e(array->buf, sizeof(node_t *) * m); + array->max = m; + } + array->buf[array->len++] = node; +} + +static void destroy_node(node_t *node); + +static void node_array__term(node_array_t *array) { + while (array->len > 0) { + array->len--; + destroy_node(array->buf[array->len]); + } + free(array->buf); +} + +static void node_const_array__init(node_const_array_t *array) { + array->len = 0; + array->max = 0; + array->buf = NULL; +} + +static void node_const_array__add(node_const_array_t *array, const node_t *node) { + if (array->max <= array->len) { + const size_t n = array->len + 1; + size_t m = array->max; + if (m == 0) m = ARRAY_MIN_SIZE; + while (m < n && m != 0) m <<= 1; + if (m == 0) m = n; /* in case of shift overflow */ + array->buf = (const node_t **)realloc_e((node_t **)array->buf, sizeof(const node_t *) * m); + array->max = m; + } + array->buf[array->len++] = node; +} + +static void node_const_array__clear(node_const_array_t *array) { + array->len = 0; +} + +static void node_const_array__copy(node_const_array_t *array, const node_const_array_t *src) { + size_t i; + if (array == src) return; + node_const_array__clear(array); + for (i = 0; i < src->len; i++) { + node_const_array__add(array, src->buf[i]); + } +} + +static void node_const_array__term(node_const_array_t *array) { + free((node_t **)array->buf); +} + +static void subst_map__init(subst_map_t *map) { + map->len = 0; + map->max = 0; + map->buf = NULL; +} + +static void subst_map__add(subst_map_t *map, const char *istr, const char *ostr) { + if (map->max <= map->len) { + const size_t n = map->len + 1; + size_t m = map->max; + if (m == 0) m = ARRAY_MIN_SIZE; + while (m < n && m != 0) m <<= 1; + if (m == 0) m = n; /* in case of shift overflow */ + map->buf = (subst_entry_t *)realloc_e(map->buf, sizeof(subst_entry_t) * m); + map->max = m; + } + { + subst_entry_t *const p = &map->buf[map->len++]; + p->istr = strdup_e(istr); + p->ostr = strdup_e(ostr); + } +} + +static void subst_map__clear(subst_map_t *map) { + map->len = 0; +} + +static void subst_map__term(subst_map_t *map) { + while (map->len > 0) { + subst_entry_t *const p = &map->buf[--map->len]; + free(p->istr); + free(p->ostr); + } + free(map->buf); +} + +static input_state_t *create_input_state(const char *path, FILE *file, input_state_t *parent, const options_t *opts) { + input_state_t *const input = (input_state_t *)malloc_e(sizeof(input_state_t)); + input->path = strdup_e((path && path[0]) ? path : ""); + input->file = file ? file : (path && path[0]) ? fopen_rb_e(path) : stdin; + input->ascii = opts->ascii; + input->flags = CODE_FLAG__NONE; + input->errnum = 0; + input->linenum = 0; + input->charnum = 0; + input->linepos = 0; + input->bufpos = 0; + input->bufcur = 0; + char_array__init(&input->buffer); + input->parent = parent; + return input; +} + +static input_state_t *destroy_input_state(input_state_t *input) { + input_state_t *parent; + if (input == NULL) return NULL; + parent = input->parent; + char_array__term(&input->buffer); + fclose_e(input->file, input->path); + free(input->path); + free(input); + return parent; +} + +static bool_t is_in_imported_input(const input_state_t *input) { + return input->parent ? TRUE : FALSE; +} + +static context_t *create_context(const char *ipath, const char *opath, const string_array_t *dirs, const options_t *opts) { + context_t *const ctx = (context_t *)malloc_e(sizeof(context_t)); + ctx->spath = (opath && opath[0]) ? add_fileext(opath, "c") : replace_fileext((ipath && ipath[0]) ? ipath : "-", "c"); + ctx->hpath = (opath && opath[0]) ? add_fileext(opath, "h") : replace_fileext((ipath && ipath[0]) ? ipath : "-", "h"); + ctx->hid = strdup_e(extract_filename(ctx->hpath)); make_header_identifier(ctx->hid); + ctx->vtype = NULL; + ctx->atype = NULL; + ctx->prefix = NULL; + ctx->dirs = dirs; + ctx->opts = *opts; + ctx->flags = CODE_FLAG__NONE; + ctx->errnum = 0; + ctx->input = create_input_state(ipath, NULL, NULL, opts); + file_id_array__init(&ctx->done); + subst_map__init(&ctx->subst); + node_array__init(&ctx->rules); + ctx->rulehash.mod = 0; + ctx->rulehash.max = 0; + ctx->rulehash.buf = NULL; + code_block_array__init(&ctx->esource); + code_block_array__init(&ctx->eheader); + code_block_array__init(&ctx->source); + code_block_array__init(&ctx->header); + code_block_array__init(&ctx->fsource); + return ctx; +} + +static void destroy_context(context_t *ctx) { + if (ctx == NULL) return; + code_block_array__term(&ctx->fsource); + code_block_array__term(&ctx->header); + code_block_array__term(&ctx->source); + code_block_array__term(&ctx->eheader); + code_block_array__term(&ctx->esource); + free((node_t **)ctx->rulehash.buf); + node_array__term(&ctx->rules); + subst_map__term(&ctx->subst); + file_id_array__term(&ctx->done); + while (ctx->input) ctx->input = destroy_input_state(ctx->input); + free(ctx->prefix); + free(ctx->atype); + free(ctx->vtype); + free(ctx->hid); + free(ctx->hpath); + free(ctx->spath); + free(ctx); +} + +static node_t *create_node(node_type_t type) { + node_t *const node = (node_t *)malloc_e(sizeof(node_t)); + node->type = type; + switch (node->type) { + case NODE_RULE: + node->data.rule.name = NULL; + node->data.rule.expr = NULL; + node->data.rule.ref = 0; + node->data.rule.used = FALSE; + node_const_array__init(&node->data.rule.vars); + node_const_array__init(&node->data.rule.capts); + node_const_array__init(&node->data.rule.codes); + file_pos__init(&node->data.rule.fpos); + break; + case NODE_REFERENCE: + node->data.reference.var = NULL; + node->data.reference.index = VOID_VALUE; + node->data.reference.name = NULL; + node->data.reference.rule = NULL; + file_pos__init(&node->data.reference.fpos); + break; + case NODE_STRING: + node->data.string.value = NULL; + break; + case NODE_CHARCLASS: + node->data.charclass.value = NULL; + break; + case NODE_POSITION: + node->data.position.value = 0; + break; + case NODE_QUANTITY: + node->data.quantity.min = node->data.quantity.max = 0; + node->data.quantity.expr = NULL; + break; + case NODE_PREDICATE: + node->data.predicate.neg = FALSE; + node->data.predicate.expr = NULL; + break; + case NODE_SEQUENCE: + node_array__init(&node->data.sequence.nodes); + break; + case NODE_ALTERNATE: + node_array__init(&node->data.alternate.nodes); + break; + case NODE_CAPTURE: + node->data.capture.expr = NULL; + node->data.capture.index = VOID_VALUE; + break; + case NODE_EXPAND: + node->data.expand.index = VOID_VALUE; + file_pos__init(&node->data.expand.fpos); + break; + case NODE_ACTION: + code_block__init(&node->data.action.code); + node->data.action.index = VOID_VALUE; + node_const_array__init(&node->data.action.vars); + node_const_array__init(&node->data.action.capts); + break; + case NODE_ERROR: + node->data.error.expr = NULL; + code_block__init(&node->data.error.code); + node->data.error.index = VOID_VALUE; + node_const_array__init(&node->data.error.vars); + node_const_array__init(&node->data.error.capts); + break; + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } + return node; +} + +static void destroy_node(node_t *node) { + if (node == NULL) return; + switch (node->type) { + case NODE_RULE: + file_pos__term(&node->data.rule.fpos); + node_const_array__term(&node->data.rule.codes); + node_const_array__term(&node->data.rule.capts); + node_const_array__term(&node->data.rule.vars); + destroy_node(node->data.rule.expr); + free(node->data.rule.name); + break; + case NODE_REFERENCE: + file_pos__term(&node->data.reference.fpos); + free(node->data.reference.name); + free(node->data.reference.var); + break; + case NODE_STRING: + free(node->data.string.value); + break; + case NODE_CHARCLASS: + free(node->data.charclass.value); + break; + case NODE_POSITION: + break; + case NODE_QUANTITY: + destroy_node(node->data.quantity.expr); + break; + case NODE_PREDICATE: + destroy_node(node->data.predicate.expr); + break; + case NODE_SEQUENCE: + node_array__term(&node->data.sequence.nodes); + break; + case NODE_ALTERNATE: + node_array__term(&node->data.alternate.nodes); + break; + case NODE_CAPTURE: + destroy_node(node->data.capture.expr); + break; + case NODE_EXPAND: + file_pos__term(&node->data.expand.fpos); + break; + case NODE_ACTION: + node_const_array__term(&node->data.action.capts); + node_const_array__term(&node->data.action.vars); + code_block__term(&node->data.action.code); + break; + case NODE_ERROR: + node_const_array__term(&node->data.error.capts); + node_const_array__term(&node->data.error.vars); + code_block__term(&node->data.error.code); + destroy_node(node->data.error.expr); + break; + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } + free(node); +} + +static void make_rulehash(context_t *ctx) { + size_t i, j; + ctx->rulehash.mod = populate_bits(ctx->rules.len * 4); + ctx->rulehash.max = ctx->rulehash.mod + 1; + ctx->rulehash.buf = (const node_t **)realloc_e((node_t **)ctx->rulehash.buf, sizeof(const node_t *) * ctx->rulehash.max); + for (i = 0; i < ctx->rulehash.max; i++) { + ctx->rulehash.buf[i] = NULL; + } + for (i = 0; i < ctx->rules.len; i++) { + node_rule_t *const rule = &ctx->rules.buf[i]->data.rule; + assert(ctx->rules.buf[i]->type == NODE_RULE); + j = hash_string(rule->name) & ctx->rulehash.mod; + while (ctx->rulehash.buf[j] != NULL) { + if (strcmp(rule->name, ctx->rulehash.buf[j]->data.rule.name) == 0) { + assert(rule->ref == 0); + assert(ctx->rulehash.buf[j]->data.rule.ref <= 0); /* always 0 or -1 */ + rule->ref = -1; /* marks as duplicate */ + ((node_t *)ctx->rulehash.buf[j])->data.rule.ref = -1; /* marks as duplicate */ + goto EXCEPTION; + } + j = (j + 1) & ctx->rulehash.mod; + } + ctx->rulehash.buf[j] = ctx->rules.buf[i]; + + EXCEPTION:; + } +} + +static const node_t *lookup_rulehash(const context_t *ctx, const char *name) { + size_t j = hash_string(name) & ctx->rulehash.mod; + while (ctx->rulehash.buf[j] != NULL && strcmp(name, ctx->rulehash.buf[j]->data.rule.name) != 0) { + j = (j + 1) & ctx->rulehash.mod; + } + return (ctx->rulehash.buf[j] != NULL) ? ctx->rulehash.buf[j] : NULL; +} + +static void link_references(context_t *ctx, node_t *node) { + if (node == NULL) return; + switch (node->type) { + case NODE_RULE: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + case NODE_REFERENCE: + node->data.reference.rule = lookup_rulehash(ctx, node->data.reference.name); + if (node->data.reference.rule == NULL) { + print_error( + "%s:" FMT_LU ":" FMT_LU ": No definition of rule: '%s'\n", + node->data.reference.fpos.path, + (ulong_t)(node->data.reference.fpos.line + 1), (ulong_t)(node->data.reference.fpos.col + 1), + node->data.reference.name + ); + ctx->errnum++; + } + else if (node->data.reference.rule->data.rule.ref >= 0) { /* the target rule is not defined multiple times */ + assert(node->data.reference.rule->type == NODE_RULE); + ((node_t *)node->data.reference.rule)->data.rule.ref++; + } + break; + case NODE_STRING: + break; + case NODE_CHARCLASS: + break; + case NODE_POSITION: + break; + case NODE_QUANTITY: + link_references(ctx, node->data.quantity.expr); + break; + case NODE_PREDICATE: + link_references(ctx, node->data.predicate.expr); + break; + case NODE_SEQUENCE: + { + size_t i; + for (i = 0; i < node->data.sequence.nodes.len; i++) { + link_references(ctx, node->data.sequence.nodes.buf[i]); + } + } + break; + case NODE_ALTERNATE: + { + size_t i; + for (i = 0; i < node->data.alternate.nodes.len; i++) { + link_references(ctx, node->data.alternate.nodes.buf[i]); + } + } + break; + case NODE_CAPTURE: + link_references(ctx, node->data.capture.expr); + break; + case NODE_EXPAND: + break; + case NODE_ACTION: + break; + case NODE_ERROR: + link_references(ctx, node->data.error.expr); + break; + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } +} + +static void mark_rules_if_used(context_t *ctx, node_t *node) { + if (node == NULL) return; + switch (node->type) { + case NODE_RULE: + if (!node->data.rule.used) { + node->data.rule.used = TRUE; + mark_rules_if_used(ctx, node->data.rule.expr); + } + break; + case NODE_REFERENCE: + mark_rules_if_used(ctx, (node_t *)node->data.reference.rule); + break; + case NODE_STRING: + break; + case NODE_CHARCLASS: + break; + case NODE_POSITION: + break; + case NODE_QUANTITY: + mark_rules_if_used(ctx, node->data.quantity.expr); + break; + case NODE_PREDICATE: + mark_rules_if_used(ctx, node->data.predicate.expr); + break; + case NODE_SEQUENCE: + { + size_t i; + for (i = 0; i < node->data.sequence.nodes.len; i++) { + mark_rules_if_used(ctx, node->data.sequence.nodes.buf[i]); + } + } + break; + case NODE_ALTERNATE: + { + size_t i; + for (i = 0; i < node->data.alternate.nodes.len; i++) { + mark_rules_if_used(ctx, node->data.alternate.nodes.buf[i]); + } + } + break; + case NODE_CAPTURE: + mark_rules_if_used(ctx, node->data.capture.expr); + break; + case NODE_EXPAND: + break; + case NODE_ACTION: + break; + case NODE_ERROR: + mark_rules_if_used(ctx, node->data.error.expr); + break; + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } +} + +static void unreference_rules_from_unused_rule(context_t *ctx, node_t *node) { + if (node == NULL) return; + switch (node->type) { + case NODE_RULE: + unreference_rules_from_unused_rule(ctx, node->data.rule.expr); + break; + case NODE_REFERENCE: + if (node->data.reference.rule && node->data.reference.rule->data.rule.ref > 0) + ((node_t *)node->data.reference.rule)->data.rule.ref--; + break; + case NODE_STRING: + break; + case NODE_CHARCLASS: + break; + case NODE_POSITION: + break; + case NODE_QUANTITY: + unreference_rules_from_unused_rule(ctx, node->data.quantity.expr); + break; + case NODE_PREDICATE: + unreference_rules_from_unused_rule(ctx, node->data.predicate.expr); + break; + case NODE_SEQUENCE: + { + size_t i; + for (i = 0; i < node->data.sequence.nodes.len; i++) { + unreference_rules_from_unused_rule(ctx, node->data.sequence.nodes.buf[i]); + } + } + break; + case NODE_ALTERNATE: + { + size_t i; + for (i = 0; i < node->data.alternate.nodes.len; i++) { + unreference_rules_from_unused_rule(ctx, node->data.alternate.nodes.buf[i]); + } + } + break; + case NODE_CAPTURE: + unreference_rules_from_unused_rule(ctx, node->data.capture.expr); + break; + case NODE_EXPAND: + break; + case NODE_ACTION: + break; + case NODE_ERROR: + unreference_rules_from_unused_rule(ctx, node->data.error.expr); + break; + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } +} + +static void verify_variables(context_t *ctx, node_t *node, node_const_array_t *vars) { + node_const_array_t a; + const bool_t b = (vars == NULL) ? TRUE : FALSE; + if (node == NULL) return; + if (b) { + node_const_array__init(&a); + vars = &a; + } + switch (node->type) { + case NODE_RULE: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + case NODE_REFERENCE: + if (node->data.reference.index != VOID_VALUE) { + size_t i; + for (i = 0; i < vars->len; i++) { + assert(vars->buf[i]->type == NODE_REFERENCE); + if (node->data.reference.index == vars->buf[i]->data.reference.index) break; + } + if (i == vars->len) node_const_array__add(vars, node); + } + break; + case NODE_STRING: + break; + case NODE_CHARCLASS: + break; + case NODE_POSITION: + break; + case NODE_QUANTITY: + verify_variables(ctx, node->data.quantity.expr, vars); + break; + case NODE_PREDICATE: + verify_variables(ctx, node->data.predicate.expr, vars); + break; + case NODE_SEQUENCE: + { + size_t i; + for (i = 0; i < node->data.sequence.nodes.len; i++) { + verify_variables(ctx, node->data.sequence.nodes.buf[i], vars); + } + } + break; + case NODE_ALTERNATE: + { + size_t i, j, k, m = vars->len; + node_const_array_t v; + node_const_array__init(&v); + node_const_array__copy(&v, vars); + for (i = 0; i < node->data.alternate.nodes.len; i++) { + v.len = m; + verify_variables(ctx, node->data.alternate.nodes.buf[i], &v); + for (j = m; j < v.len; j++) { + for (k = m; k < vars->len; k++) { + if (v.buf[j]->data.reference.index == vars->buf[k]->data.reference.index) break; + } + if (k == vars->len) node_const_array__add(vars, v.buf[j]); + } + } + node_const_array__term(&v); + } + break; + case NODE_CAPTURE: + verify_variables(ctx, node->data.capture.expr, vars); + break; + case NODE_EXPAND: + break; + case NODE_ACTION: + node_const_array__copy(&node->data.action.vars, vars); + break; + case NODE_ERROR: + node_const_array__copy(&node->data.error.vars, vars); + verify_variables(ctx, node->data.error.expr, vars); + break; + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } + if (b) { + node_const_array__term(&a); + } +} + +static void verify_captures(context_t *ctx, node_t *node, node_const_array_t *capts) { + node_const_array_t a; + const bool_t b = (capts == NULL) ? TRUE : FALSE; + if (node == NULL) return; + if (b) { + node_const_array__init(&a); + capts = &a; + } + switch (node->type) { + case NODE_RULE: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + case NODE_REFERENCE: + break; + case NODE_STRING: + break; + case NODE_CHARCLASS: + break; + case NODE_POSITION: + break; + case NODE_QUANTITY: + verify_captures(ctx, node->data.quantity.expr, capts); + break; + case NODE_PREDICATE: + verify_captures(ctx, node->data.predicate.expr, capts); + break; + case NODE_SEQUENCE: + { + size_t i; + for (i = 0; i < node->data.sequence.nodes.len; i++) { + verify_captures(ctx, node->data.sequence.nodes.buf[i], capts); + } + } + break; + case NODE_ALTERNATE: + { + size_t i, j, m = capts->len; + node_const_array_t v; + node_const_array__init(&v); + node_const_array__copy(&v, capts); + for (i = 0; i < node->data.alternate.nodes.len; i++) { + v.len = m; + verify_captures(ctx, node->data.alternate.nodes.buf[i], &v); + for (j = m; j < v.len; j++) { + node_const_array__add(capts, v.buf[j]); + } + } + node_const_array__term(&v); + } + break; + case NODE_CAPTURE: + verify_captures(ctx, node->data.capture.expr, capts); + node_const_array__add(capts, node); + break; + case NODE_EXPAND: + { + size_t i; + for (i = 0; i < capts->len; i++) { + assert(capts->buf[i]->type == NODE_CAPTURE); + if (node->data.expand.index == capts->buf[i]->data.capture.index) break; + } + if (i >= capts->len && node->data.expand.index != VOID_VALUE) { + print_error( + "%s:" FMT_LU ":" FMT_LU ": Capture " FMT_LU " not available at this position\n", + node->data.expand.fpos.path, + (ulong_t)(node->data.expand.fpos.line + 1), (ulong_t)(node->data.expand.fpos.col + 1), + (ulong_t)(node->data.expand.index + 1) + ); + ctx->errnum++; + } + } + break; + case NODE_ACTION: + node_const_array__copy(&node->data.action.capts, capts); + break; + case NODE_ERROR: + node_const_array__copy(&node->data.error.capts, capts); + verify_captures(ctx, node->data.error.expr, capts); + break; + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } + if (b) { + node_const_array__term(&a); + } +} + +static void dump_escaped_string(const char *str) { + char s[5]; + if (str == NULL) { + fprintf(stdout, "null"); + return; + } + while (*str) { + fprintf(stdout, "%s", escape_character(*str++, &s)); + } +} + +static void dump_integer_value(size_t value) { + if (value == VOID_VALUE) { + fprintf(stdout, "void"); + } + else { + fprintf(stdout, FMT_LU, (ulong_t)value); + } +} + +static void dump_node(context_t *ctx, const node_t *node, const int indent) { + if (node == NULL) return; + switch (node->type) { + case NODE_RULE: + fprintf( + stdout, "%*sRule(name:'%s', ref:%d, vars.len:" FMT_LU ", capts.len:" FMT_LU ", codes.len:" FMT_LU ") {\n", + indent, "", node->data.rule.name, node->data.rule.ref, + (ulong_t)node->data.rule.vars.len, (ulong_t)node->data.rule.capts.len, (ulong_t)node->data.rule.codes.len + ); + dump_node(ctx, node->data.rule.expr, indent + 2); + fprintf(stdout, "%*s}\n", indent, ""); + break; + case NODE_REFERENCE: + fprintf(stdout, "%*sReference(var:'%s', index:", indent, "", node->data.reference.var); + dump_integer_value(node->data.reference.index); + fprintf( + stdout, ", name:'%s', rule:'%s')\n", node->data.reference.name, + (node->data.reference.rule) ? node->data.reference.rule->data.rule.name : NULL + ); + break; + case NODE_STRING: + fprintf(stdout, "%*sString(value:'", indent, ""); + dump_escaped_string(node->data.string.value); + fprintf(stdout, "')\n"); + break; + case NODE_CHARCLASS: + fprintf(stdout, "%*sCharclass(value:'", indent, ""); + dump_escaped_string(node->data.charclass.value); + fprintf(stdout, "')\n"); + break; + case NODE_POSITION: + fprintf(stdout, "%*sPosition(value:" FMT_LU ")\n", indent, "", (ulong_t)node->data.position.value); + break; + case NODE_QUANTITY: + fprintf(stdout, "%*sQuantity(min:%d, max:%d) {\n", indent, "", node->data.quantity.min, node->data.quantity.max); + dump_node(ctx, node->data.quantity.expr, indent + 2); + fprintf(stdout, "%*s}\n", indent, ""); + break; + case NODE_PREDICATE: + fprintf(stdout, "%*sPredicate(neg:%d) {\n", indent, "", node->data.predicate.neg); + dump_node(ctx, node->data.predicate.expr, indent + 2); + fprintf(stdout, "%*s}\n", indent, ""); + break; + case NODE_SEQUENCE: + fprintf( + stdout, "%*sSequence(max:" FMT_LU ", len:" FMT_LU ") {\n", + indent, "", (ulong_t)node->data.sequence.nodes.max, (ulong_t)node->data.sequence.nodes.len + ); + { + size_t i; + for (i = 0; i < node->data.sequence.nodes.len; i++) { + dump_node(ctx, node->data.sequence.nodes.buf[i], indent + 2); + } + } + fprintf(stdout, "%*s}\n", indent, ""); + break; + case NODE_ALTERNATE: + fprintf( + stdout, "%*sAlternate(max:" FMT_LU ", len:" FMT_LU ") {\n", + indent, "", (ulong_t)node->data.alternate.nodes.max, (ulong_t)node->data.alternate.nodes.len + ); + { + size_t i; + for (i = 0; i < node->data.alternate.nodes.len; i++) { + dump_node(ctx, node->data.alternate.nodes.buf[i], indent + 2); + } + } + fprintf(stdout, "%*s}\n", indent, ""); + break; + case NODE_CAPTURE: + fprintf(stdout, "%*sCapture(index:", indent, ""); + dump_integer_value(node->data.capture.index); + fprintf(stdout, ") {\n"); + dump_node(ctx, node->data.capture.expr, indent + 2); + fprintf(stdout, "%*s}\n", indent, ""); + break; + case NODE_EXPAND: + fprintf(stdout, "%*sExpand(index:", indent, ""); + dump_integer_value(node->data.expand.index); + fprintf(stdout, ")\n"); + break; + case NODE_ACTION: + fprintf(stdout, "%*sAction(index:", indent, ""); + dump_integer_value(node->data.action.index); + fprintf(stdout, ", code:{"); + dump_escaped_string(node->data.action.code.text); + fprintf(stdout, "}, vars:"); + if (node->data.action.vars.len + node->data.action.capts.len > 0) { + size_t i; + fprintf(stdout, "\n"); + for (i = 0; i < node->data.action.vars.len; i++) { + fprintf(stdout, "%*s'%s'\n", indent + 2, "", node->data.action.vars.buf[i]->data.reference.var); + } + for (i = 0; i < node->data.action.capts.len; i++) { + fprintf(stdout, "%*s$" FMT_LU "\n", indent + 2, "", (ulong_t)(node->data.action.capts.buf[i]->data.capture.index + 1)); + } + fprintf(stdout, "%*s)\n", indent, ""); + } + else { + fprintf(stdout, "none)\n"); + } + break; + case NODE_ERROR: + fprintf(stdout, "%*sError(index:", indent, ""); + dump_integer_value(node->data.error.index); + fprintf(stdout, ", code:{"); + dump_escaped_string(node->data.error.code.text); + fprintf(stdout, "}, vars:\n"); + { + size_t i; + for (i = 0; i < node->data.error.vars.len; i++) { + fprintf(stdout, "%*s'%s'\n", indent + 2, "", node->data.error.vars.buf[i]->data.reference.var); + } + for (i = 0; i < node->data.error.capts.len; i++) { + fprintf(stdout, "%*s$" FMT_LU "\n", indent + 2, "", (ulong_t)(node->data.error.capts.buf[i]->data.capture.index + 1)); + } + } + fprintf(stdout, "%*s) {\n", indent, ""); + dump_node(ctx, node->data.error.expr, indent + 2); + fprintf(stdout, "%*s}\n", indent, ""); + break; + default: + print_error("%*sInternal error [%d]\n", indent, "", __LINE__); + exit(-1); + } +} + +static size_t refill_buffer(input_state_t *input, size_t num) { + if (input->buffer.len >= input->bufcur + num) return input->buffer.len - input->bufcur; + while (input->buffer.len < input->bufcur + num) { + const int c = fgetc_e(input->file, input->path); + if (c == EOF) break; + char_array__add(&input->buffer, (char)c); + } + return input->buffer.len - input->bufcur; +} + +static void commit_buffer(input_state_t *input) { + assert(input->buffer.len >= input->bufcur); + if (input->linepos < input->bufpos + input->bufcur) + input->charnum += input->ascii ? input->bufcur : count_characters(input->buffer.buf, 0, input->bufcur); + memmove(input->buffer.buf, input->buffer.buf + input->bufcur, input->buffer.len - input->bufcur); + input->buffer.len -= input->bufcur; + input->bufpos += input->bufcur; + input->bufcur = 0; +} + +static bool_t match_eof(input_state_t *input) { + return (refill_buffer(input, 1) < 1) ? TRUE : FALSE; +} + +static bool_t match_eol(input_state_t *input) { + if (refill_buffer(input, 1) >= 1) { + switch (input->buffer.buf[input->bufcur]) { + case '\n': + input->bufcur++; + input->linenum++; + input->charnum = 0; + input->linepos = input->bufpos + input->bufcur; + return TRUE; + case '\r': + input->bufcur++; + if (refill_buffer(input, 1) >= 1) { + if (input->buffer.buf[input->bufcur] == '\n') input->bufcur++; + } + input->linenum++; + input->charnum = 0; + input->linepos = input->bufpos + input->bufcur; + return TRUE; + } + } + return FALSE; +} + +static bool_t match_character(input_state_t *input, char ch) { + if (refill_buffer(input, 1) >= 1) { + if (input->buffer.buf[input->bufcur] == ch) { + input->bufcur++; + return TRUE; + } + } + return FALSE; +} + +static bool_t match_character_range(input_state_t *input, char min, char max) { + if (refill_buffer(input, 1) >= 1) { + const char c = input->buffer.buf[input->bufcur]; + if (c >= min && c <= max) { + input->bufcur++; + return TRUE; + } + } + return FALSE; +} + +static bool_t match_character_set(input_state_t *input, const char *chs) { + if (refill_buffer(input, 1) >= 1) { + const char c = input->buffer.buf[input->bufcur]; + size_t i; + for (i = 0; chs[i]; i++) { + if (c == chs[i]) { + input->bufcur++; + return TRUE; + } + } + } + return FALSE; +} + +static bool_t match_character_any(input_state_t *input) { + if (refill_buffer(input, 1) >= 1) { + input->bufcur++; + return TRUE; + } + return FALSE; +} + +static bool_t match_string(input_state_t *input, const char *str) { + const size_t n = strlen(str); + if (refill_buffer(input, n) >= n) { + if (strncmp(input->buffer.buf + input->bufcur, str, n) == 0) { + input->bufcur += n; + return TRUE; + } + } + return FALSE; +} + +static bool_t match_blank(input_state_t *input) { + return match_character_set(input, " \t\v\f"); +} + +static bool_t match_section_line_(input_state_t *input, const char *head) { + if (match_string(input, head)) { + while (!match_eol(input) && !match_eof(input)) match_character_any(input); + return TRUE; + } + return FALSE; +} + +static bool_t match_section_line_continuable_(input_state_t *input, const char *head) { + if (match_string(input, head)) { + while (!match_eof(input)) { + const size_t p = input->bufcur; + if (match_eol(input)) { + if (input->buffer.buf[p - 1] != '\\') break; + } + else { + match_character_any(input); + } + } + return TRUE; + } + return FALSE; +} + +static bool_t match_section_block_(input_state_t *input, const char *left, const char *right, const char *name) { + const size_t l = input->linenum; + const size_t m = column_number(input); + if (match_string(input, left)) { + while (!match_string(input, right)) { + if (match_eof(input)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Premature EOF in %s\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), name); + input->errnum++; + break; + } + if (!match_eol(input)) match_character_any(input); + } + return TRUE; + } + return FALSE; +} + +static bool_t match_quotation_(input_state_t *input, const char *left, const char *right, const char *name) { + const size_t l = input->linenum; + const size_t m = column_number(input); + if (match_string(input, left)) { + while (!match_string(input, right)) { + if (match_eof(input)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Premature EOF in %s\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), name); + input->errnum++; + break; + } + match_character(input, '\\'); + if (match_eol(input)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Premature EOL in %s\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), name); + input->errnum++; + break; + } + match_character_any(input); + } + return TRUE; + } + return FALSE; +} + +static bool_t match_comment(input_state_t *input) { + return match_section_line_(input, "#"); +} + +static bool_t match_comment_c(input_state_t *input) { + return match_section_block_(input, "/*", "*/", "C comment"); +} + +static bool_t match_comment_cxx(input_state_t *input) { + return match_section_line_continuable_(input, "//"); +} + +static bool_t match_quotation_single(input_state_t *input) { + return match_quotation_(input, "\'", "\'", "single quotation"); +} + +static bool_t match_quotation_double(input_state_t *input) { + return match_quotation_(input, "\"", "\"", "double quotation"); +} + +static bool_t match_character_class(input_state_t *input) { + return match_quotation_(input, "[", "]", "character class"); +} + +static bool_t match_directive_c(input_state_t *input) { + if (match_character(input, '#')) { + while (!match_eof(input)) { + const size_t p = input->bufcur; + if (match_eol(input)) { + if (input->buffer.buf[p - 1] != '\\') break; + } + else if (match_comment_cxx(input)) { + break; + } + else if ( + !match_comment_c(input) && + !match_quotation_single(input) && + !match_quotation_double(input) && + !match_character_any(input) + ) { + break; + } + } + return TRUE; + } + return FALSE; +} + +static bool_t match_spaces(input_state_t *input) { + size_t n = 0; + while (match_blank(input) || match_eol(input) || match_comment(input)) n++; + return (n > 0) ? TRUE : FALSE; +} + +static bool_t match_number(input_state_t *input) { + if (match_character_range(input, '0', '9')) { + while (match_character_range(input, '0', '9')); + return TRUE; + } + return FALSE; +} + +static bool_t match_identifier(input_state_t *input) { + if ( + match_character_range(input, 'a', 'z') || + match_character_range(input, 'A', 'Z') || + match_character(input, '_') + ) { + while ( + match_character_range(input, 'a', 'z') || + match_character_range(input, 'A', 'Z') || + match_character_range(input, '0', '9') || + match_character(input, '_') + ); + return TRUE; + } + return FALSE; +} + +static bool_t match_code_block(input_state_t *input) { + const size_t l = input->linenum; + const size_t m = column_number(input); + if (match_character(input, '{')) { + int d = 1; + for (;;) { + if (match_eof(input)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Premature EOF in code block\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + input->errnum++; + break; + } + if ( + match_directive_c(input) || + match_comment_c(input) || + match_comment_cxx(input) || + match_quotation_single(input) || + match_quotation_double(input) + ) continue; + if (match_character(input, '{')) { + d++; + } + else if (match_character(input, '}')) { + d--; + if (d == 0) break; + } + else if (!match_eol(input)) { + match_character_any(input); + } + } + return TRUE; + } + return FALSE; +} + +static bool_t match_footer_start(input_state_t *input) { + return match_string(input, "%%"); +} + +static node_t *parse_expression(input_state_t *input, node_t *rule); + +static node_t *parse_primary(input_state_t *input, node_t *rule) { + const size_t p = input->bufcur; + const size_t l = input->linenum; + const size_t m = column_number(input); + const size_t n = input->charnum; + const size_t o = input->linepos; + node_t *n_p = NULL; + if (match_identifier(input)) { + const size_t q = input->bufcur; + size_t r = VOID_VALUE, s = VOID_VALUE; + match_spaces(input); + if (match_character(input, ':')) { + match_spaces(input); + r = input->bufcur; + if (!match_identifier(input)) goto EXCEPTION; + s = input->bufcur; + match_spaces(input); + } + if (match_string(input, "<-")) goto EXCEPTION; + n_p = create_node(NODE_REFERENCE); + if (r == VOID_VALUE) { + assert(q >= p); + n_p->data.reference.var = NULL; + n_p->data.reference.index = VOID_VALUE; + n_p->data.reference.name = strndup_e(input->buffer.buf + p, q - p); + } + else { + assert(s != VOID_VALUE); /* s should have a valid value when r has a valid value */ + assert(q >= p); + n_p->data.reference.var = strndup_e(input->buffer.buf + p, q - p); + if (n_p->data.reference.var[0] == '_') { + print_error( + "%s:" FMT_LU ":" FMT_LU ": Leading underscore in variable name '%s'\n", + input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), n_p->data.reference.var + ); + input->errnum++; + } + { + size_t i; + for (i = 0; i < rule->data.rule.vars.len; i++) { + assert(rule->data.rule.vars.buf[i]->type == NODE_REFERENCE); + if (strcmp(n_p->data.reference.var, rule->data.rule.vars.buf[i]->data.reference.var) == 0) break; + } + if (i == rule->data.rule.vars.len) node_const_array__add(&rule->data.rule.vars, n_p); + n_p->data.reference.index = i; + } + assert(s >= r); + n_p->data.reference.name = strndup_e(input->buffer.buf + r, s - r); + } + file_pos__set(&n_p->data.reference.fpos, input->path, l, m); + } + else if (match_character(input, '(')) { + match_spaces(input); + n_p = parse_expression(input, rule); + if (n_p == NULL) goto EXCEPTION; + if (!match_character(input, ')')) goto EXCEPTION; + match_spaces(input); + } + else if (match_character(input, '<')) { + match_spaces(input); + n_p = create_node(NODE_CAPTURE); + n_p->data.capture.index = rule->data.rule.capts.len; + node_const_array__add(&rule->data.rule.capts, n_p); + n_p->data.capture.expr = parse_expression(input, rule); + if (n_p->data.capture.expr == NULL || !match_character(input, '>')) { + rule->data.rule.capts.len = n_p->data.capture.index; + goto EXCEPTION; + } + match_spaces(input); + } + else if (match_character(input, '$')) { + size_t p; + match_spaces(input); + p = input->bufcur; + if (match_number(input)) { + const size_t q = input->bufcur; + char *s; + match_spaces(input); + n_p = create_node(NODE_EXPAND); + assert(q >= p); + s = strndup_e(input->buffer.buf + p, q - p); + n_p->data.expand.index = string_to_size_t(s); + if (n_p->data.expand.index == VOID_VALUE) { + print_error("%s:" FMT_LU ":" FMT_LU ": Invalid unsigned number '%s'\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), s); + input->errnum++; + } + else if (n_p->data.expand.index == 0) { + print_error("%s:" FMT_LU ":" FMT_LU ": 0 not allowed\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + input->errnum++; + } + else if (s[0] == '0') { + print_error("%s:" FMT_LU ":" FMT_LU ": 0-prefixed number not allowed\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + input->errnum++; + n_p->data.expand.index = 0; + } + free(s); + if (n_p->data.expand.index > 0 && n_p->data.expand.index != VOID_VALUE) { + n_p->data.expand.index--; + file_pos__set(&n_p->data.expand.fpos, input->path, l, m); + } + } + else { + goto EXCEPTION; + } + } + else if (match_character(input, '^')) { + match_spaces(input); + n_p = create_node(NODE_POSITION); + n_p->data.position.value = 0; + } + else if (match_character(input, '.')) { + match_spaces(input); + n_p = create_node(NODE_CHARCLASS); + n_p->data.charclass.value = NULL; + if (!input->ascii) { + input->flags |= CODE_FLAG__UTF8_CHARCLASS_USED; + } + } + else if (match_character_class(input)) { + const size_t q = input->bufcur; + match_spaces(input); + n_p = create_node(NODE_CHARCLASS); + n_p->data.charclass.value = strndup_e(input->buffer.buf + p + 1, q - p - 2); + if (!unescape_string(n_p->data.charclass.value, TRUE)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Illegal escape sequence\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + input->errnum++; + } + if (!input->ascii && !is_valid_utf8_string(n_p->data.charclass.value)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Invalid UTF-8 string\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + input->errnum++; + } + if (!input->ascii && n_p->data.charclass.value[0] != '\0') { + input->flags |= CODE_FLAG__UTF8_CHARCLASS_USED; + } + } + else if (match_quotation_single(input) || match_quotation_double(input)) { + const size_t q = input->bufcur; + match_spaces(input); + n_p = create_node(NODE_STRING); + n_p->data.string.value = strndup_e(input->buffer.buf + p + 1, q - p - 2); + if (!unescape_string(n_p->data.string.value, FALSE)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Illegal escape sequence\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + input->errnum++; + } + if (!input->ascii && !is_valid_utf8_string(n_p->data.string.value)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Invalid UTF-8 string\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + input->errnum++; + } + } + else if (match_code_block(input)) { + const size_t q = input->bufcur; + match_spaces(input); + n_p = create_node(NODE_ACTION); + n_p->data.action.code.text = strndup_e(input->buffer.buf + p + 1, q - p - 2); + n_p->data.action.code.len = find_trailing_blanks(n_p->data.action.code.text); + file_pos__set(&n_p->data.action.code.fpos, input->path, l, m); + n_p->data.action.index = rule->data.rule.codes.len; + node_const_array__add(&rule->data.rule.codes, n_p); + } + else { + goto EXCEPTION; + } + return n_p; + +EXCEPTION:; + destroy_node(n_p); + input->bufcur = p; + input->linenum = l; + input->charnum = n; + input->linepos = o; + return NULL; +} + +static node_t *parse_term(input_state_t *input, node_t *rule) { + const size_t p = input->bufcur; + const size_t l = input->linenum; + const size_t n = input->charnum; + const size_t o = input->linepos; + node_t *n_p = NULL; + node_t *n_q = NULL; + node_t *n_r = NULL; + node_t *n_t = NULL; + const char t = match_character(input, '&') ? '&' : match_character(input, '!') ? '!' : '\0'; + if (t) match_spaces(input); + n_p = parse_primary(input, rule); + if (n_p == NULL) goto EXCEPTION; + if (match_character(input, '*')) { + match_spaces(input); + n_q = create_node(NODE_QUANTITY); + n_q->data.quantity.min = 0; + n_q->data.quantity.max = -1; + n_q->data.quantity.expr = n_p; + } + else if (match_character(input, '+')) { + match_spaces(input); + n_q = create_node(NODE_QUANTITY); + n_q->data.quantity.min = 1; + n_q->data.quantity.max = -1; + n_q->data.quantity.expr = n_p; + } + else if (match_character(input, '?')) { + match_spaces(input); + n_q = create_node(NODE_QUANTITY); + n_q->data.quantity.min = 0; + n_q->data.quantity.max = 1; + n_q->data.quantity.expr = n_p; + } + else { + n_q = n_p; + } + switch (t) { + case '&': + n_r = create_node(NODE_PREDICATE); + n_r->data.predicate.neg = FALSE; + n_r->data.predicate.expr = n_q; + break; + case '!': + n_r = create_node(NODE_PREDICATE); + n_r->data.predicate.neg = TRUE; + n_r->data.predicate.expr = n_q; + break; + default: + n_r = n_q; + } + if (match_character(input, '~')) { + size_t p, l, m; + match_spaces(input); + p = input->bufcur; + l = input->linenum; + m = column_number(input); + if (match_code_block(input)) { + const size_t q = input->bufcur; + match_spaces(input); + n_t = create_node(NODE_ERROR); + n_t->data.error.expr = n_r; + n_t->data.error.code.text = strndup_e(input->buffer.buf + p + 1, q - p - 2); + n_t->data.error.code.len = find_trailing_blanks(n_t->data.error.code.text); + file_pos__set(&n_t->data.error.code.fpos, input->path, l, m); + n_t->data.error.index = rule->data.rule.codes.len; + node_const_array__add(&rule->data.rule.codes, n_t); + } + else { + goto EXCEPTION; + } + } + else { + n_t = n_r; + } + return n_t; + +EXCEPTION:; + destroy_node(n_r); + input->bufcur = p; + input->linenum = l; + input->charnum = n; + input->linepos = o; + return NULL; +} + +static node_t *parse_sequence(input_state_t *input, node_t *rule) { + const size_t p = input->bufcur; + const size_t l = input->linenum; + const size_t n = input->charnum; + const size_t o = input->linepos; + node_array_t *a_t = NULL; + node_t *n_t = NULL; + node_t *n_u = NULL; + node_t *n_s = NULL; + n_t = parse_term(input, rule); + if (n_t == NULL) goto EXCEPTION; + n_u = parse_term(input, rule); + if (n_u != NULL) { + n_s = create_node(NODE_SEQUENCE); + a_t = &n_s->data.sequence.nodes; + node_array__add(a_t, n_t); + node_array__add(a_t, n_u); + while ((n_t = parse_term(input, rule)) != NULL) { + node_array__add(a_t, n_t); + } + } + else { + n_s = n_t; + } + return n_s; + +EXCEPTION:; + input->bufcur = p; + input->linenum = l; + input->charnum = n; + input->linepos = o; + return NULL; +} + +static node_t *parse_expression(input_state_t *input, node_t *rule) { + const size_t p = input->bufcur; + const size_t l = input->linenum; + const size_t n = input->charnum; + const size_t o = input->linepos; + size_t q; + node_array_t *a_s = NULL; + node_t *n_s = NULL; + node_t *n_e = NULL; + n_s = parse_sequence(input, rule); + if (n_s == NULL) goto EXCEPTION; + q = input->bufcur; + if (match_character(input, '/')) { + input->bufcur = q; + n_e = create_node(NODE_ALTERNATE); + a_s = &n_e->data.alternate.nodes; + node_array__add(a_s, n_s); + while (match_character(input, '/')) { + match_spaces(input); + n_s = parse_sequence(input, rule); + if (n_s == NULL) goto EXCEPTION; + node_array__add(a_s, n_s); + } + } + else { + n_e = n_s; + } + return n_e; + +EXCEPTION:; + destroy_node(n_e); + input->bufcur = p; + input->linenum = l; + input->charnum = n; + input->linepos = o; + return NULL; +} + +static node_t *parse_rule(input_state_t *input) { + const size_t p = input->bufcur; + const size_t l = input->linenum; + const size_t m = column_number(input); + const size_t n = input->charnum; + const size_t o = input->linepos; + size_t q; + node_t *n_r = NULL; + if (!match_identifier(input)) goto EXCEPTION; + q = input->bufcur; + match_spaces(input); + if (!match_string(input, "<-")) goto EXCEPTION; + match_spaces(input); + n_r = create_node(NODE_RULE); + n_r->data.rule.expr = parse_expression(input, n_r); + if (n_r->data.rule.expr == NULL) goto EXCEPTION; + assert(q >= p); + n_r->data.rule.name = strndup_e(input->buffer.buf + p, q - p); + file_pos__set(&n_r->data.rule.fpos, input->path, l, m); + return n_r; + +EXCEPTION:; + destroy_node(n_r); + input->bufcur = p; + input->linenum = l; + input->charnum = n; + input->linepos = o; + return NULL; +} + +static const char *get_value_type(context_t *ctx) { + return (ctx->vtype && ctx->vtype[0]) ? ctx->vtype : "int"; +} + +static const char *get_auxil_type(context_t *ctx) { + return (ctx->atype && ctx->atype[0]) ? ctx->atype : "void *"; +} + +static const char *get_prefix(context_t *ctx) { + return (ctx->prefix && ctx->prefix[0]) ? ctx->prefix : "pcc"; +} + +static void dump_options(context_t *ctx) { + fprintf(stdout, "value_type: '%s'\n", get_value_type(ctx)); + fprintf(stdout, "auxil_type: '%s'\n", get_auxil_type(ctx)); + fprintf(stdout, "prefix: '%s'\n", get_prefix(ctx)); +} + +static bool_t parse_directive_block_(input_state_t *input, const char *name, code_block_array_t *output1, code_block_array_t *output2) { + if (!match_string(input, name)) return FALSE; + match_spaces(input); + { + const size_t p = input->bufcur; + const size_t l = input->linenum; + const size_t m = column_number(input); + if (match_code_block(input)) { + const size_t q = input->bufcur; + match_spaces(input); + if (output1 != NULL) { + code_block_t *const c = code_block_array__create_entry(output1); + c->text = strndup_e(input->buffer.buf + p + 1, q - p - 2); + c->len = q - p - 2; + file_pos__set(&c->fpos, input->path, l, m); + } + if (output2 != NULL) { + code_block_t *const c = code_block_array__create_entry(output2); + c->text = strndup_e(input->buffer.buf + p + 1, q - p - 2); + c->len = q - p - 2; + file_pos__set(&c->fpos, input->path, l, m); + } + } + else { + print_error("%s:" FMT_LU ":" FMT_LU ": Illegal %s syntax\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), name); + input->errnum++; + } + } + return TRUE; +} + +static bool_t parse_directive_string_(input_state_t *input, const char *name, char **output, string_flag_t mode) { + const size_t l = input->linenum; + const size_t m = column_number(input); + if (!match_string(input, name)) return FALSE; + match_spaces(input); + { + char *s = NULL; + const size_t p = input->bufcur; + const size_t lv = input->linenum; + const size_t mv = column_number(input); + size_t q; + if (match_quotation_single(input) || match_quotation_double(input)) { + q = input->bufcur; + match_spaces(input); + s = strndup_e(input->buffer.buf + p + 1, q - p - 2); + if (!unescape_string(s, FALSE)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Illegal escape sequence\n", input->path, (ulong_t)(lv + 1), (ulong_t)(mv + 1)); + input->errnum++; + } + } + else { + print_error("%s:" FMT_LU ":" FMT_LU ": Illegal %s syntax\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), name); + input->errnum++; + } + if (s != NULL) { + string_flag_t f = STRING_FLAG__NONE; + bool_t b = TRUE; + remove_leading_blanks(s); + remove_trailing_blanks(s); + assert((mode & ~7) == 0); + if ((mode & STRING_FLAG__NOTEMPTY) && !is_filled_string(s)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Empty string\n", input->path, (ulong_t)(lv + 1), (ulong_t)(mv + 1)); + input->errnum++; + f |= STRING_FLAG__NOTEMPTY; + } + if ((mode & STRING_FLAG__NOTVOID) && strcmp(s, "void") == 0) { + print_error("%s:" FMT_LU ":" FMT_LU ": 'void' not allowed\n", input->path, (ulong_t)(lv + 1), (ulong_t)(mv + 1)); + input->errnum++; + f |= STRING_FLAG__NOTVOID; + } + if ((mode & STRING_FLAG__IDENTIFIER) && !is_identifier_string(s)) { + if (!(f & STRING_FLAG__NOTEMPTY)) { + print_error("%s:" FMT_LU ":" FMT_LU ": Invalid identifier\n", input->path, (ulong_t)(lv + 1), (ulong_t)(mv + 1)); + input->errnum++; + } + f |= STRING_FLAG__IDENTIFIER; + } + if (output == NULL) { + print_error("%s:" FMT_LU ":" FMT_LU ": Definition of %s not allowed\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), name); + input->errnum++; + b = FALSE; + } + else if (*output != NULL) { + print_error("%s:" FMT_LU ":" FMT_LU ": Multiple definitions of %s\n", input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), name); + input->errnum++; + b = FALSE; + } + if (f == STRING_FLAG__NONE && b) { + assert(output != NULL); + *output = s; + } + else { + free(s); s = NULL; + } + } + } + return TRUE; +} + +static bool_t parse_footer_(input_state_t *input, code_block_array_t *output) { + if (!match_footer_start(input)) return FALSE; + { + const size_t p = input->bufcur; + const size_t l = input->linenum; + const size_t m = column_number(input); + while (!match_eof(input)) match_character_any(input); + { + const size_t q = input->bufcur; + code_block_t *const c = code_block_array__create_entry(output); + c->text = strndup_e(input->buffer.buf + p, q - p); + c->len = q - p; + file_pos__set(&c->fpos, input->path, l, m); + } + } + return TRUE; +} + +static void parse_file_(context_t *ctx) { + if (ctx->input == NULL) return; + { + file_id_t id; + file_id__get(ctx->input->file, ctx->input->path, &id); + if (!file_id_array__add_if_not_yet(&ctx->done, &id)) return; /* already imported */ + } + { + const bool_t imp = is_in_imported_input(ctx->input); + bool_t b = TRUE; + match_spaces(ctx->input); + for (;;) { + char *s = NULL; + size_t l, m, n, o; + if (match_eof(ctx->input) || parse_footer_(ctx->input, &ctx->fsource)) break; + l = ctx->input->linenum; + m = column_number(ctx->input); + n = ctx->input->charnum; + o = ctx->input->linepos; + if (parse_directive_string_(ctx->input, "%import", &s, STRING_FLAG__NOTEMPTY)) { + if (s) { + if (is_absolute_path(s)) { + FILE *const file = fopen(s, "rb"); + if (file) { + ctx->input = create_input_state(s, file, ctx->input, &ctx->opts); + parse_file_(ctx); + ctx->input = destroy_input_state(ctx->input); + } + else { + if (errno != ENOENT) { + print_error( + "%s:" FMT_LU ":" FMT_LU ": Cannot open file to read: %s\n", + ctx->input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), + s + ); + } + else { + print_error( + "%s:" FMT_LU ":" FMT_LU ": File not found: %s\n", + ctx->input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), + s + ); + } + ctx->input->errnum++; + } + } + else { + size_t i = 0; + char *path = replace_filename(ctx->input->path, s); + FILE *file = fopen(path, "rb"); + while (file == NULL) { + if (errno != ENOENT) { + print_error( + "%s:" FMT_LU ":" FMT_LU ": Cannot open file to read: %s\n", + ctx->input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), + path + ); + ctx->input->errnum++; + break; + } + if (i >= ctx->dirs->len) { + print_error( + "%s:" FMT_LU ":" FMT_LU ": File not found: %s\n", + ctx->input->path, (ulong_t)(l + 1), (ulong_t)(m + 1), + s + ); + ctx->input->errnum++; + break; + } + free(path); + path = add_filename(ctx->dirs->buf[i++], s); + file = fopen(path, "rb"); + } + if (file) { + ctx->input = create_input_state(path, file, ctx->input, &ctx->opts); + parse_file_(ctx); + ctx->input = destroy_input_state(ctx->input); + } + free(path); + } + free(s); + } + b = TRUE; + } + else if ( + parse_directive_block_(ctx->input, "%earlysource", &ctx->esource, NULL) || + parse_directive_block_(ctx->input, "%earlyheader", &ctx->eheader, NULL) || + parse_directive_block_(ctx->input, "%earlycommon", &ctx->esource, &ctx->eheader) || + parse_directive_block_(ctx->input, "%source", &ctx->source, NULL) || + parse_directive_block_(ctx->input, "%header", &ctx->header, NULL) || + parse_directive_block_(ctx->input, "%common", &ctx->source, &ctx->header) || + parse_directive_string_(ctx->input, "%value", imp ? NULL : &ctx->vtype, STRING_FLAG__NOTEMPTY | STRING_FLAG__NOTVOID) || + parse_directive_string_(ctx->input, "%auxil", imp ? NULL : &ctx->atype, STRING_FLAG__NOTEMPTY | STRING_FLAG__NOTVOID) || + parse_directive_string_(ctx->input, "%prefix", imp ? NULL : &ctx->prefix, STRING_FLAG__NOTEMPTY | STRING_FLAG__IDENTIFIER) + ) { + b = TRUE; + } + else if (match_character(ctx->input, '%')) { + print_error("%s:" FMT_LU ":" FMT_LU ": Invalid directive\n", ctx->input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + ctx->input->errnum++; + match_identifier(ctx->input); + match_spaces(ctx->input); + b = TRUE; + } + else { + node_t *const n_r = parse_rule(ctx->input); + if (n_r == NULL) { + if (b) { + print_error("%s:" FMT_LU ":" FMT_LU ": Illegal rule syntax\n", ctx->input->path, (ulong_t)(l + 1), (ulong_t)(m + 1)); + ctx->input->errnum++; + b = FALSE; + } + ctx->input->linenum = l; + ctx->input->charnum = n; + ctx->input->linepos = o; + if (!match_identifier(ctx->input) && !match_spaces(ctx->input)) match_character_any(ctx->input); + continue; + } + node_array__add(&ctx->rules, n_r); + b = TRUE; + } + commit_buffer(ctx->input); + } + commit_buffer(ctx->input); + } + ctx->errnum += ctx->input->errnum; + ctx->flags |= ctx->input->flags; +} + +static bool_t parse(context_t *ctx) { + parse_file_(ctx); + make_rulehash(ctx); + { + size_t i; + for (i = 0; i < ctx->rules.len; i++) { + node_rule_t *const rule = &ctx->rules.buf[i]->data.rule; + if (rule->ref < 0) { + print_error( + "%s:" FMT_LU ":" FMT_LU ": Multiple definitions of rule: '%s'\n", + rule->fpos.path, (ulong_t)(rule->fpos.line + 1), (ulong_t)(rule->fpos.col + 1), + rule->name + ); + ctx->errnum++; + continue; + } + link_references(ctx, rule->expr); + } + } + if (ctx->rules.len > 0) + mark_rules_if_used(ctx, ctx->rules.buf[0]); + { + size_t i; + for (i = 0; i < ctx->rules.len; i++) { + if (!ctx->rules.buf[i]->data.rule.used) + unreference_rules_from_unused_rule(ctx, ctx->rules.buf[i]); + } + } + { + size_t i, j; + for (i = 0, j = 0; i < ctx->rules.len; i++) { + if (!ctx->rules.buf[i]->data.rule.used) + destroy_node(ctx->rules.buf[i]); + else + ctx->rules.buf[j++] = ctx->rules.buf[i]; + } + ctx->rules.len = j; + } + { + size_t i; + for (i = 0; i < ctx->rules.len; i++) { + const node_rule_t *const rule = &ctx->rules.buf[i]->data.rule; + verify_variables(ctx, rule->expr, NULL); + verify_captures(ctx, rule->expr, NULL); + } + } + if (ctx->opts.debug) { + size_t i; + for (i = 0; i < ctx->rules.len; i++) { + dump_node(ctx, ctx->rules.buf[i], 0); + } + dump_options(ctx); + } + return (ctx->errnum == 0) ? TRUE : FALSE; +} + +static code_reach_t generate_matching_string_code(generate_t *gen, const char *value, int onfail, size_t indent, bool_t bare) { + const size_t n = (value != NULL) ? strlen(value) : 0; + if (n > 0) { + char s[5]; + if (n > 1) { + size_t i; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "if (\n"); + for (i = 0; i < n; i++) { + stream__write_characters(gen->stream, ' ', indent + 4); + stream__printf( + gen->stream, + "pcc_refill_buffer(ctx, " FMT_LU ") < " FMT_LU " || (ctx->buffer.buf + ctx->cur)[" FMT_LU "] != '%s'%s\n", + (ulong_t)i + 1, (ulong_t)i + 1, (ulong_t)i, escape_character(value[i], &s), (i < n - 1) ? " ||" : "" + ); + } + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, ") goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "ctx->cur += " FMT_LU ";\n", (ulong_t)n); + return CODE_REACH__BOTH; + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "if (\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "pcc_refill_buffer(ctx, 1) < 1 ||\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__printf(gen->stream, "ctx->buffer.buf[ctx->cur] != '%s'\n", escape_character(value[0], &s)); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, ") goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur++;\n"); + return CODE_REACH__BOTH; + } + } + else { + /* no code to generate */ + return CODE_REACH__ALWAYS_SUCCEED; + } +} + +static code_reach_t generate_matching_charclass_code(generate_t *gen, const char *value, int onfail, size_t indent, bool_t bare) { + assert(gen->ascii); + if (value != NULL) { + const size_t n = strlen(value); + if (n > 0) { + char s[5], t[5]; + if (n > 1) { + const bool_t a = (value[0] == '^') ? TRUE : FALSE; + size_t i = a ? 1 : 0; + if (i + 1 == n) { /* fulfilled only if a == TRUE */ + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "if (\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "pcc_refill_buffer(ctx, 1) < 1 ||\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__printf(gen->stream, "ctx->buffer.buf[ctx->cur] == '%s'\n", escape_character(value[i], &s)); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, ") goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur++;\n"); + return CODE_REACH__BOTH; + } + else { + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "char c;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "if (pcc_refill_buffer(ctx, 1) < 1) goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "c = ctx->buffer.buf[ctx->cur];\n"); + if (i + 3 == n && value[i] != '\\' && value[i + 1] == '-') { + stream__write_characters(gen->stream, ' ', indent); + stream__printf( + gen->stream, + a ? "if (c >= '%s' && c <= '%s') goto L%04d;\n" + : "if (!(c >= '%s' && c <= '%s')) goto L%04d;\n", + escape_character(value[i], &s), escape_character(value[i + 2], &t), onfail + ); + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, a ? "if (\n" : "if (!(\n"); + for (; i < n; i++) { + stream__write_characters(gen->stream, ' ', indent + 4); + if (value[i] == '\\' && i + 1 < n) i++; + if (i + 2 < n && value[i + 1] == '-') { + stream__printf( + gen->stream, "(c >= '%s' && c <= '%s')%s\n", + escape_character(value[i], &s), escape_character(value[i + 2], &t), (i + 3 == n) ? "" : " ||" + ); + i += 2; + } + else { + stream__printf( + gen->stream, "c == '%s'%s\n", + escape_character(value[i], &s), (i + 1 == n) ? "" : " ||" + ); + } + } + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, a ? ") goto L%04d;\n" : ")) goto L%04d;\n", onfail); + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur++;\n"); + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return CODE_REACH__BOTH; + } + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "if (\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "pcc_refill_buffer(ctx, 1) < 1 ||\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__printf(gen->stream, "ctx->buffer.buf[ctx->cur] != '%s'\n", escape_character(value[0], &s)); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, ") goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur++;\n"); + return CODE_REACH__BOTH; + } + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", onfail); + return CODE_REACH__ALWAYS_FAIL; + } + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "if (pcc_refill_buffer(ctx, 1) < 1) goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur++;\n"); + return CODE_REACH__BOTH; + } +} + +static code_reach_t generate_matching_utf8_charclass_code(generate_t *gen, const char *value, int onfail, size_t indent, bool_t bare) { + const size_t n = (value != NULL) ? strlen(value) : 0; + if (value == NULL || n > 0) { + const bool_t a = (n > 0 && value[0] == '^') ? TRUE : FALSE; + size_t i = a ? 1 : 0; + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "int u;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t n = pcc_get_char_as_utf32(ctx, &u);\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "if (n == 0) goto L%04d;\n", onfail); + if (value != NULL && !(a && n == 1)) { /* not '.' or '[^]' */ + int u0 = 0; + bool_t r = FALSE; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, a ? "if (\n" : "if (!(\n"); + while (i < n) { + int u = 0; + if (value[i] == '\\' && i + 1 < n) i++; + i += utf8_to_utf32(value + i, &u); + if (r) { /* character range */ + stream__write_characters(gen->stream, ' ', indent + 4); + stream__printf(gen->stream, "(u >= 0x%06x && u <= 0x%06x)%s\n", u0, u, (i < n) ? " ||" : ""); + u0 = 0; + r = FALSE; + } + else if ( + value[i] != '-' || + i == n - 1 /* the individual '-' character is valid when it is at the first or the last position */ + ) { /* single character */ + stream__write_characters(gen->stream, ' ', indent + 4); + stream__printf(gen->stream, "u == 0x%06x%s\n", u, (i < n) ? " ||" : ""); + u0 = 0; + r = FALSE; + } + else { + assert(value[i] == '-'); + i++; + u0 = u; + r = TRUE; + } + } + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, a ? ") goto L%04d;\n" : ")) goto L%04d;\n", onfail); + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur += n;\n"); + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return CODE_REACH__BOTH; + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", onfail); + return CODE_REACH__ALWAYS_FAIL; + } +} + +static code_reach_t generate_position_code(generate_t *gen, size_t value, int onfail, size_t indent, bool_t bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "if (ctx->pos + ctx->cur != " FMT_LU ") goto L%04d;\n", value, onfail); + return CODE_REACH__BOTH; +} + +static code_reach_t generate_code(generate_t *gen, const node_t *node, int onfail, size_t indent, bool_t bare); + +static code_reach_t generate_quantifying_code(generate_t *gen, const node_t *expr, int min, int max, int onfail, size_t indent, bool_t bare) { + if (max > 1 || max < 0) { + code_reach_t r; + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + if (min > 0) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t p0 = ctx->cur;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t n0 = chunk->thunks.len;\n"); + } + if (max < 0) { + if (min > 0) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "int i;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "for (i = 0;; i++) {\n"); + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "for (;;) {\n"); + } + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "int i;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "for (i = 0; i < %d; i++) {\n", max); + } + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "const size_t p = ctx->cur;\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "const size_t n = chunk->thunks.len;\n"); + { + const int l = ++gen->label; + r = generate_code(gen, expr, l, indent + 4, FALSE); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "if (ctx->cur == p) break;\n"); + if (r != CODE_REACH__ALWAYS_SUCCEED) { + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "continue;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "L%04d:;\n", l); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "ctx->cur = p;\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "pcc_thunk_array__revert(ctx, &chunk->thunks, n);\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "break;\n"); + } + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + if (min > 0) { + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "if (i < %d) {\n", min); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "ctx->cur = p0;\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "pcc_thunk_array__revert(ctx, &chunk->thunks, n0);\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__printf(gen->stream, "goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return (min > 0) ? ((r == CODE_REACH__ALWAYS_FAIL) ? CODE_REACH__ALWAYS_FAIL : CODE_REACH__BOTH) : CODE_REACH__ALWAYS_SUCCEED; + } + else if (max == 1) { + if (min > 0) { + return generate_code(gen, expr, onfail, indent, bare); + } + else { + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "MARK_VAR_AS_USED\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t p = ctx->cur;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "MARK_VAR_AS_USED\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t n = chunk->thunks.len;\n"); + { + const int l = ++gen->label; + if (generate_code(gen, expr, l, indent, FALSE) != CODE_REACH__ALWAYS_SUCCEED) { + const int m = ++gen->label; + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", m); + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", l); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur = p;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "pcc_thunk_array__revert(ctx, &chunk->thunks, n);\n"); + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", m); + } + } + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return CODE_REACH__ALWAYS_SUCCEED; + } + } + else { + /* no code to generate */ + return CODE_REACH__ALWAYS_SUCCEED; + } +} + +static code_reach_t generate_predicating_code(generate_t *gen, const node_t *expr, bool_t neg, int onfail, size_t indent, bool_t bare) { + code_reach_t r; + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t p = ctx->cur;\n"); + if (neg) { + const int l = ++gen->label; + r = generate_code(gen, expr, l, indent, FALSE); + if (r != CODE_REACH__ALWAYS_FAIL) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur = p;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", onfail); + } + if (r != CODE_REACH__ALWAYS_SUCCEED) { + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", l); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur = p;\n"); + } + switch (r) { + case CODE_REACH__ALWAYS_SUCCEED: r = CODE_REACH__ALWAYS_FAIL; break; + case CODE_REACH__ALWAYS_FAIL: r = CODE_REACH__ALWAYS_SUCCEED; break; + case CODE_REACH__BOTH: break; + } + } + else { + const int l = ++gen->label; + const int m = ++gen->label; + r = generate_code(gen, expr, l, indent, FALSE); + if (r != CODE_REACH__ALWAYS_FAIL) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur = p;\n"); + } + if (r == CODE_REACH__BOTH) { + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", m); + } + if (r != CODE_REACH__ALWAYS_SUCCEED) { + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", l); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur = p;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", onfail); + } + if (r == CODE_REACH__BOTH) { + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", m); + } + } + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return r; +} + +static code_reach_t generate_sequential_code(generate_t *gen, const node_array_t *nodes, int onfail, size_t indent, bool_t bare) { + bool_t b = FALSE; + size_t i; + for (i = 0; i < nodes->len; i++) { + switch (generate_code(gen, nodes->buf[i], onfail, indent, FALSE)) { + case CODE_REACH__ALWAYS_FAIL: + if (i + 1 < nodes->len) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "/* unreachable codes omitted */\n"); + } + return CODE_REACH__ALWAYS_FAIL; + case CODE_REACH__ALWAYS_SUCCEED: + break; + default: + b = TRUE; + } + } + return b ? CODE_REACH__BOTH : CODE_REACH__ALWAYS_SUCCEED; +} + +static code_reach_t generate_alternative_code(generate_t *gen, const node_array_t *nodes, int onfail, size_t indent, bool_t bare) { + bool_t b = FALSE; + int m = ++gen->label; + size_t i; + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "MARK_VAR_AS_USED\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t p = ctx->cur;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "MARK_VAR_AS_USED\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t n = chunk->thunks.len;\n"); + for (i = 0; i < nodes->len; i++) { + const bool_t c = (i + 1 < nodes->len) ? TRUE : FALSE; + const int l = ++gen->label; + switch (generate_code(gen, nodes->buf[i], l, indent, FALSE)) { + case CODE_REACH__ALWAYS_SUCCEED: + if (c) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "/* unreachable codes omitted */\n"); + } + if (b) { + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", m); + } + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return CODE_REACH__ALWAYS_SUCCEED; + case CODE_REACH__ALWAYS_FAIL: + break; + default: + b = TRUE; + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", m); + } + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", l); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "ctx->cur = p;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "pcc_thunk_array__revert(ctx, &chunk->thunks, n);\n"); + if (!c) { + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", onfail); + } + } + if (b) { + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", m); + } + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return b ? CODE_REACH__BOTH : CODE_REACH__ALWAYS_FAIL; +} + +static code_reach_t generate_capturing_code(generate_t *gen, const node_t *expr, size_t index, int onfail, size_t indent, bool_t bare) { + code_reach_t r; + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "const size_t p = ctx->cur;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "size_t q;\n"); + r = generate_code(gen, expr, onfail, indent, FALSE); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "q = ctx->cur;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "chunk->capts.buf[" FMT_LU "].range.start = p;\n", (ulong_t)index); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "chunk->capts.buf[" FMT_LU "].range.end = q;\n", (ulong_t)index); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "pcc_char_array__resize(ctx->auxil, &chunk->capts.buf[" FMT_LU "].string, 0);\n", (ulong_t)index); + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return r; +} + +static code_reach_t generate_expanding_code(generate_t *gen, size_t index, int onfail, size_t indent, bool_t bare) { + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + stream__write_characters(gen->stream, ' ', indent); + stream__printf( + gen->stream, "const size_t n = chunk->capts.buf[" FMT_LU "].range.end - chunk->capts.buf[" FMT_LU "].range.start;\n", + (ulong_t)index, (ulong_t)index + ); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "if (pcc_refill_buffer(ctx, n) < n) goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "if (n > 0) {\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "const char *const p = ctx->buffer.buf + ctx->cur;\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__printf(gen->stream, "const char *const q = ctx->buffer.buf + chunk->capts.buf[" FMT_LU "].range.start;\n", (ulong_t)index); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "size_t i;\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "for (i = 0; i < n; i++) {\n"); + stream__write_characters(gen->stream, ' ', indent + 8); + stream__printf(gen->stream, "if (p[i] != q[i]) goto L%04d;\n", onfail); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "}\n"); + stream__write_characters(gen->stream, ' ', indent + 4); + stream__puts(gen->stream, "ctx->cur += n;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return CODE_REACH__BOTH; +} + +static code_reach_t generate_thunking_action_code( + generate_t *gen, size_t index, const node_const_array_t *vars, const node_const_array_t *capts, bool_t error, int onfail, size_t indent, bool_t bare +) { + assert(gen->rule->type == NODE_RULE); + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + if (error) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "pcc_value_t null;\n"); + } + stream__write_characters(gen->stream, ' ', indent); + stream__printf( + gen->stream, "pcc_thunk_t *const thunk = pcc_thunk__create_leaf(ctx, pcc_action_%s_" FMT_LU ", " FMT_LU ", " FMT_LU ");\n", + gen->rule->data.rule.name, (ulong_t)index, (ulong_t)gen->rule->data.rule.vars.len, (ulong_t)gen->rule->data.rule.capts.len + ); + { + size_t i; + for (i = 0; i < vars->len; i++) { + assert(vars->buf[i]->type == NODE_REFERENCE); + stream__write_characters(gen->stream, ' ', indent); + stream__printf( + gen->stream, "thunk->data.leaf.values.buf[" FMT_LU "] = &(chunk->values.buf[" FMT_LU "]);\n", + (ulong_t)vars->buf[i]->data.reference.index, (ulong_t)vars->buf[i]->data.reference.index + ); + } + for (i = 0; i < capts->len; i++) { + assert(capts->buf[i]->type == NODE_CAPTURE); + stream__write_characters(gen->stream, ' ', indent); + stream__printf( + gen->stream, "thunk->data.leaf.capts.buf[" FMT_LU "] = &(chunk->capts.buf[" FMT_LU "]);\n", + (ulong_t)capts->buf[i]->data.capture.index, (ulong_t)capts->buf[i]->data.capture.index + ); + } + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "thunk->data.leaf.capt0.range.start = chunk->pos;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "thunk->data.leaf.capt0.range.end = ctx->cur;\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "pcc_char_array__resize(ctx->auxil, &thunk->data.leaf.capt0.string, 0);\n"); + } + if (error) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "memset(&null, 0, sizeof(pcc_value_t)); /* in case */\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "thunk->data.leaf.action(ctx, thunk, &null);\n"); + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "pcc_thunk__destroy(ctx, thunk);\n"); + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "pcc_thunk_array__add(ctx, &chunk->thunks, thunk);\n"); + } + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return CODE_REACH__ALWAYS_SUCCEED; +} + +static code_reach_t generate_thunking_error_code( + generate_t *gen, const node_t *expr, size_t index, const node_const_array_t *vars, const node_const_array_t *capts, int onfail, size_t indent, bool_t bare +) { + code_reach_t r; + const int l = ++gen->label; + const int m = ++gen->label; + assert(gen->rule->type == NODE_RULE); + if (!bare) { + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "{\n"); + indent += 4; + } + r = generate_code(gen, expr, l, indent, TRUE); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", m); + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", l); + generate_thunking_action_code(gen, index, vars, capts, TRUE, l, indent, FALSE); + stream__write_characters(gen->stream, ' ', indent); + stream__printf(gen->stream, "goto L%04d;\n", onfail); + if (indent > 4) stream__write_characters(gen->stream, ' ', indent - 4); + stream__printf(gen->stream, "L%04d:;\n", m); + if (!bare) { + indent -= 4; + stream__write_characters(gen->stream, ' ', indent); + stream__puts(gen->stream, "}\n"); + } + return r; +} + +static code_reach_t generate_code(generate_t *gen, const node_t *node, int onfail, size_t indent, bool_t bare) { + if (node == NULL) { + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } + switch (node->type) { + case NODE_RULE: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + case NODE_REFERENCE: + if (node->data.reference.index != VOID_VALUE) { + stream__write_characters(gen->stream, ' ', indent); + stream__printf( + gen->stream, "if (!pcc_apply_rule(ctx, pcc_evaluate_rule_%s, &chunk->thunks, &(chunk->values.buf[" FMT_LU "]))) goto L%04d;\n", + node->data.reference.name, (ulong_t)node->data.reference.index, onfail + ); + } + else { + stream__write_characters(gen->stream, ' ', indent); + stream__printf( + gen->stream, "if (!pcc_apply_rule(ctx, pcc_evaluate_rule_%s, &chunk->thunks, NULL)) goto L%04d;\n", + node->data.reference.name, onfail + ); + } + return CODE_REACH__BOTH; + case NODE_STRING: + return generate_matching_string_code(gen, node->data.string.value, onfail, indent, bare); + case NODE_CHARCLASS: + return gen->ascii ? + generate_matching_charclass_code(gen, node->data.charclass.value, onfail, indent, bare) : + generate_matching_utf8_charclass_code(gen, node->data.charclass.value, onfail, indent, bare); + case NODE_POSITION: + return generate_position_code(gen, node->data.position.value, onfail, indent, bare); + case NODE_QUANTITY: + return generate_quantifying_code(gen, node->data.quantity.expr, node->data.quantity.min, node->data.quantity.max, onfail, indent, bare); + case NODE_PREDICATE: + return generate_predicating_code(gen, node->data.predicate.expr, node->data.predicate.neg, onfail, indent, bare); + case NODE_SEQUENCE: + return generate_sequential_code(gen, &node->data.sequence.nodes, onfail, indent, bare); + case NODE_ALTERNATE: + return generate_alternative_code(gen, &node->data.alternate.nodes, onfail, indent, bare); + case NODE_CAPTURE: + return generate_capturing_code(gen, node->data.capture.expr, node->data.capture.index, onfail, indent, bare); + case NODE_EXPAND: + return generate_expanding_code(gen, node->data.expand.index, onfail, indent, bare); + case NODE_ACTION: + return generate_thunking_action_code( + gen, node->data.action.index, &node->data.action.vars, &node->data.action.capts, FALSE, onfail, indent, bare + ); + case NODE_ERROR: + return generate_thunking_error_code( + gen, node->data.error.expr, node->data.error.index, &node->data.error.vars, &node->data.error.capts, onfail, indent, bare + ); + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } +} + +static bool_t generate(context_t *ctx) { + const char *const vt = get_value_type(ctx); + const char *const at = get_auxil_type(ctx); + const bool_t vp = is_pointer_type(vt); + const bool_t ap = is_pointer_type(at); + stream_t sstream = stream__wrap(fopen_wt_e(ctx->spath), ctx->spath, ctx->opts.lines ? 0 : VOID_VALUE); + stream_t hstream = stream__wrap(fopen_wt_e(ctx->hpath), ctx->hpath, ctx->opts.lines ? 0 : VOID_VALUE); + stream__printf(&sstream, "/* A packrat parser generated by PackCC %s */\n\n", VERSION); + stream__printf(&hstream, "/* A packrat parser generated by PackCC %s */\n\n", VERSION); + { + subst_map__clear(&ctx->subst); + subst_map__add(&ctx->subst, "prefix", get_prefix(ctx)); + subst_map__add(&ctx->subst, "PREFIX", get_prefix(ctx)); + to_uppercase(ctx->subst.buf[ctx->subst.len - 1].ostr); + } + { + { + size_t i; + for (i = 0; i < ctx->eheader.len; i++) { + stream__write_code_block( + &hstream, ctx->eheader.buf[i].text, ctx->eheader.buf[i].len, 0, + ctx->eheader.buf[i].fpos.path, ctx->eheader.buf[i].fpos.line, FALSE, &ctx->subst + ); + stream__puts(&hstream, "\n"); + } + } + stream__printf( + &hstream, + "#ifndef PCC_INCLUDED_%s\n" + "#define PCC_INCLUDED_%s\n" + "\n", + ctx->hid, ctx->hid + ); + { + size_t i; + for (i = 0; i < ctx->header.len; i++) { + stream__write_code_block( + &hstream, ctx->header.buf[i].text, ctx->header.buf[i].len, 0, + ctx->header.buf[i].fpos.path, ctx->header.buf[i].fpos.line, FALSE, &ctx->subst + ); + stream__puts(&hstream, "\n"); + } + } + } + { + { + size_t i; + for (i = 0; i < ctx->esource.len; i++) { + stream__write_code_block( + &sstream, ctx->esource.buf[i].text, ctx->esource.buf[i].len, 0, + ctx->esource.buf[i].fpos.path, ctx->esource.buf[i].fpos.line, FALSE, &ctx->subst + ); + stream__puts(&sstream, "\n"); + } + } + stream__puts( + &sstream, + "#ifdef _MSC_VER\n" + "#undef _CRT_NONSTDC_NO_WARNINGS\n" + "#undef _CRT_SECURE_NO_WARNINGS\n" + "#define _CRT_NONSTDC_NO_WARNINGS\n" + "#define _CRT_SECURE_NO_WARNINGS\n" + "#endif /* _MSC_VER */\n" + "#include \n" + "#include \n" + "#include \n" + "\n" + ); + stream__printf( + &sstream, + "#include \"%s\"\n" + "\n", + extract_filename(ctx->hpath) + ); + if (ctx->opts.ascii || ctx->opts.lines) { + if (ctx->opts.ascii) { + stream__puts( + &sstream, + "#define PCC_OPTION_ASCII_ENABLED\n" + ); + } + if (ctx->opts.lines) { + stream__puts( + &sstream, + "#define PCC_OPTION_LINES_ENABLED\n" + ); + } + stream__puts( + &sstream, + "\n" + ); + } + { + size_t i; + for (i = 0; i < ctx->source.len; i++) { + stream__write_code_block( + &sstream, ctx->source.buf[i].text, ctx->source.buf[i].len, 0, + ctx->source.buf[i].fpos.path, ctx->source.buf[i].fpos.line, FALSE, &ctx->subst + ); + stream__puts(&sstream, "\n"); + } + } + } + { + stream__puts( + &sstream, + "#if !defined __has_attribute || defined _MSC_VER\n" + "#define __attribute__(x)\n" + "#endif\n" + "\n" + "#ifdef _MSC_VER\n" + "#define MARK_FUNC_AS_USED __pragma(warning(suppress:4505))\n" + "#else\n" + "#define MARK_FUNC_AS_USED __attribute__((__unused__))\n" + "#endif\n" + "\n" + "#ifdef _MSC_VER\n" + "#define MARK_VAR_AS_USED __pragma(warning(suppress:4189))\n" + "#else\n" + "#define MARK_VAR_AS_USED __attribute__((__unused__))\n" + "#endif\n" + "\n" + "#ifndef PCC_BUFFER_MIN_SIZE\n" + "#define PCC_BUFFER_MIN_SIZE 256\n" + "#endif /* !PCC_BUFFER_MIN_SIZE */\n" + "\n" + "#ifndef PCC_ARRAY_MIN_SIZE\n" + "#define PCC_ARRAY_MIN_SIZE 2\n" + "#endif /* !PCC_ARRAY_MIN_SIZE */\n" + "\n" + "#ifndef PCC_POOL_MIN_SIZE\n" + "#define PCC_POOL_MIN_SIZE 65536\n" + "#endif /* !PCC_POOL_MIN_SIZE */\n" + "\n" + "#define PCC_DBG_EVALUATE 0\n" + "#define PCC_DBG_MATCH 1\n" + "#define PCC_DBG_NOMATCH 2\n" + "\n" + "#define PCC_VOID_VALUE (~(size_t)0)\n" + "\n" + "typedef enum pcc_bool_tag {\n" + " PCC_FALSE = 0,\n" + " PCC_TRUE\n" + "} pcc_bool_t;\n" + "\n" + "typedef struct pcc_char_array_tag {\n" + " char *buf;\n" + " size_t max;\n" + " size_t len;\n" + "} pcc_char_array_t;\n" + "\n" + "typedef struct pcc_range_tag {\n" + " size_t start;\n" + " size_t end;\n" + "} pcc_range_t;\n" + "\n" + ); + stream__printf( + &sstream, + "typedef %s%spcc_value_t;\n" + "\n", + vt, vp ? "" : " " + ); + stream__printf( + &sstream, + "typedef %s%spcc_auxil_t;\n" + "\n", + at, ap ? "" : " " + ); + if (strcmp(get_prefix(ctx), "pcc") != 0) { + stream__printf( + &sstream, + "typedef %s_context_t pcc_context_t;\n" + "\n", + get_prefix(ctx) + ); + } + stream__puts( + &sstream, + "typedef struct pcc_value_table_tag {\n" + " pcc_value_t *buf;\n" + " size_t max;\n" + " size_t len;\n" + "} pcc_value_table_t;\n" + "\n" + "typedef struct pcc_value_refer_table_tag {\n" + " pcc_value_t **buf;\n" + " size_t max;\n" + " size_t len;\n" + "} pcc_value_refer_table_t;\n" + "\n" + "typedef struct pcc_capture_tag {\n" + " pcc_range_t range;\n" + " pcc_char_array_t string; /* mutable */\n" + "} pcc_capture_t;\n" + "\n" + "typedef struct pcc_capture_table_tag {\n" + " pcc_capture_t *buf;\n" + " size_t max;\n" + " size_t len;\n" + "} pcc_capture_table_t;\n" + "\n" + "typedef struct pcc_capture_const_table_tag {\n" + " const pcc_capture_t **buf;\n" + " size_t max;\n" + " size_t len;\n" + "} pcc_capture_const_table_t;\n" + "\n" + "typedef struct pcc_thunk_tag pcc_thunk_t;\n" + "typedef struct pcc_thunk_array_tag pcc_thunk_array_t;\n" + "\n" + "typedef void (*pcc_action_t)(pcc_context_t *, pcc_thunk_t *, pcc_value_t *);\n" + "\n" + ); + stream__puts( + &sstream, + "typedef enum pcc_thunk_type_tag {\n" + " PCC_THUNK_LEAF,\n" + " PCC_THUNK_NODE\n" + "} pcc_thunk_type_t;\n" + "\n" + "typedef struct pcc_thunk_leaf_tag {\n" + " pcc_value_refer_table_t values;\n" + " pcc_capture_const_table_t capts;\n" + " pcc_capture_t capt0;\n" + " pcc_action_t action;\n" + "} pcc_thunk_leaf_t;\n" + "\n" + "typedef struct pcc_thunk_node_tag {\n" + " const pcc_thunk_array_t *thunks; /* just a reference */\n" + " pcc_value_t *value; /* just a reference */\n" + "} pcc_thunk_node_t;\n" + "\n" + "typedef union pcc_thunk_data_tag {\n" + " pcc_thunk_leaf_t leaf;\n" + " pcc_thunk_node_t node;\n" + "} pcc_thunk_data_t;\n" + "\n" + "struct pcc_thunk_tag {\n" + " pcc_thunk_type_t type;\n" + " pcc_thunk_data_t data;\n" + "};\n" + "\n" + "struct pcc_thunk_array_tag {\n" + " pcc_thunk_t **buf;\n" + " size_t max;\n" + " size_t len;\n" + "};\n" + "\n" + "typedef struct pcc_thunk_chunk_tag {\n" + " pcc_value_table_t values;\n" + " pcc_capture_table_t capts;\n" + " pcc_thunk_array_t thunks;\n" + " size_t pos; /* the starting position in the character buffer */\n" + "} pcc_thunk_chunk_t;\n" + "\n" + "typedef struct pcc_lr_entry_tag pcc_lr_entry_t;\n" + "\n" + "typedef enum pcc_lr_answer_type_tag {\n" + " PCC_LR_ANSWER_LR,\n" + " PCC_LR_ANSWER_CHUNK\n" + "} pcc_lr_answer_type_t;\n" + "\n" + "typedef union pcc_lr_answer_data_tag {\n" + " pcc_lr_entry_t *lr;\n" + " pcc_thunk_chunk_t *chunk;\n" + "} pcc_lr_answer_data_t;\n" + "\n" + "typedef struct pcc_lr_answer_tag pcc_lr_answer_t;\n" + "\n" + "struct pcc_lr_answer_tag {\n" + " pcc_lr_answer_type_t type;\n" + " pcc_lr_answer_data_t data;\n" + " size_t pos; /* the absolute position in the input */\n" + " pcc_lr_answer_t *hold;\n" + "};\n" + "\n" + ); + stream__puts( + &sstream, + "typedef pcc_thunk_chunk_t *(*pcc_rule_t)(pcc_context_t *);\n" + "\n" + "typedef struct pcc_rule_set_tag {\n" + " pcc_rule_t *buf;\n" + " size_t max;\n" + " size_t len;\n" + "} pcc_rule_set_t;\n" + "\n" + "typedef struct pcc_lr_head_tag pcc_lr_head_t;\n" + "\n" + "struct pcc_lr_head_tag {\n" + " pcc_rule_t rule;\n" + " pcc_rule_set_t invol;\n" + " pcc_rule_set_t eval;\n" + " pcc_lr_head_t *hold;\n" + "};\n" + "\n" + "typedef struct pcc_lr_memo_tag {\n" + " pcc_rule_t rule;\n" + " pcc_lr_answer_t *answer;\n" + " size_t next; /* the index of the next instance with the same hash value */\n" + "} pcc_lr_memo_t;\n" + "\n" + "typedef struct pcc_lr_memo_map_tag {\n" + " pcc_lr_memo_t *buf;\n" + " size_t max;\n" + " size_t len;\n" + "} pcc_lr_memo_map_t;\n" + "\n" + "typedef struct pcc_lr_table_entry_tag {\n" + " pcc_lr_head_t *head; /* just a reference */\n" + " pcc_lr_memo_map_t memos;\n" + " pcc_lr_answer_t *hold_a;\n" + " pcc_lr_head_t *hold_h;\n" + "} pcc_lr_table_entry_t;\n" + "\n" + "typedef struct pcc_lr_table_tag {\n" + " pcc_lr_table_entry_t **buf;\n" + " size_t max;\n" + " size_t len;\n" + " size_t ofs;\n" + "} pcc_lr_table_t;\n" + "\n" + "struct pcc_lr_entry_tag {\n" + " pcc_rule_t rule;\n" + " pcc_thunk_chunk_t *seed; /* just a reference */\n" + " pcc_lr_head_t *head; /* just a reference */\n" + "};\n" + "\n" + "typedef struct pcc_lr_stack_tag {\n" + " pcc_lr_entry_t **buf;\n" + " size_t max;\n" + " size_t len;\n" + "} pcc_lr_stack_t;\n" + "\n" + ); + stream__puts( + &sstream, + "typedef struct pcc_memory_entry_tag pcc_memory_entry_t;\n" + "typedef struct pcc_memory_pool_tag pcc_memory_pool_t;\n" + "\n" + "struct pcc_memory_entry_tag {\n" + " pcc_memory_entry_t *next;\n" + "};\n" + "\n" + "struct pcc_memory_pool_tag {\n" + " pcc_memory_pool_t *next;\n" + " size_t allocated;\n" + " size_t unused;\n" + "};\n" + "\n" + "typedef struct pcc_memory_recycler_tag {\n" + " pcc_memory_pool_t *pool_list;\n" + " pcc_memory_entry_t *entry_list;\n" + " size_t element_size;\n" + "} pcc_memory_recycler_t;\n" + "\n" + ); + stream__printf( + &sstream, + "struct %s_context_tag {\n" + " size_t pos; /* the position in the input of the first character currently buffered */\n" + " size_t cur; /* the current parsing position in the character buffer */\n" + " size_t level;\n" + " pcc_char_array_t buffer;\n" + " pcc_lr_table_t lrtable;\n" + " pcc_lr_stack_t lrstack;\n" + " pcc_thunk_array_t thunks;\n" + " pcc_auxil_t auxil;\n" + " pcc_memory_recycler_t thunk_recycler;\n" + " pcc_memory_recycler_t thunk_chunk_recycler;\n" + " pcc_memory_recycler_t lr_head_recycler;\n" + " pcc_memory_recycler_t lr_answer_recycler;\n" + " pcc_memory_recycler_t lr_table_entry_recycler;\n" + " pcc_memory_recycler_t lr_entry_recycler;\n" + "};\n" + "\n", + get_prefix(ctx) + ); + stream__puts( + &sstream, + "#ifndef PCC_ERROR\n" + "#define PCC_ERROR(auxil) pcc_error()\n" + "MARK_FUNC_AS_USED\n" + "static void pcc_error(void) {\n" + " fprintf(stderr, \"Syntax error\\n\");\n" + " exit(1);\n" + "}\n" + "#endif /* !PCC_ERROR */\n" + "\n" + "#ifndef PCC_GETCHAR\n" + "#define PCC_GETCHAR(auxil) getchar()\n" + "#endif /* !PCC_GETCHAR */\n" + "\n" + "#ifndef PCC_MALLOC\n" + "#define PCC_MALLOC(auxil, size) pcc_malloc_e(size)\n" + "static void *pcc_malloc_e(size_t size) {\n" + " void *const p = malloc(size);\n" + " if (p == NULL) {\n" + " fprintf(stderr, \"Out of memory\\n\");\n" + " exit(1);\n" + " }\n" + " return p;\n" + "}\n" + "#endif /* !PCC_MALLOC */\n" + "\n" + "#ifndef PCC_REALLOC\n" + "#define PCC_REALLOC(auxil, ptr, size) pcc_realloc_e(ptr, size)\n" + "static void *pcc_realloc_e(void *ptr, size_t size) {\n" + " void *const p = realloc(ptr, size);\n" + " if (p == NULL) {\n" + " fprintf(stderr, \"Out of memory\\n\");\n" + " exit(1);\n" + " }\n" + " return p;\n" + "}\n" + "#endif /* !PCC_REALLOC */\n" + "\n" + "#ifndef PCC_FREE\n" + "#define PCC_FREE(auxil, ptr) free(ptr)\n" + "#endif /* !PCC_FREE */\n" + "\n" + "#ifndef PCC_DEBUG\n" + "#define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) ((void)0)\n" + "#endif /* !PCC_DEBUG */\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_char_array__init(pcc_auxil_t auxil, pcc_char_array_t *array) {\n" + " array->len = 0;\n" + " array->max = 0;\n" + " array->buf = NULL;\n" + "}\n" + "\n" + "static void pcc_char_array__resize(pcc_auxil_t auxil, pcc_char_array_t *array, size_t len) {\n" + " if (array->max < len) {\n" + " size_t m = array->max;\n" + " if (m == 0) m = PCC_BUFFER_MIN_SIZE;\n" + " while (m < len && m != 0) m <<= 1;\n" + " if (m == 0) m = len;\n" + " array->buf = (char *)PCC_REALLOC(auxil, array->buf, m);\n" + " array->max = m;\n" + " }\n" + " array->len = len;\n" + "}\n" + "\n" + "static void pcc_char_array__add(pcc_auxil_t auxil, pcc_char_array_t *array, char ch) {\n" + " if (array->max <= array->len) {\n" + " const size_t n = array->len + 1;\n" + " size_t m = array->max;\n" + " if (m == 0) m = PCC_BUFFER_MIN_SIZE;\n" + " while (m < n && m != 0) m <<= 1;\n" + " if (m == 0) m = n;\n" + " array->buf = (char *)PCC_REALLOC(auxil, array->buf, m);\n" + " array->max = m;\n" + " }\n" + " array->buf[array->len++] = ch;\n" + "}\n" + "\n" + "static void pcc_char_array__term(pcc_auxil_t auxil, pcc_char_array_t *array) {\n" + " PCC_FREE(auxil, array->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_value_table__init(pcc_auxil_t auxil, pcc_value_table_t *table) {\n" + " table->len = 0;\n" + " table->max = 0;\n" + " table->buf = NULL;\n" + "}\n" + "\n" + "MARK_FUNC_AS_USED\n" + "static void pcc_value_table__resize(pcc_auxil_t auxil, pcc_value_table_t *table, size_t len) {\n" + " if (table->max < len) {\n" + " size_t m = table->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < len && m != 0) m <<= 1;\n" + " if (m == 0) m = len;\n" + " table->buf = (pcc_value_t *)PCC_REALLOC(auxil, table->buf, sizeof(pcc_value_t) * m);\n" + " table->max = m;\n" + " }\n" + " table->len = len;\n" + "}\n" + "\n" + "MARK_FUNC_AS_USED\n" + "static void pcc_value_table__clear(pcc_auxil_t auxil, pcc_value_table_t *table) {\n" + " memset(table->buf, 0, sizeof(pcc_value_t) * table->len);\n" + "}\n" + "\n" + "static void pcc_value_table__term(pcc_auxil_t auxil, pcc_value_table_t *table) {\n" + " PCC_FREE(auxil, table->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_value_refer_table__init(pcc_auxil_t auxil, pcc_value_refer_table_t *table) {\n" + " table->len = 0;\n" + " table->max = 0;\n" + " table->buf = NULL;\n" + "}\n" + "\n" + "static void pcc_value_refer_table__resize(pcc_auxil_t auxil, pcc_value_refer_table_t *table, size_t len) {\n" + " size_t i;\n" + " if (table->max < len) {\n" + " size_t m = table->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < len && m != 0) m <<= 1;\n" + " if (m == 0) m = len;\n" + " table->buf = (pcc_value_t **)PCC_REALLOC(auxil, table->buf, sizeof(pcc_value_t *) * m);\n" + " table->max = m;\n" + " }\n" + " for (i = table->len; i < len; i++) table->buf[i] = NULL;\n" + " table->len = len;\n" + "}\n" + "\n" + "static void pcc_value_refer_table__term(pcc_auxil_t auxil, pcc_value_refer_table_t *table) {\n" + " PCC_FREE(auxil, table->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_capture__init(pcc_auxil_t auxil, pcc_capture_t *capt) {\n" + " capt->range.start = 0;\n" + " capt->range.end = 0;\n" + " pcc_char_array__init(auxil, &capt->string);\n" + "}\n" + "\n" + "static void pcc_capture__term(pcc_auxil_t auxil, pcc_capture_t *capt) {\n" + " pcc_char_array__term(auxil, &capt->string);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_capture_table__init(pcc_auxil_t auxil, pcc_capture_table_t *table) {\n" + " table->len = 0;\n" + " table->max = 0;\n" + " table->buf = NULL;\n" + "}\n" + "\n" + "MARK_FUNC_AS_USED\n" + "static void pcc_capture_table__resize(pcc_auxil_t auxil, pcc_capture_table_t *table, size_t len) {\n" + " size_t i;\n" + " for (i = len; i < table->len; i++) pcc_capture__term(auxil, &table->buf[i]);\n" + " if (table->max < len) {\n" + " size_t m = table->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < len && m != 0) m <<= 1;\n" + " if (m == 0) m = len;\n" + " table->buf = (pcc_capture_t *)PCC_REALLOC(auxil, table->buf, sizeof(pcc_capture_t) * m);\n" + " table->max = m;\n" + " }\n" + " for (i = table->len; i < len; i++) pcc_capture__init(auxil, &table->buf[i]);\n" + " table->len = len;\n" + "}\n" + "\n" + "static void pcc_capture_table__term(pcc_auxil_t auxil, pcc_capture_table_t *table) {\n" + " while (table->len > 0) {\n" + " table->len--;\n" + " pcc_capture__term(auxil, &table->buf[table->len]);\n" + " }\n" + " PCC_FREE(auxil, table->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_capture_const_table__init(pcc_auxil_t auxil, pcc_capture_const_table_t *table) {\n" + " table->len = 0;\n" + " table->max = 0;\n" + " table->buf = NULL;\n" + "}\n" + "\n" + "static void pcc_capture_const_table__resize(pcc_auxil_t auxil, pcc_capture_const_table_t *table, size_t len) {\n" + " size_t i;\n" + " if (table->max < len) {\n" + " size_t m = table->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < len && m != 0) m <<= 1;\n" + " if (m == 0) m = len;\n" + " table->buf = (const pcc_capture_t **)PCC_REALLOC(auxil, (pcc_capture_t **)table->buf, sizeof(const pcc_capture_t *) * m);\n" + " table->max = m;\n" + " }\n" + " for (i = table->len; i < len; i++) table->buf[i] = NULL;\n" + " table->len = len;\n" + "}\n" + "\n" + "static void pcc_capture_const_table__term(pcc_auxil_t auxil, pcc_capture_const_table_t *table) {\n" + " PCC_FREE(auxil, (void *)table->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_memory_recycler__init(pcc_auxil_t auxil, pcc_memory_recycler_t *recycler, size_t element_size) {\n" + " recycler->pool_list = NULL;\n" + " recycler->entry_list = NULL;\n" + " recycler->element_size = element_size;\n" + "}\n" + "\n" + "static void *pcc_memory_recycler__supply(pcc_auxil_t auxil, pcc_memory_recycler_t *recycler) {\n" + " if (recycler->entry_list) {\n" + " pcc_memory_entry_t *const tmp = recycler->entry_list;\n" + " recycler->entry_list = tmp->next;\n" + " return tmp;\n" + " }\n" + " if (!recycler->pool_list || recycler->pool_list->unused == 0) {\n" + " size_t size = PCC_POOL_MIN_SIZE;\n" + " if (recycler->pool_list) {\n" + " size = recycler->pool_list->allocated << 1;\n" + " if (size == 0) size = recycler->pool_list->allocated;\n" + " }\n" + " {\n" + " pcc_memory_pool_t *const pool = (pcc_memory_pool_t *)PCC_MALLOC(\n" + " auxil, sizeof(pcc_memory_pool_t) + recycler->element_size * size\n" + " );\n" + " pool->allocated = size;\n" + " pool->unused = size;\n" + " pool->next = recycler->pool_list;\n" + " recycler->pool_list = pool;\n" + " }\n" + " }\n" + " recycler->pool_list->unused--;\n" + " return (char *)recycler->pool_list + sizeof(pcc_memory_pool_t) + recycler->element_size * recycler->pool_list->unused;\n" + "}\n" + "\n" + "static void pcc_memory_recycler__recycle(pcc_auxil_t auxil, pcc_memory_recycler_t *recycler, void *ptr) {\n" + " pcc_memory_entry_t *const tmp = (pcc_memory_entry_t *)ptr;\n" + " tmp->next = recycler->entry_list;\n" + " recycler->entry_list = tmp;\n" + "}\n" + "\n" + "static void pcc_memory_recycler__term(pcc_auxil_t auxil, pcc_memory_recycler_t *recycler) {\n" + " while (recycler->pool_list) {\n" + " pcc_memory_pool_t *const tmp = recycler->pool_list;\n" + " recycler->pool_list = tmp->next;\n" + " PCC_FREE(auxil, tmp);\n" + " }\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "MARK_FUNC_AS_USED\n" + "static pcc_thunk_t *pcc_thunk__create_leaf(pcc_context_t *ctx, pcc_action_t action, size_t valuec, size_t captc) {\n" + " pcc_thunk_t *const thunk = (pcc_thunk_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->thunk_recycler);\n" + " thunk->type = PCC_THUNK_LEAF;\n" + " pcc_value_refer_table__init(ctx->auxil, &thunk->data.leaf.values);\n" + " pcc_value_refer_table__resize(ctx->auxil, &thunk->data.leaf.values, valuec);\n" + " pcc_capture_const_table__init(ctx->auxil, &thunk->data.leaf.capts);\n" + " pcc_capture_const_table__resize(ctx->auxil, &thunk->data.leaf.capts, captc);\n" + " pcc_capture__init(ctx->auxil, &thunk->data.leaf.capt0);\n" + " thunk->data.leaf.action = action;\n" + " return thunk;\n" + "}\n" + "\n" + "static pcc_thunk_t *pcc_thunk__create_node(pcc_context_t *ctx, const pcc_thunk_array_t *thunks, pcc_value_t *value) {\n" + " pcc_thunk_t *const thunk = (pcc_thunk_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->thunk_recycler);\n" + " thunk->type = PCC_THUNK_NODE;\n" + " thunk->data.node.thunks = thunks;\n" + " thunk->data.node.value = value;\n" + " return thunk;\n" + "}\n" + "\n" + "static void pcc_thunk__destroy(pcc_context_t *ctx, pcc_thunk_t *thunk) {\n" + " if (thunk == NULL) return;\n" + " switch (thunk->type) {\n" + " case PCC_THUNK_LEAF:\n" + " pcc_capture__term(ctx->auxil, &thunk->data.leaf.capt0);\n" + " pcc_capture_const_table__term(ctx->auxil, &thunk->data.leaf.capts);\n" + " pcc_value_refer_table__term(ctx->auxil, &thunk->data.leaf.values);\n" + " break;\n" + " case PCC_THUNK_NODE:\n" + " break;\n" + " default: /* unknown */\n" + " break;\n" + " }\n" + " pcc_memory_recycler__recycle(ctx->auxil, &ctx->thunk_recycler, thunk);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_thunk_array__init(pcc_context_t *ctx, pcc_thunk_array_t *array) {\n" + " array->len = 0;\n" + " array->max = 0;\n" + " array->buf = NULL;\n" + "}\n" + "\n" + "static void pcc_thunk_array__add(pcc_context_t *ctx, pcc_thunk_array_t *array, pcc_thunk_t *thunk) {\n" + " if (array->max <= array->len) {\n" + " const size_t n = array->len + 1;\n" + " size_t m = array->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < n && m != 0) m <<= 1;\n" + " if (m == 0) m = n;\n" + " array->buf = (pcc_thunk_t **)PCC_REALLOC(ctx->auxil, array->buf, sizeof(pcc_thunk_t *) * m);\n" + " array->max = m;\n" + " }\n" + " array->buf[array->len++] = thunk;\n" + "}\n" + "\n" + "static void pcc_thunk_array__revert(pcc_context_t *ctx, pcc_thunk_array_t *array, size_t len) {\n" + " while (array->len > len) {\n" + " array->len--;\n" + " pcc_thunk__destroy(ctx, array->buf[array->len]);\n" + " }\n" + "}\n" + "\n" + "static void pcc_thunk_array__term(pcc_context_t *ctx, pcc_thunk_array_t *array) {\n" + " while (array->len > 0) {\n" + " array->len--;\n" + " pcc_thunk__destroy(ctx, array->buf[array->len]);\n" + " }\n" + " PCC_FREE(ctx->auxil, array->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "MARK_FUNC_AS_USED\n" + "static pcc_thunk_chunk_t *pcc_thunk_chunk__create(pcc_context_t *ctx) {\n" + " pcc_thunk_chunk_t *const chunk = (pcc_thunk_chunk_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->thunk_chunk_recycler);\n" + " pcc_value_table__init(ctx->auxil, &chunk->values);\n" + " pcc_capture_table__init(ctx->auxil, &chunk->capts);\n" + " pcc_thunk_array__init(ctx, &chunk->thunks);\n" + " chunk->pos = 0;\n" + " return chunk;\n" + "}\n" + "\n" + "static void pcc_thunk_chunk__destroy(pcc_context_t *ctx, pcc_thunk_chunk_t *chunk) {\n" + " if (chunk == NULL) return;\n" + " pcc_thunk_array__term(ctx, &chunk->thunks);\n" + " pcc_capture_table__term(ctx->auxil, &chunk->capts);\n" + " pcc_value_table__term(ctx->auxil, &chunk->values);\n" + " pcc_memory_recycler__recycle(ctx->auxil, &ctx->thunk_chunk_recycler, chunk);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_rule_set__init(pcc_auxil_t auxil, pcc_rule_set_t *set) {\n" + " set->len = 0;\n" + " set->max = 0;\n" + " set->buf = NULL;\n" + "}\n" + "\n" + "static size_t pcc_rule_set__index(pcc_auxil_t auxil, const pcc_rule_set_t *set, pcc_rule_t rule) {\n" + " size_t i;\n" + " for (i = 0; i < set->len; i++) {\n" + " if (set->buf[i] == rule) return i;\n" + " }\n" + " return PCC_VOID_VALUE;\n" + "}\n" + "\n" + "static pcc_bool_t pcc_rule_set__add(pcc_auxil_t auxil, pcc_rule_set_t *set, pcc_rule_t rule) {\n" + " const size_t i = pcc_rule_set__index(auxil, set, rule);\n" + " if (i != PCC_VOID_VALUE) return PCC_FALSE;\n" + " if (set->max <= set->len) {\n" + " const size_t n = set->len + 1;\n" + " size_t m = set->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < n && m != 0) m <<= 1;\n" + " if (m == 0) m = n;\n" + " set->buf = (pcc_rule_t *)PCC_REALLOC(auxil, set->buf, sizeof(pcc_rule_t) * m);\n" + " set->max = m;\n" + " }\n" + " set->buf[set->len++] = rule;\n" + " return PCC_TRUE;\n" + "}\n" + "\n" + "static pcc_bool_t pcc_rule_set__remove(pcc_auxil_t auxil, pcc_rule_set_t *set, pcc_rule_t rule) {\n" + " const size_t i = pcc_rule_set__index(auxil, set, rule);\n" + " if (i == PCC_VOID_VALUE) return PCC_FALSE;\n" + " memmove(set->buf + i, set->buf + (i + 1), sizeof(pcc_rule_t) * (set->len - (i + 1)));\n" + " return PCC_TRUE;\n" + "}\n" + "\n" + "static void pcc_rule_set__clear(pcc_auxil_t auxil, pcc_rule_set_t *set) {\n" + " set->len = 0;\n" + "}\n" + "\n" + "static void pcc_rule_set__copy(pcc_auxil_t auxil, pcc_rule_set_t *set, const pcc_rule_set_t *src) {\n" + " size_t i;\n" + " if (set == src) return;\n" + " pcc_rule_set__clear(auxil, set);\n" + " for (i = 0; i < src->len; i++) {\n" + " pcc_rule_set__add(auxil, set, src->buf[i]);\n" + " }\n" + "}\n" + "\n" + "static void pcc_rule_set__term(pcc_auxil_t auxil, pcc_rule_set_t *set) {\n" + " PCC_FREE(auxil, set->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static pcc_lr_head_t *pcc_lr_head__create(pcc_context_t *ctx, pcc_rule_t rule) {\n" + " pcc_lr_head_t *const head = (pcc_lr_head_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->lr_head_recycler);\n" + " head->rule = rule;\n" + " pcc_rule_set__init(ctx->auxil, &head->invol);\n" + " pcc_rule_set__init(ctx->auxil, &head->eval);\n" + " head->hold = NULL;\n" + " return head;\n" + "}\n" + "\n" + "static void pcc_lr_head__destroy(pcc_context_t *ctx, pcc_lr_head_t *head) {\n" + " if (head == NULL) return;\n" + " pcc_lr_head__destroy(ctx, head->hold);\n" + " pcc_rule_set__term(ctx->auxil, &head->eval);\n" + " pcc_rule_set__term(ctx->auxil, &head->invol);\n" + " pcc_memory_recycler__recycle(ctx->auxil, &ctx->lr_head_recycler, head);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_lr_entry__destroy(pcc_context_t *ctx, pcc_lr_entry_t *lr);\n" + "\n" + "static pcc_lr_answer_t *pcc_lr_answer__create(pcc_context_t *ctx, pcc_lr_answer_type_t type, size_t pos) {\n" + " pcc_lr_answer_t *answer = (pcc_lr_answer_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->lr_answer_recycler);\n" + " answer->type = type;\n" + " answer->pos = pos;\n" + " answer->hold = NULL;\n" + " switch (answer->type) {\n" + " case PCC_LR_ANSWER_LR:\n" + " answer->data.lr = NULL;\n" + " break;\n" + " case PCC_LR_ANSWER_CHUNK:\n" + " answer->data.chunk = NULL;\n" + " break;\n" + " default: /* unknown */\n" + " pcc_memory_recycler__recycle(ctx->auxil, &ctx->lr_answer_recycler, answer);\n" + " answer = NULL;\n" + " }\n" + " return answer;\n" + "}\n" + "\n" + "static void pcc_lr_answer__set_chunk(pcc_context_t *ctx, pcc_lr_answer_t *answer, pcc_thunk_chunk_t *chunk) {\n" + " pcc_lr_answer_t *const a = pcc_lr_answer__create(ctx, answer->type, answer->pos);\n" + " switch (answer->type) {\n" + " case PCC_LR_ANSWER_LR:\n" + " a->data.lr = answer->data.lr;\n" + " break;\n" + " case PCC_LR_ANSWER_CHUNK:\n" + " a->data.chunk = answer->data.chunk;\n" + " break;\n" + " default: /* unknown */\n" + " break;\n" + " }\n" + " a->hold = answer->hold;\n" + " answer->hold = a;\n" + " answer->type = PCC_LR_ANSWER_CHUNK;\n" + " answer->data.chunk = chunk;\n" + "}\n" + "\n" + "static void pcc_lr_answer__destroy(pcc_context_t *ctx, pcc_lr_answer_t *answer) {\n" + " while (answer != NULL) {\n" + " pcc_lr_answer_t *const a = answer->hold;\n" + " switch (answer->type) {\n" + " case PCC_LR_ANSWER_LR:\n" + " pcc_lr_entry__destroy(ctx, answer->data.lr);\n" + " break;\n" + " case PCC_LR_ANSWER_CHUNK:\n" + " pcc_thunk_chunk__destroy(ctx, answer->data.chunk);\n" + " break;\n" + " default: /* unknown */\n" + " break;\n" + " }\n" + " pcc_memory_recycler__recycle(ctx->auxil, &ctx->lr_answer_recycler, answer);\n" + " answer = a;\n" + " }\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_lr_memo_map__init(pcc_context_t *ctx, pcc_lr_memo_map_t *map) {\n" + " map->len = 0;\n" + " map->max = 0;\n" + " map->buf = NULL;\n" + "}\n" + "\n" + "static size_t pcc_lr_memo_map__index(pcc_context_t *ctx, pcc_lr_memo_map_t *map, pcc_rule_t rule) {\n" + " size_t i;\n" + " for (i = 0; i < map->len; i++) {\n" + " if (map->buf[i].rule == rule) return i;\n" + " }\n" + " return PCC_VOID_VALUE;\n" + "}\n" + "\n" + "static void pcc_lr_memo_map__put(pcc_context_t *ctx, pcc_lr_memo_map_t *map, pcc_rule_t rule, pcc_lr_answer_t *answer) {\n" + " const size_t i = pcc_lr_memo_map__index(ctx, map, rule);\n" + " if (i != PCC_VOID_VALUE) {\n" + " pcc_lr_answer__destroy(ctx, map->buf[i].answer);\n" + " map->buf[i].answer = answer;\n" + " }\n" + " else {\n" + " if (map->max <= map->len) {\n" + " const size_t n = map->len + 1;\n" + " size_t m = map->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < n && m != 0) m <<= 1;\n" + " if (m == 0) m = n;\n" + " map->buf = (pcc_lr_memo_t *)PCC_REALLOC(ctx->auxil, map->buf, sizeof(pcc_lr_memo_t) * m);\n" + " map->max = m;\n" + " }\n" + " map->buf[map->len].rule = rule;\n" + " map->buf[map->len].answer = answer;\n" + " map->len++;\n" + " }\n" + "}\n" + "\n" + "static pcc_lr_answer_t *pcc_lr_memo_map__get(pcc_context_t *ctx, pcc_lr_memo_map_t *map, pcc_rule_t rule) {\n" + " const size_t i = pcc_lr_memo_map__index(ctx, map, rule);\n" + " return (i != PCC_VOID_VALUE) ? map->buf[i].answer : NULL;\n" + "}\n" + "\n" + "static void pcc_lr_memo_map__term(pcc_context_t *ctx, pcc_lr_memo_map_t *map) {\n" + " while (map->len > 0) {\n" + " map->len--;\n" + " pcc_lr_answer__destroy(ctx, map->buf[map->len].answer);\n" + " }\n" + " PCC_FREE(ctx->auxil, map->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static pcc_lr_table_entry_t *pcc_lr_table_entry__create(pcc_context_t *ctx) {\n" + " pcc_lr_table_entry_t *const entry = (pcc_lr_table_entry_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->lr_table_entry_recycler);\n" + " entry->head = NULL;\n" + " pcc_lr_memo_map__init(ctx, &entry->memos);\n" + " entry->hold_a = NULL;\n" + " entry->hold_h = NULL;\n" + " return entry;\n" + "}\n" + "\n" + "static void pcc_lr_table_entry__destroy(pcc_context_t *ctx, pcc_lr_table_entry_t *entry) {\n" + " if (entry == NULL) return;\n" + " pcc_lr_head__destroy(ctx, entry->hold_h);\n" + " pcc_lr_answer__destroy(ctx, entry->hold_a);\n" + " pcc_lr_memo_map__term(ctx, &entry->memos);\n" + " pcc_memory_recycler__recycle(ctx->auxil, &ctx->lr_table_entry_recycler, entry);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_lr_table__init(pcc_context_t *ctx, pcc_lr_table_t *table) {\n" + " table->ofs = 0;\n" + " table->len = 0;\n" + " table->max = 0;\n" + " table->buf = NULL;\n" + "}\n" + "\n" + "static void pcc_lr_table__resize(pcc_context_t *ctx, pcc_lr_table_t *table, size_t len) {\n" + " size_t i;\n" + " for (i = len; i < table->len; i++) pcc_lr_table_entry__destroy(ctx, table->buf[i]);\n" + " if (table->max < len) {\n" + " size_t m = table->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < len && m != 0) m <<= 1;\n" + " if (m == 0) m = len;\n" + " table->buf = (pcc_lr_table_entry_t **)PCC_REALLOC(ctx->auxil, table->buf, sizeof(pcc_lr_table_entry_t *) * m);\n" + " table->max = m;\n" + " }\n" + " for (i = table->len; i < len; i++) table->buf[i] = NULL;\n" + " table->len = len;\n" + "}\n" + "\n" + "static void pcc_lr_table__set_head(pcc_context_t *ctx, pcc_lr_table_t *table, size_t index, pcc_lr_head_t *head) {\n" + " index += table->ofs;\n" + " if (index >= table->len) pcc_lr_table__resize(ctx, table, index + 1);\n" + " if (table->buf[index] == NULL) table->buf[index] = pcc_lr_table_entry__create(ctx);\n" + " table->buf[index]->head = head;\n" + "}\n" + "\n" + "static void pcc_lr_table__hold_head(pcc_context_t *ctx, pcc_lr_table_t *table, size_t index, pcc_lr_head_t *head) {\n" + " index += table->ofs;\n" + " if (index >= table->len) pcc_lr_table__resize(ctx, table, index + 1);\n" + " if (table->buf[index] == NULL) table->buf[index] = pcc_lr_table_entry__create(ctx);\n" + " head->hold = table->buf[index]->hold_h;\n" + " table->buf[index]->hold_h = head;\n" + "}\n" + "\n" + "static void pcc_lr_table__set_answer(pcc_context_t *ctx, pcc_lr_table_t *table, size_t index, pcc_rule_t rule, pcc_lr_answer_t *answer) {\n" + " index += table->ofs;\n" + " if (index >= table->len) pcc_lr_table__resize(ctx, table, index + 1);\n" + " if (table->buf[index] == NULL) table->buf[index] = pcc_lr_table_entry__create(ctx);\n" + " pcc_lr_memo_map__put(ctx, &table->buf[index]->memos, rule, answer);\n" + "}\n" + "\n" + "static void pcc_lr_table__hold_answer(pcc_context_t *ctx, pcc_lr_table_t *table, size_t index, pcc_lr_answer_t *answer) {\n" + " index += table->ofs;\n" + " if (index >= table->len) pcc_lr_table__resize(ctx, table, index + 1);\n" + " if (table->buf[index] == NULL) table->buf[index] = pcc_lr_table_entry__create(ctx);\n" + " answer->hold = table->buf[index]->hold_a;\n" + " table->buf[index]->hold_a = answer;\n" + "}\n" + "\n" + "static pcc_lr_head_t *pcc_lr_table__get_head(pcc_context_t *ctx, pcc_lr_table_t *table, size_t index) {\n" + " index += table->ofs;\n" + " if (index >= table->len || table->buf[index] == NULL) return NULL;\n" + " return table->buf[index]->head;\n" + "}\n" + "\n" + "static pcc_lr_answer_t *pcc_lr_table__get_answer(pcc_context_t *ctx, pcc_lr_table_t *table, size_t index, pcc_rule_t rule) {\n" + " index += table->ofs;\n" + " if (index >= table->len || table->buf[index] == NULL) return NULL;\n" + " return pcc_lr_memo_map__get(ctx, &table->buf[index]->memos, rule);\n" + "}\n" + "\n" + "static void pcc_lr_table__shift(pcc_context_t *ctx, pcc_lr_table_t *table, size_t count) {\n" + " size_t i;\n" + " if (count > table->len - table->ofs) count = table->len - table->ofs;\n" + " for (i = 0; i < count; i++) pcc_lr_table_entry__destroy(ctx, table->buf[table->ofs++]);\n" + " if (table->ofs > (table->max >> 1)) {\n" + " memmove(table->buf, table->buf + table->ofs, sizeof(pcc_lr_table_entry_t *) * (table->len - table->ofs));\n" + " table->len -= table->ofs;\n" + " table->ofs = 0;\n" + " }\n" + "}\n" + "\n" + "static void pcc_lr_table__term(pcc_context_t *ctx, pcc_lr_table_t *table) {\n" + " while (table->len > table->ofs) {\n" + " table->len--;\n" + " pcc_lr_table_entry__destroy(ctx, table->buf[table->len]);\n" + " }\n" + " PCC_FREE(ctx->auxil, table->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static pcc_lr_entry_t *pcc_lr_entry__create(pcc_context_t *ctx, pcc_rule_t rule) {\n" + " pcc_lr_entry_t *const lr = (pcc_lr_entry_t *)pcc_memory_recycler__supply(ctx->auxil, &ctx->lr_entry_recycler);\n" + " lr->rule = rule;\n" + " lr->seed = NULL;\n" + " lr->head = NULL;\n" + " return lr;\n" + "}\n" + "\n" + "static void pcc_lr_entry__destroy(pcc_context_t *ctx, pcc_lr_entry_t *lr) {\n" + " pcc_memory_recycler__recycle(ctx->auxil, &ctx->lr_entry_recycler, lr);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_lr_stack__init(pcc_auxil_t auxil, pcc_lr_stack_t *stack) {\n" + " stack->len = 0;\n" + " stack->max = 0;\n" + " stack->buf = NULL;\n" + "}\n" + "\n" + "static void pcc_lr_stack__push(pcc_auxil_t auxil, pcc_lr_stack_t *stack, pcc_lr_entry_t *lr) {\n" + " if (stack->max <= stack->len) {\n" + " const size_t n = stack->len + 1;\n" + " size_t m = stack->max;\n" + " if (m == 0) m = PCC_ARRAY_MIN_SIZE;\n" + " while (m < n && m != 0) m <<= 1;\n" + " if (m == 0) m = n;\n" + " stack->buf = (pcc_lr_entry_t **)PCC_REALLOC(auxil, stack->buf, sizeof(pcc_lr_entry_t *) * m);\n" + " stack->max = m;\n" + " }\n" + " stack->buf[stack->len++] = lr;\n" + "}\n" + "\n" + "static pcc_lr_entry_t *pcc_lr_stack__pop(pcc_auxil_t auxil, pcc_lr_stack_t *stack) {\n" + " return stack->buf[--stack->len];\n" + "}\n" + "\n" + "static void pcc_lr_stack__term(pcc_auxil_t auxil, pcc_lr_stack_t *stack) {\n" + " PCC_FREE(auxil, stack->buf);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static pcc_context_t *pcc_context__create(pcc_auxil_t auxil) {\n" + " pcc_context_t *const ctx = (pcc_context_t *)PCC_MALLOC(auxil, sizeof(pcc_context_t));\n" + " ctx->pos = 0;\n" + " ctx->cur = 0;\n" + " ctx->level = 0;\n" + " pcc_char_array__init(auxil, &ctx->buffer);\n" + " pcc_lr_table__init(ctx, &ctx->lrtable);\n" + " pcc_lr_stack__init(auxil, &ctx->lrstack);\n" + " pcc_thunk_array__init(ctx, &ctx->thunks);\n" + " pcc_memory_recycler__init(auxil, &ctx->thunk_recycler, sizeof(pcc_thunk_t));\n" + " pcc_memory_recycler__init(auxil, &ctx->thunk_chunk_recycler, sizeof(pcc_thunk_chunk_t));\n" + " pcc_memory_recycler__init(auxil, &ctx->lr_head_recycler, sizeof(pcc_lr_head_t));\n" + " pcc_memory_recycler__init(auxil, &ctx->lr_answer_recycler, sizeof(pcc_lr_answer_t));\n" + " pcc_memory_recycler__init(auxil, &ctx->lr_table_entry_recycler, sizeof(pcc_lr_table_entry_t));\n" + " pcc_memory_recycler__init(auxil, &ctx->lr_entry_recycler, sizeof(pcc_lr_entry_t));\n" + " ctx->auxil = auxil;\n" + " return ctx;\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static void pcc_context__destroy(pcc_context_t *ctx) {\n" + " if (ctx == NULL) return;\n" + " pcc_thunk_array__term(ctx, &ctx->thunks);\n" + " pcc_lr_stack__term(ctx->auxil, &ctx->lrstack);\n" + " pcc_lr_table__term(ctx, &ctx->lrtable);\n" + " pcc_char_array__term(ctx->auxil, &ctx->buffer);\n" + " pcc_memory_recycler__term(ctx->auxil, &ctx->thunk_recycler);\n" + " pcc_memory_recycler__term(ctx->auxil, &ctx->thunk_chunk_recycler);\n" + " pcc_memory_recycler__term(ctx->auxil, &ctx->lr_head_recycler);\n" + " pcc_memory_recycler__term(ctx->auxil, &ctx->lr_answer_recycler);\n" + " pcc_memory_recycler__term(ctx->auxil, &ctx->lr_table_entry_recycler);\n" + " pcc_memory_recycler__term(ctx->auxil, &ctx->lr_entry_recycler);\n" + " PCC_FREE(ctx->auxil, ctx);\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "static size_t pcc_refill_buffer(pcc_context_t *ctx, size_t num) {\n" + " if (ctx->buffer.len >= ctx->cur + num) return ctx->buffer.len - ctx->cur;\n" + " while (ctx->buffer.len < ctx->cur + num) {\n" + " const int c = PCC_GETCHAR(ctx->auxil);\n" + " if (c < 0) break;\n" + " pcc_char_array__add(ctx->auxil, &ctx->buffer, (char)c);\n" + " }\n" + " return ctx->buffer.len - ctx->cur;\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "MARK_FUNC_AS_USED\n" + "static void pcc_commit_buffer(pcc_context_t *ctx) {\n" + " memmove(ctx->buffer.buf, ctx->buffer.buf + ctx->cur, ctx->buffer.len - ctx->cur);\n" + " ctx->buffer.len -= ctx->cur;\n" + " ctx->pos += ctx->cur;\n" + " pcc_lr_table__shift(ctx, &ctx->lrtable, ctx->cur);\n" + " ctx->cur = 0;\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "MARK_FUNC_AS_USED\n" + "static const char *pcc_get_capture_string(pcc_context_t *ctx, const pcc_capture_t *capt) {\n" + " if (capt->string.len == 0) {\n" + " const size_t n = capt->range.end - capt->range.start;\n" + " pcc_capture_t *const p = (pcc_capture_t *)capt;\n" + " pcc_char_array__resize(ctx->auxil, &p->string, n + 1);\n" + " if (n > 0) memcpy(p->string.buf, ctx->buffer.buf + capt->range.start, n);\n" + " p->string.buf[n] = '\\0';\n" + " }\n" + " return capt->string.buf;\n" + "}\n" + "\n" + ); + if (ctx->flags & CODE_FLAG__UTF8_CHARCLASS_USED) { + stream__puts( + &sstream, + "static size_t pcc_get_char_as_utf32(pcc_context_t *ctx, int *out) { /* with checking UTF-8 validity */\n" + " int c, u;\n" + " size_t n, i;\n" + " if (pcc_refill_buffer(ctx, 1) < 1) return 0;\n" + " c = (int)(unsigned char)ctx->buffer.buf[ctx->cur];\n" + " n = (c < 0x80) ? 1 :\n" + " ((c & 0xe0) == 0xc0) ? 2 :\n" + " ((c & 0xf0) == 0xe0) ? 3 :\n" + " ((c & 0xf8) == 0xf0) ? 4 :\n" + " ((c & 0xfc) == 0xf8) ? 5 :\n" + " ((c & 0xfe) == 0xfc) ? 6 : 0;\n" + " if (n < 1) return 0;\n" + " if (pcc_refill_buffer(ctx, n) < n) return 0;\n" + " u = (n <= 1) ? c : (c & ((1 << (7 - n)) - 1));\n" + " for (i = 1; i < n; i++) {\n" + " const int d = (int)(unsigned char)ctx->buffer.buf[ctx->cur + i];\n" + " if ((d & 0xc0) != 0x80) return 0; /* not a continuation byte */\n" + " u = (u << 6) | (d & 0x3f);\n" + " }\n" + " if (\n" + " (n == 2 && u < 0x00000080) ||\n" + " (n == 3 && u < 0x00000800) ||\n" + " (n == 4 && u < 0x00010000) ||\n" + " (n == 5 && u < 0x00200000) ||\n" + " (n == 6 && u < 0x04000000)\n" + " ) return 0; /* invalidly encoded */\n" + " if (out) *out = u;\n" + " return n;\n" + "}\n" + "\n" + ); + } + stream__puts( + &sstream, + "MARK_FUNC_AS_USED\n" + "static pcc_bool_t pcc_apply_rule(pcc_context_t *ctx, pcc_rule_t rule, pcc_thunk_array_t *thunks, pcc_value_t *value) {\n" + " static pcc_value_t null;\n" + " pcc_thunk_chunk_t *c = NULL;\n" + " const size_t p = ctx->pos + ctx->cur;\n" + " pcc_bool_t b = PCC_TRUE;\n" + " pcc_lr_answer_t *a = pcc_lr_table__get_answer(ctx, &ctx->lrtable, p, rule);\n" + " pcc_lr_head_t *h = pcc_lr_table__get_head(ctx, &ctx->lrtable, p);\n" + " if (h != NULL) {\n" + " if (a == NULL && rule != h->rule && pcc_rule_set__index(ctx->auxil, &h->invol, rule) == PCC_VOID_VALUE) {\n" + " b = PCC_FALSE;\n" + " c = NULL;\n" + " }\n" + " else if (pcc_rule_set__remove(ctx->auxil, &h->eval, rule)) {\n" + " b = PCC_FALSE;\n" + " c = rule(ctx);\n" + " a = pcc_lr_answer__create(ctx, PCC_LR_ANSWER_CHUNK, ctx->pos + ctx->cur);\n" + " a->data.chunk = c;\n" + " pcc_lr_table__hold_answer(ctx, &ctx->lrtable, p, a);\n" + " }\n" + " }\n" + " if (b) {\n" + " if (a != NULL) {\n" + " ctx->cur = a->pos - ctx->pos;\n" + " switch (a->type) {\n" + " case PCC_LR_ANSWER_LR:\n" + " if (a->data.lr->head == NULL) {\n" + " a->data.lr->head = pcc_lr_head__create(ctx, rule);\n" + " pcc_lr_table__hold_head(ctx, &ctx->lrtable, p, a->data.lr->head);\n" + " }\n" + " {\n" + " size_t i = ctx->lrstack.len;\n" + " while (i > 0) {\n" + " i--;\n" + " if (ctx->lrstack.buf[i]->head == a->data.lr->head) break;\n" + " ctx->lrstack.buf[i]->head = a->data.lr->head;\n" + " pcc_rule_set__add(ctx->auxil, &a->data.lr->head->invol, ctx->lrstack.buf[i]->rule);\n" + " }\n" + " }\n" + " c = a->data.lr->seed;\n" + " break;\n" + " case PCC_LR_ANSWER_CHUNK:\n" + " c = a->data.chunk;\n" + " break;\n" + " default: /* unknown */\n" + " break;\n" + " }\n" + " }\n" + " else {\n" + " pcc_lr_entry_t *const e = pcc_lr_entry__create(ctx, rule);\n" + " pcc_lr_stack__push(ctx->auxil, &ctx->lrstack, e);\n" + " a = pcc_lr_answer__create(ctx, PCC_LR_ANSWER_LR, p);\n" + " a->data.lr = e;\n" + " pcc_lr_table__set_answer(ctx, &ctx->lrtable, p, rule, a);\n" + " c = rule(ctx);\n" + " pcc_lr_stack__pop(ctx->auxil, &ctx->lrstack);\n" + " a->pos = ctx->pos + ctx->cur;\n" + " if (e->head == NULL) {\n" + " pcc_lr_answer__set_chunk(ctx, a, c);\n" + " }\n" + " else {\n" + " e->seed = c;\n" + " h = a->data.lr->head;\n" + " if (h->rule != rule) {\n" + " c = a->data.lr->seed;\n" + " a = pcc_lr_answer__create(ctx, PCC_LR_ANSWER_CHUNK, ctx->pos + ctx->cur);\n" + " a->data.chunk = c;\n" + " pcc_lr_table__hold_answer(ctx, &ctx->lrtable, p, a);\n" + " }\n" + " else {\n" + " pcc_lr_answer__set_chunk(ctx, a, a->data.lr->seed);\n" + " if (a->data.chunk == NULL) {\n" + " c = NULL;\n" + " }\n" + " else {\n" + " pcc_lr_table__set_head(ctx, &ctx->lrtable, p, h);\n" + " for (;;) {\n" + " ctx->cur = p - ctx->pos;\n" + " pcc_rule_set__copy(ctx->auxil, &h->eval, &h->invol);\n" + " c = rule(ctx);\n" + " if (c == NULL || ctx->pos + ctx->cur <= a->pos) break;\n" + " pcc_lr_answer__set_chunk(ctx, a, c);\n" + " a->pos = ctx->pos + ctx->cur;\n" + " }\n" + " pcc_thunk_chunk__destroy(ctx, c);\n" + " pcc_lr_table__set_head(ctx, &ctx->lrtable, p, NULL);\n" + " ctx->cur = a->pos - ctx->pos;\n" + " c = a->data.chunk;\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " if (c == NULL) return PCC_FALSE;\n" + " if (value == NULL) value = &null;\n" + " memset(value, 0, sizeof(pcc_value_t)); /* in case */\n" + " pcc_thunk_array__add(ctx, thunks, pcc_thunk__create_node(ctx, &c->thunks, value));\n" + " return PCC_TRUE;\n" + "}\n" + "\n" + ); + stream__puts( + &sstream, + "MARK_FUNC_AS_USED\n" + "static void pcc_do_action(pcc_context_t *ctx, const pcc_thunk_array_t *thunks, pcc_value_t *value) {\n" + " size_t i;\n" + " for (i = 0; i < thunks->len; i++) {\n" + " pcc_thunk_t *const thunk = thunks->buf[i];\n" + " switch (thunk->type) {\n" + " case PCC_THUNK_LEAF:\n" + " thunk->data.leaf.action(ctx, thunk, value);\n" + " break;\n" + " case PCC_THUNK_NODE:\n" + " pcc_do_action(ctx, thunk->data.node.thunks, thunk->data.node.value);\n" + " break;\n" + " default: /* unknown */\n" + " break;\n" + " }\n" + " }\n" + "}\n" + "\n" + ); + { + size_t i, j, k; + for (i = 0; i < ctx->rules.len; i++) { + const node_rule_t *const rule = &ctx->rules.buf[i]->data.rule; + for (j = 0; j < rule->codes.len; j++) { + const code_block_t *b; + size_t d; + const node_const_array_t *v, *c; + switch (rule->codes.buf[j]->type) { + case NODE_ACTION: + b = &rule->codes.buf[j]->data.action.code; + d = rule->codes.buf[j]->data.action.index; + v = &rule->codes.buf[j]->data.action.vars; + c = &rule->codes.buf[j]->data.action.capts; + break; + case NODE_ERROR: + b = &rule->codes.buf[j]->data.error.code; + d = rule->codes.buf[j]->data.error.index; + v = &rule->codes.buf[j]->data.error.vars; + c = &rule->codes.buf[j]->data.error.capts; + break; + default: + print_error("Internal error [%d]\n", __LINE__); + exit(-1); + } + stream__printf( + &sstream, + "static void pcc_action_%s_" FMT_LU "(%s_context_t *__pcc_ctx, pcc_thunk_t *__pcc_in, pcc_value_t *__pcc_out) {\n", + rule->name, (ulong_t)d, get_prefix(ctx) + ); + stream__puts( + &sstream, + "#define auxil (__pcc_ctx->auxil)\n" + "#define __ (*__pcc_out)\n" + ); + k = 0; + while (k < v->len) { + assert(v->buf[k]->type == NODE_REFERENCE); + stream__printf( + &sstream, + "#define %s (*__pcc_in->data.leaf.values.buf[" FMT_LU "])\n", + v->buf[k]->data.reference.var, (ulong_t)v->buf[k]->data.reference.index + ); + k++; + } + stream__puts( + &sstream, + "#define _0 pcc_get_capture_string(__pcc_ctx, &__pcc_in->data.leaf.capt0)\n" + "#define _0s ((const size_t)(__pcc_ctx->pos + __pcc_in->data.leaf.capt0.range.start))\n" + "#define _0e ((const size_t)(__pcc_ctx->pos + __pcc_in->data.leaf.capt0.range.end))\n" + ); + k = 0; + while (k < c->len) { + assert(c->buf[k]->type == NODE_CAPTURE); + stream__printf( + &sstream, + "#define _" FMT_LU " pcc_get_capture_string(__pcc_ctx, __pcc_in->data.leaf.capts.buf[" FMT_LU "])\n", + (ulong_t)(c->buf[k]->data.capture.index + 1), (ulong_t)c->buf[k]->data.capture.index + ); + stream__printf( + &sstream, + "#define _" FMT_LU "s ((const size_t)(__pcc_ctx->pos + __pcc_in->data.leaf.capts.buf[" FMT_LU "]->range.start))\n", + (ulong_t)(c->buf[k]->data.capture.index + 1), (ulong_t)c->buf[k]->data.capture.index + ); + stream__printf( + &sstream, + "#define _" FMT_LU "e ((const size_t)(__pcc_ctx->pos + __pcc_in->data.leaf.capts.buf[" FMT_LU "]->range.end))\n", + (ulong_t)(c->buf[k]->data.capture.index + 1), (ulong_t)c->buf[k]->data.capture.index + ); + k++; + } + stream__write_code_block(&sstream, b->text, b->len, 4, b->fpos.path, b->fpos.line, TRUE, &ctx->subst); + k = c->len; + while (k > 0) { + k--; + assert(c->buf[k]->type == NODE_CAPTURE); + stream__printf( + &sstream, + "#undef _" FMT_LU "e\n", + (ulong_t)(c->buf[k]->data.capture.index + 1) + ); + stream__printf( + &sstream, + "#undef _" FMT_LU "s\n", + (ulong_t)(c->buf[k]->data.capture.index + 1) + ); + stream__printf( + &sstream, + "#undef _" FMT_LU "\n", + (ulong_t)(c->buf[k]->data.capture.index + 1) + ); + } + stream__puts( + &sstream, + "#undef _0e\n" + "#undef _0s\n" + "#undef _0\n" + ); + k = v->len; + while (k > 0) { + k--; + assert(v->buf[k]->type == NODE_REFERENCE); + stream__printf( + &sstream, + "#undef %s\n", + v->buf[k]->data.reference.var + ); + } + stream__puts( + &sstream, + "#undef __\n" + "#undef auxil\n" + ); + stream__puts( + &sstream, + "}\n" + "\n" + ); + } + } + } + { + size_t i; + for (i = 0; i < ctx->rules.len; i++) { + const node_rule_t *const rule = &ctx->rules.buf[i]->data.rule; + stream__printf( + &sstream, + "static pcc_thunk_chunk_t *pcc_evaluate_rule_%s(pcc_context_t *ctx);\n", + rule->name + ); + } + stream__puts( + &sstream, + "\n" + ); + for (i = 0; i < ctx->rules.len; i++) { + code_reach_t r; + generate_t g; + const node_rule_t *const rule = &ctx->rules.buf[i]->data.rule; + g.stream = &sstream; + g.rule = ctx->rules.buf[i]; + g.label = 0; + g.ascii = ctx->opts.ascii; + stream__printf( + &sstream, + "static pcc_thunk_chunk_t *pcc_evaluate_rule_%s(pcc_context_t *ctx) {\n", + rule->name + ); + stream__printf( + &sstream, + " pcc_thunk_chunk_t *const chunk = pcc_thunk_chunk__create(ctx);\n" + " chunk->pos = ctx->cur;\n" + " PCC_DEBUG(ctx->auxil, PCC_DBG_EVALUATE, \"%s\", ctx->level, chunk->pos, (ctx->buffer.buf + chunk->pos), (ctx->buffer.len - chunk->pos));\n" + " ctx->level++;\n", + rule->name + ); + if (rule->capts.len > 0) { + stream__printf( + &sstream, + " pcc_capture_table__resize(ctx->auxil, &chunk->capts, " FMT_LU ");\n", + (ulong_t)rule->capts.len + ); + } + if (rule->vars.len > 0) { + stream__printf( + &sstream, + " pcc_value_table__resize(ctx->auxil, &chunk->values, " FMT_LU ");\n", + (ulong_t)rule->vars.len + ); + stream__puts( + &sstream, + " pcc_value_table__clear(ctx->auxil, &chunk->values);\n" + ); + } + r = generate_code(&g, rule->expr, 0, 4, FALSE); + stream__printf( + &sstream, + " ctx->level--;\n" + " PCC_DEBUG(ctx->auxil, PCC_DBG_MATCH, \"%s\", ctx->level, chunk->pos, (ctx->buffer.buf + chunk->pos), (ctx->cur - chunk->pos));\n" + " return chunk;\n", + rule->name + ); + if (r != CODE_REACH__ALWAYS_SUCCEED) { + stream__printf( + &sstream, + "L0000:;\n" + " ctx->level--;\n" + " PCC_DEBUG(ctx->auxil, PCC_DBG_NOMATCH, \"%s\", ctx->level, chunk->pos, (ctx->buffer.buf + chunk->pos), (ctx->cur - chunk->pos));\n" + " pcc_thunk_chunk__destroy(ctx, chunk);\n" + " return NULL;\n", + rule->name + ); + } + stream__puts( + &sstream, + "}\n" + "\n" + ); + } + } + stream__printf( + &sstream, + "%s_context_t *%s_create(%s%sauxil) {\n", + get_prefix(ctx), get_prefix(ctx), + at, ap ? "" : " " + ); + stream__puts( + &sstream, + " return pcc_context__create(auxil);\n" + "}\n" + "\n" + ); + stream__printf( + &sstream, + "int %s_parse(%s_context_t *ctx, %s%s*ret) {\n", + get_prefix(ctx), get_prefix(ctx), + vt, vp ? "" : " " + ); + stream__printf( + &sstream, + " if (pcc_refill_buffer(ctx, 1) < 1) return 0;\n" + ); + if (ctx->rules.len > 0) { + stream__printf( + &sstream, + " if (pcc_apply_rule(ctx, pcc_evaluate_rule_%s, &ctx->thunks, ret))\n", + ctx->rules.buf[0]->data.rule.name + ); + stream__puts( + &sstream, + " pcc_do_action(ctx, &ctx->thunks, ret);\n" + " else\n" + " PCC_ERROR(ctx->auxil);\n" + " pcc_commit_buffer(ctx);\n" + ); + } + stream__puts( + &sstream, + " pcc_thunk_array__revert(ctx, &ctx->thunks, 0);\n" + " return 1;\n" + "}\n" + "\n" + ); + stream__printf( + &sstream, + "void %s_destroy(%s_context_t *ctx) {\n", + get_prefix(ctx), get_prefix(ctx) + ); + stream__puts( + &sstream, + " pcc_context__destroy(ctx);\n" + "}\n" + ); + } + { + stream__puts( + &hstream, + "#ifdef __cplusplus\n" + "extern \"C\" {\n" + "#endif\n" + "\n" + ); + stream__printf( + &hstream, + "typedef struct %s_context_tag %s_context_t;\n" + "\n", + get_prefix(ctx), get_prefix(ctx) + ); + stream__printf( + &hstream, + "%s_context_t *%s_create(%s%sauxil);\n", + get_prefix(ctx), get_prefix(ctx), + at, ap ? "" : " " + ); + stream__printf( + &hstream, + "int %s_parse(%s_context_t *ctx, %s%s*ret);\n", + get_prefix(ctx), get_prefix(ctx), + vt, vp ? "" : " " + ); + stream__printf( + &hstream, + "void %s_destroy(%s_context_t *ctx);\n", + get_prefix(ctx), get_prefix(ctx) + ); + stream__puts( + &hstream, + "\n" + "#ifdef __cplusplus\n" + "}\n" + "#endif\n" + ); + stream__printf( + &hstream, + "\n" + "#endif /* !PCC_INCLUDED_%s */\n", + ctx->hid + ); + } + { + size_t i; + for (i = 0; i < ctx->fsource.len; i++) { + stream__putc(&sstream, '\n'); + stream__write_footer( + &sstream, ctx->fsource.buf[i].text, ctx->fsource.buf[i].len, + ctx->fsource.buf[i].fpos.path, ctx->fsource.buf[i].fpos.line, &ctx->subst + ); + } + } + fclose_e(hstream.file, hstream.path); + fclose_e(sstream.file, sstream.path); + if (ctx->errnum) { + unlink(ctx->hpath); + unlink(ctx->spath); + return FALSE; + } + return TRUE; +} + +static void print_version(FILE *output) { + fprintf(output, "%s version %s\n", g_cmdname, VERSION); + fprintf(output, "Copyright (c) 2014, 2019-2025 Arihiro Yoshida. All rights reserved.\n"); +} + +static void print_usage(FILE *output) { + fprintf(output, "Usage: %s [OPTIONS] [FILE]\n", g_cmdname); + fprintf(output, "Generates a packrat parser for C.\n"); + fprintf(output, "\n"); + fprintf(output, "Options:\n"); + fprintf(output, " -o BASENAME specify a base name of output source and header files;\n"); + fprintf(output, " can be used only once\n"); + fprintf(output, " -I DIRNAME specify a directory name to search for import files;\n"); + fprintf(output, " can be used as many times as needed to add directories\n"); + fprintf(output, " -a, --ascii disable UTF-8 support\n"); + fprintf(output, " -l, --lines add #line directives\n"); + fprintf(output, " -d, --debug with debug information\n"); + fprintf(output, " -h, --help print this help message and exit\n"); + fprintf(output, " -v, --version print the version and exit\n"); + fprintf(output, "\n"); + fprintf(output, "Environment Variable:\n"); + fprintf(output, " %s\n", ENVVAR_IMPORT_PATH); + fprintf(output, " specify directory names to search for import files, delimited by '%c'\n", PATH_SEP); + fprintf(output, "\n"); + fprintf(output, "Full documentation at: <%s>\n", WEBSITE); +} + +int main(int argc, char **argv) { +#ifdef _MSC_VER +#ifdef _DEBUG + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); +#endif +#endif + g_cmdname = extract_filename(argv[0]); + { + const char *ipath = NULL; + const char *opath = NULL; + options_t opts = { 0 }; + string_array_t dirs; + string_array__init(&dirs); + opts.ascii = FALSE; + opts.lines = FALSE; + opts.debug = FALSE; + { + const char *path = NULL; + const char *opt_o = NULL; + bool_t opt_a = FALSE; + bool_t opt_l = FALSE; + bool_t opt_d = FALSE; + bool_t opt_h = FALSE; + bool_t opt_v = FALSE; + int i; + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + break; + } + else if (strcmp(argv[i], "--") == 0) { + i++; break; + } + else if (argv[i][1] == 'I') { + const char *const v = (argv[i][2] != '\0') ? argv[i] + 2 : (++i < argc) ? argv[i] : NULL; + if (v == NULL || v[0] == '\0') { + print_error("Import directory name missing\n"); + fprintf(stderr, "\n"); + print_usage(stderr); + exit(1); + } + string_array__add(&dirs, v, VOID_VALUE); + } + else if (argv[i][1] == 'o') { + const char *const v = (argv[i][2] != '\0') ? argv[i] + 2 : (++i < argc) ? argv[i] : NULL; + if (v == NULL || v[0] == '\0') { + print_error("Output base name missing\n"); + fprintf(stderr, "\n"); + print_usage(stderr); + exit(1); + } + if (opt_o != NULL) { + print_error("Extra output base name: '%s'\n", v); + fprintf(stderr, "\n"); + print_usage(stderr); + exit(1); + } + opt_o = v; + } + else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--ascii") == 0) { + opt_a = TRUE; + } + else if (strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--lines") == 0) { + opt_l = TRUE; + } + else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--debug") == 0) { + opt_d = TRUE; + } + else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + opt_h = TRUE; + } + else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) { + opt_v = TRUE; + } + else { + print_error("Invalid option: '%s'\n", argv[i]); + fprintf(stderr, "\n"); + print_usage(stderr); + exit(1); + } + } + switch (argc - i) { + case 0: + break; + case 1: + path = argv[i]; + break; + default: + print_error("Extra input file: '%s'\n", argv[i + 1]); + fprintf(stderr, "\n"); + print_usage(stderr); + exit(1); + } + if (opt_h || opt_v) { + if (opt_v) print_version(stdout); + if (opt_v && opt_h) fprintf(stdout, "\n"); + if (opt_h) print_usage(stdout); + exit(0); + } + ipath = (path && path[0]) ? path : NULL; + opath = (opt_o && opt_o[0]) ? opt_o : NULL; + opts.ascii = opt_a; + opts.lines = opt_l; + opts.debug = opt_d; + } + { + const char *const v = getenv(ENVVAR_IMPORT_PATH); + if (v) { + size_t i = 0, h = 0; + for (;;) { + if (v[i] == '\0') { + if (i > h) string_array__add(&dirs, v + h, i - h); + break; + } + else if (v[i] == PATH_SEP) { + if (i > h) string_array__add(&dirs, v + h, i - h); + h = i + 1; + } + i++; + } + } + } + { + char *const s = get_home_directory(); + if (s) { + char *const t = add_filename(s, IMPORT_DIR_USER); + string_array__add(&dirs, t, VOID_VALUE); + free(t); + free(s); + } + } + { +#ifdef _MSC_VER + char *const s = get_appdata_directory(); + if (s) { + char *const t = add_filename(s, IMPORT_DIR_SYSTEM); + string_array__add(&dirs, t, VOID_VALUE); + free(t); + free(s); + } +#else + string_array__add(&dirs, IMPORT_DIR_SYSTEM, VOID_VALUE); +#endif + } + { + context_t *const ctx = create_context(ipath, opath, &dirs, &opts); + const int b = parse(ctx) && generate(ctx); + destroy_context(ctx); + if (!b) exit(10); + } + string_array__term(&dirs); + } + return 0; +} diff --git a/src/subprojects/packcc/tests/.gitignore b/src/subprojects/packcc/tests/.gitignore new file mode 100644 index 00000000..2e126c89 --- /dev/null +++ b/src/subprojects/packcc/tests/.gitignore @@ -0,0 +1,10 @@ +packcc +packcc.exe +*.gcda +*.gcno +*.gcov +*/parser.c +*/parser.h +*/parser +*/parser.exe +*/test.bats diff --git a/src/subprojects/packcc/tests/README.md b/src/subprojects/packcc/tests/README.md new file mode 100644 index 00000000..4f3eeacf --- /dev/null +++ b/src/subprojects/packcc/tests/README.md @@ -0,0 +1,87 @@ +# Testing PackCC + +## How to run the tests + +For running the tests, we assume you have `bats-core` and `uncrustify`. + +If you do not have `bats-core` installed, you can do it using your package manager or from its tarball: +``` +$ curl -L -o bats-core-1.2.1.tar.gz https://github.com/bats-core/bats-core/archive/v1.2.1.tar.gz && + tar zxvf bats-core-1.2.1.tar.gz && + cd bats-core-1.2.1 && + sudo ./install.sh /usr/local +``` + +If you do not have `uncrustify` installed, you can do it using your package manager or from its repository: +``` +$ git clone https://github.com/uncrustify/uncrustify && + cd uncrustify && + git checkout uncrustify-0.72.0 && + mkdir -p build && + cd build && + cmake .. && + make && + sudo make install +``` + +When you use MinGW-w64, `cmake` requires the options `-G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX=/usr/local`. + +After installing `bats-core-1.2.1` and `uncrustify`, you can run the tests using `tests/test.sh` script: +``` +$ ./test.sh + ✓ Testing basic.d - generation + ✓ Testing basic.d - compilation + ✓ Testing basic.d - run + ... + ✓ Testing strings.d - generation + ✓ Testing strings.d - compilation + ✓ Testing strings.d - run + ✓ Testing strings.d - run [utf8] + +19 tests, 0 failures, 1 skipped +``` + +The script passes all its arguments to `bats`, for example to run only some tests, +you can call it with `--filter `. To see all the available arguments, execute `tests/test.sh --help`. + +The behavior of the `test.sh` can also be influenced by environment variables: + - `PACKCC` - Path to a compiled `packcc` binary. If unset, the script will compile it before running the tests. + - `CC` - Compiler to use to compile `packcc` (if necessary) and the programs for testing. Defaults to `cc`. + +## How to write a generic test + +To create a new test, just follow these simple steps: + +1. Create a directory with suitable name, e.g.: `tests/sequence.d`. +2. Create a grammar file called `input.peg` in this directory. +3. Create one or more input files. The files must match the glob pattern `input*.txt`. +4. Create a file with expected output for each of the inputs. The names must match the input, + just replace "input" with "expected". E.g.: for `input-1.txt`, there must be `expected-1.txt`. + +Each test automatically performs three or more test cases: + +1. Generates a parser from the `input.peg` grammar. +2. Compiles the generated parser. +3. Runs the parser with specified inputs, comparing the outputs with the contents of the respective expected files. + +## How to write a customized test + +Sometimes the auto-generated test is not exactly what you need. In this case, you can simply create a customized test on your own: + +1. Create a directory with a suitable name, e.g.: `tests/sequence.d`. +2. Create one or more `*.bats` files in this directory. +3. Specify a custom test in the bats file. + +The test script will notice the customized files and will not generate a generic one. +However, you can still reuse as much of the common code as you want simply by loading `tests/utils.sh` +and calling the prepared functions. See [calc.d/calc.bats](calc.d/calc.bats) as an example. + +## How to skip a test input + +*Note: This paragraph applies only to automatically generated tests. For customized tests, +just add `skip` directive to your* `*.bats` *file as needed.* + +Sometimes it is useful to skip a test input, for example to avoid an input that triggers a known bug +that has not yet been fixed. To do so, simply rename the input file to `input*.skip.txt`. + +If you want to skip all test inputs in the directory, rename the grammar file to `input.skip.peg`. diff --git a/src/subprojects/packcc/tests/ascii.d/ascii.bats b/src/subprojects/packcc/tests/ascii.d/ascii.bats new file mode 100644 index 00000000..3d8197a1 --- /dev/null +++ b/src/subprojects/packcc/tests/ascii.d/ascii.bats @@ -0,0 +1,19 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing ascii.d - generation" { + PACKCC_OPTS=("--ascii") + test_generate +} + +@test "Testing ascii.d - check code" { + ! in_source "pcc_get_char_as_utf32" +} + +@test "Testing ascii.d - compilation" { + test_compile +} +@test "Testing ascii.d - run" { + run_for_input "ascii.d/input.txt" +} diff --git a/src/subprojects/packcc/tests/ascii.d/expected.txt b/src/subprojects/packcc/tests/ascii.d/expected.txt new file mode 100644 index 00000000..c2a2bdd5 --- /dev/null +++ b/src/subprojects/packcc/tests/ascii.d/expected.txt @@ -0,0 +1,4 @@ +This +is +a +test diff --git a/src/subprojects/packcc/tests/ascii.d/input.peg b/src/subprojects/packcc/tests/ascii.d/input.peg new file mode 100644 index 00000000..996750c4 --- /dev/null +++ b/src/subprojects/packcc/tests/ascii.d/input.peg @@ -0,0 +1,3 @@ +FILE <- WORD / SPACE +WORD <- [^ \r\n\t]+ { PRINT($0); } +SPACE <- [ \r\n\t]+ diff --git a/src/subprojects/packcc/tests/ascii.d/input.txt b/src/subprojects/packcc/tests/ascii.d/input.txt new file mode 100644 index 00000000..0527e6bd --- /dev/null +++ b/src/subprojects/packcc/tests/ascii.d/input.txt @@ -0,0 +1 @@ +This is a test diff --git a/src/subprojects/packcc/tests/ast-calc.d/ast-calc.bats b/src/subprojects/packcc/tests/ast-calc.d/ast-calc.bats new file mode 100644 index 00000000..f39b8f14 --- /dev/null +++ b/src/subprojects/packcc/tests/ast-calc.d/ast-calc.bats @@ -0,0 +1,15 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing ast-calc.d - generation" { + test_generate "$ROOTDIR/examples/ast-calc.peg" +} + +@test "Testing ast-calc.d - compilation" { + ${CC:-cc} ast-calc.d/parser.c -o ast-calc.d/parser +} + +@test "Testing ast-calc.d - run" { + run_for_input ast-calc.d/input.txt +} diff --git a/src/subprojects/packcc/tests/ast-calc.d/expected.txt b/src/subprojects/packcc/tests/ast-calc.d/expected.txt new file mode 100644 index 00000000..bc7ab02e --- /dev/null +++ b/src/subprojects/packcc/tests/ast-calc.d/expected.txt @@ -0,0 +1,26 @@ +binary: "+" + nullary: "1" + binary: "*" + nullary: "2" + binary: "+" + nullary: "3" + binary: "*" + nullary: "4" + binary: "+" + nullary: "5" + nullary: "6" +binary: "/" + binary: "*" + binary: "*" + binary: "*" + nullary: "5" + nullary: "6" + nullary: "7" + nullary: "8" + binary: "*" + binary: "*" + binary: "*" + nullary: "1" + nullary: "2" + nullary: "3" + nullary: "4" diff --git a/src/subprojects/packcc/tests/ast-calc.d/input.txt b/src/subprojects/packcc/tests/ast-calc.d/input.txt new file mode 100644 index 00000000..eb6a98d2 --- /dev/null +++ b/src/subprojects/packcc/tests/ast-calc.d/input.txt @@ -0,0 +1,2 @@ +1+2*(3+4*(5+6)) +5*6*7*8/(1*2*3*4) diff --git a/src/subprojects/packcc/tests/basic.d/expected.txt b/src/subprojects/packcc/tests/basic.d/expected.txt new file mode 100644 index 00000000..c2a2bdd5 --- /dev/null +++ b/src/subprojects/packcc/tests/basic.d/expected.txt @@ -0,0 +1,4 @@ +This +is +a +test diff --git a/src/subprojects/packcc/tests/basic.d/input.peg b/src/subprojects/packcc/tests/basic.d/input.peg new file mode 100644 index 00000000..996750c4 --- /dev/null +++ b/src/subprojects/packcc/tests/basic.d/input.peg @@ -0,0 +1,3 @@ +FILE <- WORD / SPACE +WORD <- [^ \r\n\t]+ { PRINT($0); } +SPACE <- [ \r\n\t]+ diff --git a/src/subprojects/packcc/tests/basic.d/input.txt b/src/subprojects/packcc/tests/basic.d/input.txt new file mode 100644 index 00000000..0527e6bd --- /dev/null +++ b/src/subprojects/packcc/tests/basic.d/input.txt @@ -0,0 +1 @@ +This is a test diff --git a/src/subprojects/packcc/tests/calc.d/calc.bats b/src/subprojects/packcc/tests/calc.d/calc.bats new file mode 100644 index 00000000..0814e957 --- /dev/null +++ b/src/subprojects/packcc/tests/calc.d/calc.bats @@ -0,0 +1,15 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing calc.d - generation" { + test_generate "$ROOTDIR/examples/calc.peg" +} + +@test "Testing calc.d - compilation" { + ${CC:-cc} calc.d/parser.c -o calc.d/parser +} + +@test "Testing calc.d - run" { + run_for_input calc.d/input.txt +} diff --git a/src/subprojects/packcc/tests/calc.d/expected.txt b/src/subprojects/packcc/tests/calc.d/expected.txt new file mode 100644 index 00000000..5683d42d --- /dev/null +++ b/src/subprojects/packcc/tests/calc.d/expected.txt @@ -0,0 +1,4 @@ +answer=2 +answer=6 +answer=4 +answer=-2 diff --git a/src/subprojects/packcc/tests/calc.d/input.txt b/src/subprojects/packcc/tests/calc.d/input.txt new file mode 100644 index 00000000..44e8a21b --- /dev/null +++ b/src/subprojects/packcc/tests/calc.d/input.txt @@ -0,0 +1,4 @@ +1+1 +2*3 +12 / (1+2) +24 / -4 / 3 diff --git a/src/subprojects/packcc/tests/captures.d/expected.txt b/src/subprojects/packcc/tests/captures.d/expected.txt new file mode 100644 index 00000000..6df15579 --- /dev/null +++ b/src/subprojects/packcc/tests/captures.d/expected.txt @@ -0,0 +1,7 @@ +0,11:capture all +12,19:capture +34,40:second +59,64:words +83,92:something +93,97:more 98,106:captures +116,121:again diff --git a/src/subprojects/packcc/tests/captures.d/input.peg b/src/subprojects/packcc/tests/captures.d/input.peg new file mode 100644 index 00000000..c4d1eac4 --- /dev/null +++ b/src/subprojects/packcc/tests/captures.d/input.peg @@ -0,0 +1,13 @@ +FILE <- (LINE '\n')* +LINE <- ALL / FIRST / SECOND / MULTI1 / MULTI2 / MORE / CAPTURED / UNKNOWN + +ALL <- <'capture' _ 'all'> { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); } +FIRST <- <'capture'> _ 'first' { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); } +SECOND <- 'capture' _ <'second'> { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); } +MULTI1 <- 'capture' _ 'multiple1' (_ <[a-z]+>)+ { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); } +MULTI2 <- 'capture' _ 'multiple2' (_ <[a-z]+> { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); })+ +MORE <- <'more'> _ <'captures'> { printf("%d,%d:%s %d,%d:%s\n", (int)$1s, (int)$1e, $1, (int)$2s, (int)$2e, $2); } +CAPTURED <- "captured" _ <[a-z]+> _ 'and' _ $1 { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); } + +UNKNOWN <- [^\n]+ { printf("ERROR: %s\n", $0); } +_ <- " " diff --git a/src/subprojects/packcc/tests/captures.d/input.txt b/src/subprojects/packcc/tests/captures.d/input.txt new file mode 100644 index 00000000..f69b8dde --- /dev/null +++ b/src/subprojects/packcc/tests/captures.d/input.txt @@ -0,0 +1,7 @@ +capture all +capture first +capture second +capture multiple1 words +capture multiple2 something +more captures +captured again and again diff --git a/src/subprojects/packcc/tests/character_classes_0.d/expected.txt b/src/subprojects/packcc/tests/character_classes_0.d/expected.txt new file mode 100644 index 00000000..cab35b66 --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_0.d/expected.txt @@ -0,0 +1,8 @@ +CLASS0: '^' +CLASS0: '-' +CLASS1: '\' +CLASS1: ']' +CLASS2: 'ぬ' +CLASS3: '𝓴' +CLASS4: 'J' +CLASS5: '7' diff --git a/src/subprojects/packcc/tests/character_classes_0.d/input.peg b/src/subprojects/packcc/tests/character_classes_0.d/input.peg new file mode 100644 index 00000000..8633e0b0 --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_0.d/input.peg @@ -0,0 +1,9 @@ +FILE <- TOKEN (_ TOKEN)* _* +TOKEN <- CLASS0 / CLASS1 / CLASS2 / CLASS3 / CLASS4 / CLASS5 +CLASS0 <- [\^a-z-] { printf("CLASS0: '%s'\n", $0); } +CLASS1 <- [\\\]] { printf("CLASS1: '%s'\n", $0); } +CLASS2 <- [-あ-ん] { printf("CLASS2: '%s'\n", $0); } +CLASS3 <- [𝓪-𝔃-] { printf("CLASS3: '%s'\n", $0); } +CLASS4 <- [^0-9] { printf("CLASS4: '%s'\n", $0); } +CLASS5 <- [^] { printf("CLASS5: '%s'\n", $0); } +_ <- ' ' / '\n' diff --git a/src/subprojects/packcc/tests/character_classes_0.d/input.txt b/src/subprojects/packcc/tests/character_classes_0.d/input.txt new file mode 100644 index 00000000..4a92f453 --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_0.d/input.txt @@ -0,0 +1 @@ +^ - \ ] ぬ 𝓴 J 7 diff --git a/src/subprojects/packcc/tests/character_classes_1.d/expected-utf8.txt b/src/subprojects/packcc/tests/character_classes_1.d/expected-utf8.txt new file mode 100644 index 00000000..6f5e7fab --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_1.d/expected-utf8.txt @@ -0,0 +1,3 @@ +UNICODE: '€' +UNICODE: '£' +ESCAPED: chr(10) diff --git a/src/subprojects/packcc/tests/character_classes_1.d/expected.txt b/src/subprojects/packcc/tests/character_classes_1.d/expected.txt new file mode 100644 index 00000000..d5a4b1ff --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_1.d/expected.txt @@ -0,0 +1,23 @@ +LOWER: 'a' +LOWER: 'b' +LOWER: 'c' +LOWER: 'z' +ESCAPED: chr(10) +UPPER: 'Z' +UPPER: 'Y' +UPPER: 'X' +UPPER: 'A' +ESCAPED: chr(10) +DIGIT: '4' +DIGIT: '5' +DIGIT: '6' +ESCAPED: chr(10) +SPACE: ' ' +ESCAPED: chr(9) +CARET: '^' +OTHER: '_' +OTHER: '-' +OTHER: '@' +SPECIAL: '/' +ESCAPED: '\' +ESCAPED: chr(10) diff --git a/src/subprojects/packcc/tests/character_classes_1.d/input-utf8.txt b/src/subprojects/packcc/tests/character_classes_1.d/input-utf8.txt new file mode 100644 index 00000000..396b819a --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_1.d/input-utf8.txt @@ -0,0 +1 @@ +€£ diff --git a/src/subprojects/packcc/tests/character_classes_1.d/input.peg b/src/subprojects/packcc/tests/character_classes_1.d/input.peg new file mode 100644 index 00000000..dd787af7 --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_1.d/input.peg @@ -0,0 +1,32 @@ +%source { + void print_esc(const char* type, const char* ch) { + if (strncmp(type, "UNICODE", 7) == 0) + printf("%s: '%s'\n", type, ch); + else if (*ch >= '\x20' && *ch < '\x7f') + printf("%s: '%c'\n", type, *ch); + else + printf("%s: chr(%u)\n", type, *ch); + } +} + +FILE <- (LOWER_LETTER / UPPER_LETTER / DIGIT / UNICODE / ESCAPED / CARET / SPACE / SPECIAL / OTHER)* + +# simple character class +LOWER_LETTER <- [a-z] { print_esc("LOWER", $0); } +# octal escapes (FIXME: octals do not work) +# UPPER_LETTER <- [\101-\132] { print_esc("UPPER", $0); } +UPPER_LETTER <- [A-Z] { print_esc("UPPER", $0); } +# hexadecimal escapes +DIGIT <- [\x30-\x39] { print_esc("DIGIT", $0); } +# some unicode chars +UNICODE <- [\u20AC\u00A3] { print_esc("UNICODE", $0); } +# other ANSI escapes +ESCAPED <- [\t\r\n\\\'\"] { print_esc("ESCAPED", $0); } +# caret +CARET <- [\^] { print_esc("CARET", $0); } +# negated set +SPECIAL <- [^-_@a-zA-Z0-9] { print_esc("SPECIAL", $0); } +# single character class +SPACE <- [ ] { print_esc("SPACE", $0); } +# catch non-matched +OTHER <- . { print_esc("OTHER", $0); } diff --git a/src/subprojects/packcc/tests/character_classes_1.d/input.txt b/src/subprojects/packcc/tests/character_classes_1.d/input.txt new file mode 100644 index 00000000..99d3f7dc --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_1.d/input.txt @@ -0,0 +1,4 @@ +abcz +ZYXA +456 + ^_-@/\ diff --git a/src/subprojects/packcc/tests/character_classes_2.d/expected.txt b/src/subprojects/packcc/tests/character_classes_2.d/expected.txt new file mode 100644 index 00000000..a301d418 --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_2.d/expected.txt @@ -0,0 +1,8 @@ +CLASS0: 'a-' +CLASS1: 'bb' +CLASS2: 'c+' +CLASS2: 'c-' +CLASS3: 'd+' +CLASS3: 'd-' +CLASS4: 'ee' +CLASS5: 'ff' diff --git a/src/subprojects/packcc/tests/character_classes_2.d/input.peg b/src/subprojects/packcc/tests/character_classes_2.d/input.peg new file mode 100644 index 00000000..cb2531df --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_2.d/input.peg @@ -0,0 +1,9 @@ +FILE <- TOKEN (_ TOKEN)* _* +TOKEN <- CLASS0 / CLASS1 / CLASS2 / CLASS3 / CLASS4 / CLASS5 +CLASS0 <- 'a' [-] { printf("CLASS0: '%s'\n", $0); } +CLASS1 <- 'b' [^-] { printf("CLASS1: '%s'\n", $0); } +CLASS2 <- 'c' [-+] { printf("CLASS2: '%s'\n", $0); } +CLASS3 <- 'd' [+-] { printf("CLASS3: '%s'\n", $0); } +CLASS4 <- 'e' [^-+] { printf("CLASS4: '%s'\n", $0); } +CLASS5 <- 'f' [^+-] { printf("CLASS5: '%s'\n", $0); } +_ <- ' ' / '\n' diff --git a/src/subprojects/packcc/tests/character_classes_2.d/input.txt b/src/subprojects/packcc/tests/character_classes_2.d/input.txt new file mode 100644 index 00000000..da7dc762 --- /dev/null +++ b/src/subprojects/packcc/tests/character_classes_2.d/input.txt @@ -0,0 +1 @@ +a- bb c+ c- d+ d- ee ff diff --git a/src/subprojects/packcc/tests/code_generation.d/generation.bats b/src/subprojects/packcc/tests/code_generation.d/generation.bats new file mode 100644 index 00000000..0364e70d --- /dev/null +++ b/src/subprojects/packcc/tests/code_generation.d/generation.bats @@ -0,0 +1,108 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing code_generation.d - generation" { + test_generate +} + +@test "Testing code_generation.d - compilation" { + ${CC:-cc} -I "$BATS_TEST_DIRNAME" "$BATS_TEST_DIRNAME/parser.c" "$BATS_TEST_DIRNAME/main.c" -o "$BATS_TEST_DIRNAME/parser" "$@" +} + +@test "Testing code_generation.d - earlyheader" { + in_header "EARLY HEADER ONLY" + ! in_source "EARLY HEADER ONLY" +} + +@test "Testing code_generation.d - earlycommon" { + in_header "EARLY HEADER AND SOURCE" + in_source "EARLY HEADER AND SOURCE" +} + +@test "Testing code_generation.d - earlysource" { + ! in_header "EARLY SOURCE ONLY" + in_source "EARLY SOURCE ONLY" +} + +@test "Testing code_generation.d - header" { + in_header "HEADER ONLY" + ! in_source "HEADER ONLY" +} + +@test "Testing code_generation.d - common" { + in_header "HEADER AND SOURCE" + in_source "HEADER AND SOURCE" +} + +@test "Testing code_generation.d - source" { + ! in_header "custom_function" + in_source "custom_function" +} + +@test "Testing code_generation.d - post-source" { + ! in_header "SOURCE AFTER GENERATED CODE" + in_source "SOURCE AFTER GENERATED CODE" +} + +@test "Testing code_generation.d - value" { + in_header "int my_parse(my_context_t *ctx, double *ret)" + in_source "int my_parse(my_context_t *ctx, double *ret)" +} + +@test "Testing code_generation.d - auxil" { + in_header "my_context_t *my_create(long auxil)" + in_source "my_context_t *my_create(long auxil)" + in_source "typedef long pcc_auxil_t" +} + +@test "Testing code_generation.d - prefix" { + in_header "typedef struct my_context_tag my_context_t" + in_header "my_context_t *my_create(long auxil)" + in_header "int my_parse(my_context_t *ctx, double *ret)" + in_header "void my_destroy(my_context_t *ctx)" + + in_source "my_context_t *my_create(long auxil)" + in_source "int my_parse(my_context_t *ctx, double *ret)" + in_source "void my_destroy(my_context_t *ctx)" + + ! in_header "pcc_" + ! in_source "pcc_context_t" + ! in_source "pcc_create" + ! in_source "pcc_parse" + ! in_source "pcc_destroy" +} + +@test "Testing code_generation.d - header ordering" { + EARLYHEADER=$(get_line "EARLY HEADER ONLY" parser.h) + EARLYCOMMON=$(get_line "EARLY HEADER AND SOURCE" parser.h) + IFNDEF=$(get_line "#ifndef PCC_INCLUDED_PARSER_H" parser.h) + HEADER=$(get_line "HEADER ONLY" parser.h) + COMMON=$(get_line "HEADER AND SOURCE" parser.h) + API=$(get_line "my_create" parser.h) + + [ "$EARLYHEADER" -lt "$EARLYCOMMON" ] + [ "$EARLYCOMMON" -lt "$IFNDEF" ] + [ "$HEADER" -lt "$COMMON" ] + [ "$COMMON" -lt "$API" ] +} + +@test "Testing code_generation.d - source ordering" { + EARLYSOURCE=$(get_line "EARLY SOURCE ONLY" parser.c) + EARLYCOMMON=$(get_line "EARLY HEADER AND SOURCE" parser.c) + STDINCLUDE=$(get_line '#include ' parser.c) + INCLUDE=$(get_line '#include "parser.h"' parser.c) + SOURCE=$(get_line "custom_function" parser.c) + COMMON=$(get_line "HEADER AND SOURCE" parser.c) + GENERATED_START=$(get_line "#define PCC_BUFFER_MIN_SIZE" parser.c) + GENERATED_END=$(get_line "my_destroy" parser.c) + POST_SOURCE=$(get_line "SOURCE AFTER GENERATED CODE" parser.c) + + [ "$EARLYSOURCE" -lt "$EARLYCOMMON" ] + [ "$EARLYCOMMON" -lt "$STDINCLUDE" ] + [ "$INCLUDE" -lt "$SOURCE" ] + [ "$SOURCE" -lt "$COMMON" ] + [ "$COMMON" -lt "$GENERATED_START" ] + [ "$GENERATED_START" -lt "$GENERATED_END" ] + [ "$GENERATED_END" -lt "$POST_SOURCE" ] +} diff --git a/src/subprojects/packcc/tests/code_generation.d/input.peg b/src/subprojects/packcc/tests/code_generation.d/input.peg new file mode 100644 index 00000000..88e79983 --- /dev/null +++ b/src/subprojects/packcc/tests/code_generation.d/input.peg @@ -0,0 +1,31 @@ +%header { /* HEADER ONLY */ } + +%source { + int custom_function(void) { + return 42; + } +} + +%common { + /* HEADER AND SOURCE */ +} + +%earlyheader { /* EARLY HEADER ONLY */ } + +%earlysource { /* EARLY SOURCE ONLY */ } + +%earlycommon { + /* EARLY HEADER AND SOURCE */ +} + +%value "double" + +%auxil "long" + +%prefix "my" + +FILE <- .* + +%% + +/* SOURCE AFTER GENERATED CODE */ diff --git a/src/subprojects/packcc/tests/code_generation.d/main.c b/src/subprojects/packcc/tests/code_generation.d/main.c new file mode 100644 index 00000000..017a996f --- /dev/null +++ b/src/subprojects/packcc/tests/code_generation.d/main.c @@ -0,0 +1,9 @@ +#include "parser.h" + +int main(int argc, char **argv) { + double ret; + my_context_t *ctx = my_create(0); + while (my_parse(ctx, &ret)); + my_destroy(ctx); + return 0; +} diff --git a/src/subprojects/packcc/tests/code_line_continuation.d/dump.bats b/src/subprojects/packcc/tests/code_line_continuation.d/dump.bats new file mode 100644 index 00000000..34a19b9e --- /dev/null +++ b/src/subprojects/packcc/tests/code_line_continuation.d/dump.bats @@ -0,0 +1,8 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing code_line_continuation.d - generation" { + run "$PACKCC" --debug -o "code_line_continuation.d/parser" "code_line_continuation.d/input.peg" 2>&1 + check_output "code_line_continuation.d/expected.txt" +} diff --git a/src/subprojects/packcc/tests/code_line_continuation.d/expected.txt b/src/subprojects/packcc/tests/code_line_continuation.d/expected.txt new file mode 100644 index 00000000..627a7a77 --- /dev/null +++ b/src/subprojects/packcc/tests/code_line_continuation.d/expected.txt @@ -0,0 +1,9 @@ +Rule(name:'rule', ref:0, vars.len:0, capts.len:0, codes.len:1) { + Sequence(max:2, len:2) { + Charclass(value:'null') + Action(index:0, code:{\n #define AAA /* {\n */ { \\\n aaa \"//\" /*\n {\n {\n */{ \"/*\"\n // bbb \\\n {\\\n {\n }, vars:none) + } +} +value_type: 'int' +auxil_type: 'void *' +prefix: 'pcc' diff --git a/src/subprojects/packcc/tests/code_line_continuation.d/input.peg b/src/subprojects/packcc/tests/code_line_continuation.d/input.peg new file mode 100644 index 00000000..6f85c061 --- /dev/null +++ b/src/subprojects/packcc/tests/code_line_continuation.d/input.peg @@ -0,0 +1,13 @@ +rule + <- . + { + #define AAA /* { + */ { \ + aaa "//" /* + { + { + */{ "/*" + // bbb \ + {\ + { + } diff --git a/src/subprojects/packcc/tests/debug_macro.d/expected.txt b/src/subprojects/packcc/tests/debug_macro.d/expected.txt new file mode 100644 index 00000000..c8f1dfdf --- /dev/null +++ b/src/subprojects/packcc/tests/debug_macro.d/expected.txt @@ -0,0 +1,64 @@ +Evaluating rule TOP @0 [A] + Evaluating rule RULE_A @0 [A] + Matched rule RULE_A @0 [Aaa] + Evaluating rule EOL @3 [ +] + Matched rule EOL @3 [ +] +Matched rule TOP @0 [Aaa +] +A: Aaa +Evaluating rule TOP @0 [B] + Evaluating rule RULE_A @0 [B] + Abandoning rule RULE_A @0 [] + Evaluating rule RULE_B @0 [B] + Evaluating rule RULE_B1 @0 [B] + Evaluating rule RULE_A @2 [C] + Abandoning rule RULE_A @2 [] + Abandoning rule RULE_B1 @0 [BB] + Evaluating rule RULE_B2 @0 [BBC] + Evaluating rule RULE_C @2 [C] + Evaluating rule RULE_A @5 [b] + Abandoning rule RULE_A @5 [] + Evaluating rule RULE_B @5 [b] + Evaluating rule RULE_B1 @5 [b] + Evaluating rule RULE_A @7 [C] + Abandoning rule RULE_A @7 [] + Abandoning rule RULE_B1 @5 [bb] + Evaluating rule RULE_B2 @5 [bbC] + Evaluating rule RULE_C @7 [C] + Evaluating rule RULE_A @9 [B] + Abandoning rule RULE_A @9 [] + Evaluating rule RULE_B @9 [B] + Evaluating rule RULE_B1 @9 [B] + Evaluating rule RULE_A @13 [ +] + Abandoning rule RULE_A @13 [] + Abandoning rule RULE_B1 @9 [Bbbb] + Evaluating rule RULE_B2 @9 [Bbbb +] + Evaluating rule RULE_C @13 [ +] + Abandoning rule RULE_C @13 [] + Matched rule RULE_B2 @9 [Bbbb] + Matched rule RULE_B @9 [Bbbb] + Matched rule RULE_C @7 [CCBbbb] + Matched rule RULE_B2 @5 [bbCCBbbb] + Matched rule RULE_B @5 [bbCCBbbb] + Matched rule RULE_C @2 [CccbbCCBbbb] + Matched rule RULE_B2 @0 [BBCccbbCCBbbb] + Matched rule RULE_B @0 [BBCccbbCCBbbb] + Evaluating rule EOL @13 [ +] + Matched rule EOL @13 [ +] +Matched rule TOP @0 [BBCccbbCCBbbb +] +B2: Bbbb +B: Bbbb +C: CCBbbb +B2: bbCCBbbb +B: bbCCBbbb +C: CccbbCCBbbb +B2: BBCccbbCCBbbb +B: BBCccbbCCBbbb diff --git a/src/subprojects/packcc/tests/debug_macro.d/input.peg b/src/subprojects/packcc/tests/debug_macro.d/input.peg new file mode 100644 index 00000000..dbc13d11 --- /dev/null +++ b/src/subprojects/packcc/tests/debug_macro.d/input.peg @@ -0,0 +1,14 @@ +%source { +static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" }; +#define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) \ + fprintf(stdout, "%*s%s %s @%zu [%.*s]\n", (int)((level) * 2), "", dbg_str[event], rule, pos, (int)(length), buffer) + /* NOTE: To guarantee the output order, stderr, which can lead a race condition with stdout, is not used. */ +} + +TOP <- (RULE_A / RULE_B) EOL +RULE_A <- [Aa]+ { PRINT_L("A", $0); } +RULE_B <- RULE_B1 / RULE_B2 { PRINT_L("B", $0); } +RULE_B1 <- [Bb]+ RULE_A { PRINT_L("B1", $0); } +RULE_B2 <- [Bb]+ RULE_C? { PRINT_L("B2", $0); } +RULE_C <- [Cc]+ (RULE_A / RULE_B) { PRINT_L("C", $0); } +EOL <- "\n" diff --git a/src/subprojects/packcc/tests/debug_macro.d/input.txt b/src/subprojects/packcc/tests/debug_macro.d/input.txt new file mode 100644 index 00000000..a7c07e63 --- /dev/null +++ b/src/subprojects/packcc/tests/debug_macro.d/input.txt @@ -0,0 +1,2 @@ +Aaa +BBCccbbCCBbbb diff --git a/src/subprojects/packcc/tests/dump.d/dump.bats b/src/subprojects/packcc/tests/dump.d/dump.bats new file mode 100644 index 00000000..d8ec8508 --- /dev/null +++ b/src/subprojects/packcc/tests/dump.d/dump.bats @@ -0,0 +1,8 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing dump.d - generation" { + run "$PACKCC" --debug -o "dump.d/parser" "$ROOTDIR/examples/calc.peg" 2>&1 + check_output "dump.d/expected.txt" +} diff --git a/src/subprojects/packcc/tests/dump.d/expected.txt b/src/subprojects/packcc/tests/dump.d/expected.txt new file mode 100644 index 00000000..33ebc733 --- /dev/null +++ b/src/subprojects/packcc/tests/dump.d/expected.txt @@ -0,0 +1,163 @@ +Rule(name:'statement', ref:0, vars.len:1, capts.len:0, codes.len:2) { + Alternate(max:2, len:2) { + Sequence(max:8, len:5) { + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'e', index:0, name:'expression', rule:'expression') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'(null)', index:void, name:'EOL', rule:'EOL') + Action(index:0, code:{ printf(\"answer=%d\\n\", e); }, vars: + 'e' + ) + } + Sequence(max:4, len:3) { + Quantity(min:0, max:-1) { + Sequence(max:2, len:2) { + Predicate(neg:1) { + Reference(var:'(null)', index:void, name:'EOL', rule:'EOL') + } + Charclass(value:'null') + } + } + Reference(var:'(null)', index:void, name:'EOL', rule:'EOL') + Action(index:1, code:{ printf(\"error\\n\"); }, vars:none) + } + } +} +Rule(name:'expression', ref:2, vars.len:1, capts.len:0, codes.len:1) { + Sequence(max:2, len:2) { + Reference(var:'e', index:0, name:'term', rule:'term') + Action(index:0, code:{ $$ = e; }, vars: + 'e' + ) + } +} +Rule(name:'term', ref:3, vars.len:3, capts.len:0, codes.len:3) { + Alternate(max:4, len:3) { + Sequence(max:8, len:6) { + Reference(var:'l', index:0, name:'term', rule:'term') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:'+') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'r', index:1, name:'factor', rule:'factor') + Action(index:0, code:{ $$ = l + r; }, vars: + 'l' + 'r' + ) + } + Sequence(max:8, len:6) { + Reference(var:'l', index:0, name:'term', rule:'term') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:'-') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'r', index:1, name:'factor', rule:'factor') + Action(index:1, code:{ $$ = l - r; }, vars: + 'l' + 'r' + ) + } + Sequence(max:2, len:2) { + Reference(var:'e', index:2, name:'factor', rule:'factor') + Action(index:2, code:{ $$ = e; }, vars: + 'e' + ) + } + } +} +Rule(name:'factor', ref:5, vars.len:3, capts.len:0, codes.len:3) { + Alternate(max:4, len:3) { + Sequence(max:8, len:6) { + Reference(var:'l', index:0, name:'factor', rule:'factor') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:'*') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'r', index:1, name:'unary', rule:'unary') + Action(index:0, code:{ $$ = l * r; }, vars: + 'l' + 'r' + ) + } + Sequence(max:8, len:6) { + Reference(var:'l', index:0, name:'factor', rule:'factor') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:'/') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'r', index:1, name:'unary', rule:'unary') + Action(index:1, code:{ $$ = l / r; }, vars: + 'l' + 'r' + ) + } + Sequence(max:2, len:2) { + Reference(var:'e', index:2, name:'unary', rule:'unary') + Action(index:2, code:{ $$ = e; }, vars: + 'e' + ) + } + } +} +Rule(name:'unary', ref:5, vars.len:1, capts.len:0, codes.len:3) { + Alternate(max:4, len:3) { + Sequence(max:4, len:4) { + String(value:'+') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'e', index:0, name:'unary', rule:'unary') + Action(index:0, code:{ $$ = +e; }, vars: + 'e' + ) + } + Sequence(max:4, len:4) { + String(value:'-') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'e', index:0, name:'unary', rule:'unary') + Action(index:1, code:{ $$ = -e; }, vars: + 'e' + ) + } + Sequence(max:2, len:2) { + Reference(var:'e', index:0, name:'primary', rule:'primary') + Action(index:2, code:{ $$ = e; }, vars: + 'e' + ) + } + } +} +Rule(name:'primary', ref:1, vars.len:1, capts.len:1, codes.len:2) { + Alternate(max:2, len:2) { + Sequence(max:2, len:2) { + Capture(index:0) { + Quantity(min:1, max:-1) { + Charclass(value:'0-9') + } + } + Action(index:0, code:{ $$ = atoi($1); }, vars: + $1 + ) + } + Sequence(max:8, len:6) { + String(value:'(') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'e', index:0, name:'expression', rule:'expression') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:')') + Action(index:1, code:{ $$ = e; }, vars: + 'e' + ) + } + } +} +Rule(name:'_', ref:14, vars.len:0, capts.len:0, codes.len:0) { + Quantity(min:0, max:-1) { + Charclass(value:' \t') + } +} +Rule(name:'EOL', ref:3, vars.len:0, capts.len:0, codes.len:0) { + Alternate(max:4, len:4) { + String(value:'\n') + String(value:'\r\n') + String(value:'\r') + String(value:';') + } +} +value_type: 'int' +auxil_type: 'void *' +prefix: 'calc' diff --git a/src/subprojects/packcc/tests/error_action.d/expected.txt b/src/subprojects/packcc/tests/error_action.d/expected.txt new file mode 100644 index 00000000..aaa2ddd6 --- /dev/null +++ b/src/subprojects/packcc/tests/error_action.d/expected.txt @@ -0,0 +1,8 @@ +E1 failed: 1B: +E2 failed: 1C:1 +E3 failed: 1D:12 +One of E[123] has failed: 2B: +One of E[123] has failed: 2C:1 +One of E[123] has failed: 2D:12 +1A:123 +2A:123 diff --git a/src/subprojects/packcc/tests/error_action.d/input.peg b/src/subprojects/packcc/tests/error_action.d/input.peg new file mode 100644 index 00000000..634a0be0 --- /dev/null +++ b/src/subprojects/packcc/tests/error_action.d/input.peg @@ -0,0 +1,17 @@ +FILE <- ((RULE1 / RULE2 / OTHER) '\n')* + +RULE1 <- "1" [A-Z] ":" + E1 ~{ printf("E1 failed: %s\n", $0); } + E2 ~{ printf("E2 failed: %s\n", $0); } + E3 ~{ printf("E3 failed: %s\n", $0); } + { PRINT($0); } + +RULE2 <- "2" [A-Z] ":" + (E1 E2 E3) ~{ printf("One of E[123] has failed: %s\n", $0); } + { PRINT($0); } + +E1 <- "1" +E2 <- "2" +E3 <- "3" + +OTHER <- [^\n]+ diff --git a/src/subprojects/packcc/tests/error_action.d/input.txt b/src/subprojects/packcc/tests/error_action.d/input.txt new file mode 100644 index 00000000..313475b2 --- /dev/null +++ b/src/subprojects/packcc/tests/error_action.d/input.txt @@ -0,0 +1,8 @@ +1A:123 +1B:023 +1C:1?3 +1D:124 +2A:123 +2B:023 +2C:1?3 +2D:124 diff --git a/src/subprojects/packcc/tests/escape_sequences.d/expected-hex-0.txt b/src/subprojects/packcc/tests/escape_sequences.d/expected-hex-0.txt new file mode 100644 index 00000000..652924c3 --- /dev/null +++ b/src/subprojects/packcc/tests/escape_sequences.d/expected-hex-0.txt @@ -0,0 +1 @@ +PackCC diff --git a/src/subprojects/packcc/tests/escape_sequences.d/expected-unicode-0.txt b/src/subprojects/packcc/tests/escape_sequences.d/expected-unicode-0.txt new file mode 100644 index 00000000..946c8a91 --- /dev/null +++ b/src/subprojects/packcc/tests/escape_sequences.d/expected-unicode-0.txt @@ -0,0 +1 @@ +構文解析 diff --git a/src/subprojects/packcc/tests/escape_sequences.d/expected-unicode-1.txt b/src/subprojects/packcc/tests/escape_sequences.d/expected-unicode-1.txt new file mode 100644 index 00000000..9c0ccc6a --- /dev/null +++ b/src/subprojects/packcc/tests/escape_sequences.d/expected-unicode-1.txt @@ -0,0 +1 @@ +𝓟𝓪𝓬𝓴𝓒𝓒 diff --git a/src/subprojects/packcc/tests/escape_sequences.d/input-hex-0.txt b/src/subprojects/packcc/tests/escape_sequences.d/input-hex-0.txt new file mode 100644 index 00000000..652924c3 --- /dev/null +++ b/src/subprojects/packcc/tests/escape_sequences.d/input-hex-0.txt @@ -0,0 +1 @@ +PackCC diff --git a/src/subprojects/packcc/tests/escape_sequences.d/input-unicode-0.txt b/src/subprojects/packcc/tests/escape_sequences.d/input-unicode-0.txt new file mode 100644 index 00000000..946c8a91 --- /dev/null +++ b/src/subprojects/packcc/tests/escape_sequences.d/input-unicode-0.txt @@ -0,0 +1 @@ +構文解析 diff --git a/src/subprojects/packcc/tests/escape_sequences.d/input-unicode-1.txt b/src/subprojects/packcc/tests/escape_sequences.d/input-unicode-1.txt new file mode 100644 index 00000000..9c0ccc6a --- /dev/null +++ b/src/subprojects/packcc/tests/escape_sequences.d/input-unicode-1.txt @@ -0,0 +1 @@ +𝓟𝓪𝓬𝓴𝓒𝓒 diff --git a/src/subprojects/packcc/tests/escape_sequences.d/input.peg b/src/subprojects/packcc/tests/escape_sequences.d/input.peg new file mode 100644 index 00000000..ad0439d1 --- /dev/null +++ b/src/subprojects/packcc/tests/escape_sequences.d/input.peg @@ -0,0 +1,6 @@ +FILE <- TOKEN (_ TOKEN)* _* +TOKEN <- (HEX0 / UNI0 / UNI1) { PRINT($0); } +HEX0 <- "\x50\x61\x63\x6b\x43\x43" +UNI0 <- "\u69CB\u6587\u89e3\u6790" +UNI1 <- "\uD835\udcdf\uD835\udcea\uD835\udcec\uD835\udcf4\uD835\udcd2\uD835\udcd2" +_ <- ' ' / '\n' diff --git a/src/subprojects/packcc/tests/import.d/.gitignore b/src/subprojects/packcc/tests/import.d/.gitignore new file mode 100644 index 00000000..b23b2a65 --- /dev/null +++ b/src/subprojects/packcc/tests/import.d/.gitignore @@ -0,0 +1,2 @@ +t_*/ +t_*.* diff --git a/src/subprojects/packcc/tests/import.d/check_line_number.py b/src/subprojects/packcc/tests/import.d/check_line_number.py new file mode 100644 index 00000000..51d8ad4e --- /dev/null +++ b/src/subprojects/packcc/tests/import.d/check_line_number.py @@ -0,0 +1,76 @@ +#!/usr/bin/python3 + +# Copyright (c) 2024 Arihiro Yoshida. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import sys +import os +import re + +def main(): + args = sys.argv + if len(args) < 3: + print('Too few arguments') + sys.exit(1) + optp = args.pop(1) if args[1] == '--only-pre' else '' + word = args.pop(1) + path = args.pop(1) + with open(path, 'r') as file: + text = file.read().split('\n') + for i, s in enumerate(text): + if s.find(word) >= 0: + break + if i >= len(text): + print('Keyword not found') + sys.exit(2) + if optp == '': + if i == 0 or i == len(text) - 1: + print('Keyword found in invalid line') + sys.exit(2) + m = re.search(r'^#line ([0-9]+) "(.*)"$', text[i + 1]) + if m is None: + print('#line directive not found one line after keyword') + sys.exit(2) + if int(m.group(1)) - 1 != i + 2: + print('#line directive with inconsistent line number') + sys.exit(2) + if m.group(2) != os.path.abspath(path): + print('#line directive with inconsistent file name') + sys.exit(2) + else: + if i == 0: + print('Keyword found in invalid line') + sys.exit(2) + m = re.search(r'^#line ([0-9]+) "(.*)"$', text[i - 1]) + if m is None: + print('#line directive not found one line before keyword') + sys.exit(2) + with open(m.group(2), 'r') as file: + text = file.read().split('\n') + j = int(m.group(1)) - 1 + if j < 0 or j >= len(text): + print('#line directive with invalid line number') + sys.exit(2) + if text[j].find(word) < 0: + print('#line directive with inconsistent line number') + sys.exit(2) + +if __name__ == '__main__': + main() diff --git a/src/subprojects/packcc/tests/import.d/import.bats b/src/subprojects/packcc/tests/import.d/import.bats new file mode 100644 index 00000000..0aa5ed34 --- /dev/null +++ b/src/subprojects/packcc/tests/import.d/import.bats @@ -0,0 +1,543 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +make_input() { + "${PYTHON:-python3}" "$BATS_TEST_DIRNAME/make_input.py" "$BATS_TEST_DIRNAME" "$1" "$2" "$3" "$4" "$5" "$6" +} + +make_all_inputs() { + make_input t_input.peg "t_imp_0" "" "t_imp_0.peg" "" "t_dir_1/t_imp_4.peg" + make_input t_imp_0.peg "t_imp_1" "" "t_imp_1.peg" "" "" + make_input t_imp_1.peg "t_imp_2" "" "" "" "t_imp_2.peg" + make_input t_dir_0/t_imp_2.peg "t_imp_3" "" "../t_dir_0/t_imp_3.peg" "" "t_imp_3.peg" + make_input t_dir_0/t_imp_3.peg "t_imp_4" "" "" "" "" + make_input t_dir_1/t_imp_4.peg "t_imp_5" "" "t_dir_1_0/../t_imp_5.peg" "" "t_imp_5.peg" + make_input t_dir_1/t_imp_5.peg "t_imp_6" "t_imp_6.peg" "../t_dir_1/t_dir_1_0/t_imp_7.peg" "" "" + make_input t_dir_1/t_dir_1_0/t_imp_6.peg "t_imp_7" "" "" "" "" + make_input t_dir_1/t_dir_1_0/t_imp_7.peg "t_imp_8" "t_imp_8.peg" "../t_imp_a.peg" "" "" + make_input t_dir_2/t_imp_8.peg "t_imp_9" "" "../t_dir_2/t_imp_9.peg" "" "t_imp_9.peg" + make_input t_dir_2/t_imp_9.peg "t_imp_a" "" "" "" "" + make_input t_dir_3/t_imp_a.peg "t_imp_b" "" "t_dir_3_0/../t_imp_b.peg" "" "t_imp_b.peg" + make_input t_dir_3/t_imp_b.peg "t_imp_c" "t_imp_c.peg" "../t_dir_3/t_dir_3_0/t_imp_d.peg" "" "" + make_input t_dir_3/t_dir_3_0/t_imp_c.peg "t_imp_d" "" "" "" "" + make_input t_dir_3/t_dir_3_0/t_imp_d.peg "" "" "" "t_imp_c.peg" "" +} + +@test "Testing import.d - generation" { + "$PACKCC" --debug -o "$BATS_TEST_DIRNAME/t_parser" "$BATS_TEST_DIRNAME/reference.peg" > "$BATS_TEST_DIRNAME/t_expected.txt" 2>&1 + make_all_inputs + export PCC_IMPORT_PATH=$BATS_TEST_DIRNAME/t_dir_2:$BATS_TEST_DIRNAME/t_dir_3/t_dir_3_0 + run "$PACKCC" -I "$BATS_TEST_DIRNAME/t_dir_0" -I "$BATS_TEST_DIRNAME/t_dir_1/t_dir_1_0" --debug --lines -o "$BATS_TEST_DIRNAME/parser" "$BATS_TEST_DIRNAME/t_input.peg" 2>&1 + check_output "$BATS_TEST_DIRNAME/t_expected.txt" +} + +@test "Testing import.d - header ordering" { + ! in_header ":t_input_EARLYSOURCE:" + ! in_header ":t_imp_0_EARLYSOURCE:" + ! in_header ":t_imp_1_EARLYSOURCE:" + ! in_header ":t_imp_2_EARLYSOURCE:" + ! in_header ":t_imp_3_EARLYSOURCE:" + ! in_header ":t_imp_4_EARLYSOURCE:" + ! in_header ":t_imp_5_EARLYSOURCE:" + ! in_header ":t_imp_6_EARLYSOURCE:" + ! in_header ":t_imp_7_EARLYSOURCE:" + ! in_header ":t_imp_8_EARLYSOURCE:" + ! in_header ":t_imp_9_EARLYSOURCE:" + ! in_header ":t_imp_a_EARLYSOURCE:" + ! in_header ":t_imp_b_EARLYSOURCE:" + ! in_header ":t_imp_c_EARLYSOURCE:" + ! in_header ":t_imp_d_EARLYSOURCE:" + ! in_header ":t_input_SOURCE:" + ! in_header ":t_imp_0_SOURCE:" + ! in_header ":t_imp_1_SOURCE:" + ! in_header ":t_imp_2_SOURCE:" + ! in_header ":t_imp_3_SOURCE:" + ! in_header ":t_imp_4_SOURCE:" + ! in_header ":t_imp_5_SOURCE:" + ! in_header ":t_imp_6_SOURCE:" + ! in_header ":t_imp_7_SOURCE:" + ! in_header ":t_imp_8_SOURCE:" + ! in_header ":t_imp_9_SOURCE:" + ! in_header ":t_imp_a_SOURCE:" + ! in_header ":t_imp_b_SOURCE:" + ! in_header ":t_imp_c_SOURCE:" + ! in_header ":t_imp_d_SOURCE:" + ! in_header ":t_input_CODE:" + ! in_header ":t_imp_0_CODE:" + ! in_header ":t_imp_1_CODE:" + ! in_header ":t_imp_2_CODE:" + ! in_header ":t_imp_3_CODE:" + ! in_header ":t_imp_4_CODE:" + ! in_header ":t_imp_5_CODE:" + ! in_header ":t_imp_6_CODE:" + ! in_header ":t_imp_7_CODE:" + ! in_header ":t_imp_8_CODE:" + ! in_header ":t_imp_9_CODE:" + ! in_header ":t_imp_a_CODE:" + ! in_header ":t_imp_b_CODE:" + ! in_header ":t_imp_c_CODE:" + ! in_header ":t_imp_d_CODE:" + L000=$(get_line ":t_input_EARLYHEADER:" parser.h) + L001=$(get_line ":t_input_EARLYCOMMON:" parser.h) + L002=$(get_line ":t_imp_0_EARLYHEADER:" parser.h) + L003=$(get_line ":t_imp_0_EARLYCOMMON:" parser.h) + L004=$(get_line ":t_imp_1_EARLYHEADER:" parser.h) + L005=$(get_line ":t_imp_1_EARLYCOMMON:" parser.h) + L006=$(get_line ":t_imp_2_EARLYHEADER:" parser.h) + L007=$(get_line ":t_imp_2_EARLYCOMMON:" parser.h) + L008=$(get_line ":t_imp_3_EARLYHEADER:" parser.h) + L009=$(get_line ":t_imp_3_EARLYCOMMON:" parser.h) + L010=$(get_line ":t_imp_4_EARLYHEADER:" parser.h) + L011=$(get_line ":t_imp_4_EARLYCOMMON:" parser.h) + L012=$(get_line ":t_imp_5_EARLYHEADER:" parser.h) + L013=$(get_line ":t_imp_5_EARLYCOMMON:" parser.h) + L014=$(get_line ":t_imp_6_EARLYHEADER:" parser.h) + L015=$(get_line ":t_imp_6_EARLYCOMMON:" parser.h) + L016=$(get_line ":t_imp_7_EARLYHEADER:" parser.h) + L017=$(get_line ":t_imp_7_EARLYCOMMON:" parser.h) + L018=$(get_line ":t_imp_8_EARLYHEADER:" parser.h) + L019=$(get_line ":t_imp_8_EARLYCOMMON:" parser.h) + L020=$(get_line ":t_imp_9_EARLYHEADER:" parser.h) + L021=$(get_line ":t_imp_9_EARLYCOMMON:" parser.h) + L022=$(get_line ":t_imp_a_EARLYHEADER:" parser.h) + L023=$(get_line ":t_imp_a_EARLYCOMMON:" parser.h) + L024=$(get_line ":t_imp_b_EARLYHEADER:" parser.h) + L025=$(get_line ":t_imp_b_EARLYCOMMON:" parser.h) + L026=$(get_line ":t_imp_c_EARLYHEADER:" parser.h) + L027=$(get_line ":t_imp_c_EARLYCOMMON:" parser.h) + L028=$(get_line ":t_imp_d_EARLYHEADER:" parser.h) + L029=$(get_line ":t_imp_d_EARLYCOMMON:" parser.h) + L099=$(get_line "#ifndef PCC_INCLUDED_PARSER_H" parser.h) + L100=$(get_line ":t_input_HEADER:" parser.h) + L101=$(get_line ":t_input_COMMON:" parser.h) + L102=$(get_line ":t_imp_0_HEADER:" parser.h) + L103=$(get_line ":t_imp_0_COMMON:" parser.h) + L104=$(get_line ":t_imp_1_HEADER:" parser.h) + L105=$(get_line ":t_imp_1_COMMON:" parser.h) + L106=$(get_line ":t_imp_2_HEADER:" parser.h) + L107=$(get_line ":t_imp_2_COMMON:" parser.h) + L108=$(get_line ":t_imp_3_HEADER:" parser.h) + L109=$(get_line ":t_imp_3_COMMON:" parser.h) + L110=$(get_line ":t_imp_4_HEADER:" parser.h) + L111=$(get_line ":t_imp_4_COMMON:" parser.h) + L112=$(get_line ":t_imp_5_HEADER:" parser.h) + L113=$(get_line ":t_imp_5_COMMON:" parser.h) + L114=$(get_line ":t_imp_6_HEADER:" parser.h) + L115=$(get_line ":t_imp_6_COMMON:" parser.h) + L116=$(get_line ":t_imp_7_HEADER:" parser.h) + L117=$(get_line ":t_imp_7_COMMON:" parser.h) + L118=$(get_line ":t_imp_8_HEADER:" parser.h) + L119=$(get_line ":t_imp_8_COMMON:" parser.h) + L120=$(get_line ":t_imp_9_HEADER:" parser.h) + L121=$(get_line ":t_imp_9_COMMON:" parser.h) + L122=$(get_line ":t_imp_a_HEADER:" parser.h) + L123=$(get_line ":t_imp_a_COMMON:" parser.h) + L124=$(get_line ":t_imp_b_HEADER:" parser.h) + L125=$(get_line ":t_imp_b_COMMON:" parser.h) + L126=$(get_line ":t_imp_c_HEADER:" parser.h) + L127=$(get_line ":t_imp_c_COMMON:" parser.h) + L128=$(get_line ":t_imp_d_HEADER:" parser.h) + L129=$(get_line ":t_imp_d_COMMON:" parser.h) + L199=$(get_line "pcc_create" parser.h) + [ "$L000" -lt "$L001" ] + [ "$L001" -lt "$L002" ] + [ "$L002" -lt "$L003" ] + [ "$L003" -lt "$L004" ] + [ "$L004" -lt "$L005" ] + [ "$L005" -lt "$L006" ] + [ "$L006" -lt "$L007" ] + [ "$L007" -lt "$L008" ] + [ "$L008" -lt "$L009" ] + [ "$L009" -lt "$L010" ] + [ "$L010" -lt "$L011" ] + [ "$L011" -lt "$L012" ] + [ "$L012" -lt "$L013" ] + [ "$L013" -lt "$L014" ] + [ "$L014" -lt "$L015" ] + [ "$L015" -lt "$L016" ] + [ "$L016" -lt "$L017" ] + [ "$L017" -lt "$L018" ] + [ "$L018" -lt "$L019" ] + [ "$L019" -lt "$L020" ] + [ "$L020" -lt "$L021" ] + [ "$L021" -lt "$L022" ] + [ "$L022" -lt "$L023" ] + [ "$L023" -lt "$L024" ] + [ "$L024" -lt "$L025" ] + [ "$L025" -lt "$L026" ] + [ "$L026" -lt "$L027" ] + [ "$L027" -lt "$L028" ] + [ "$L028" -lt "$L029" ] + [ "$L029" -lt "$L099" ] + [ "$L099" -lt "$L100" ] + [ "$L100" -lt "$L101" ] + [ "$L101" -lt "$L102" ] + [ "$L102" -lt "$L103" ] + [ "$L103" -lt "$L104" ] + [ "$L104" -lt "$L105" ] + [ "$L105" -lt "$L106" ] + [ "$L106" -lt "$L107" ] + [ "$L107" -lt "$L108" ] + [ "$L108" -lt "$L109" ] + [ "$L109" -lt "$L110" ] + [ "$L110" -lt "$L111" ] + [ "$L111" -lt "$L112" ] + [ "$L112" -lt "$L113" ] + [ "$L113" -lt "$L114" ] + [ "$L114" -lt "$L115" ] + [ "$L115" -lt "$L116" ] + [ "$L116" -lt "$L117" ] + [ "$L117" -lt "$L118" ] + [ "$L118" -lt "$L119" ] + [ "$L119" -lt "$L120" ] + [ "$L120" -lt "$L121" ] + [ "$L121" -lt "$L122" ] + [ "$L122" -lt "$L123" ] + [ "$L123" -lt "$L124" ] + [ "$L124" -lt "$L125" ] + [ "$L125" -lt "$L126" ] + [ "$L126" -lt "$L127" ] + [ "$L127" -lt "$L128" ] + [ "$L128" -lt "$L129" ] + [ "$L129" -lt "$L199" ] +} + +@test "Testing import.d - source ordering" { + ! in_source ":t_input_EARLYHEADER:" + ! in_source ":t_imp_0_EARLYHEADER:" + ! in_source ":t_imp_1_EARLYHEADER:" + ! in_source ":t_imp_2_EARLYHEADER:" + ! in_source ":t_imp_3_EARLYHEADER:" + ! in_source ":t_imp_4_EARLYHEADER:" + ! in_source ":t_imp_5_EARLYHEADER:" + ! in_source ":t_imp_6_EARLYHEADER:" + ! in_source ":t_imp_7_EARLYHEADER:" + ! in_source ":t_imp_8_EARLYHEADER:" + ! in_source ":t_imp_9_EARLYHEADER:" + ! in_source ":t_imp_a_EARLYHEADER:" + ! in_source ":t_imp_b_EARLYHEADER:" + ! in_source ":t_imp_c_EARLYHEADER:" + ! in_source ":t_imp_d_EARLYHEADER:" + ! in_source ":t_input_HEADER:" + ! in_source ":t_imp_0_HEADER:" + ! in_source ":t_imp_1_HEADER:" + ! in_source ":t_imp_2_HEADER:" + ! in_source ":t_imp_3_HEADER:" + ! in_source ":t_imp_4_HEADER:" + ! in_source ":t_imp_5_HEADER:" + ! in_source ":t_imp_6_HEADER:" + ! in_source ":t_imp_7_HEADER:" + ! in_source ":t_imp_8_HEADER:" + ! in_source ":t_imp_9_HEADER:" + ! in_source ":t_imp_a_HEADER:" + ! in_source ":t_imp_b_HEADER:" + ! in_source ":t_imp_c_HEADER:" + ! in_source ":t_imp_d_HEADER:" + L000=$(get_line ":t_input_EARLYSOURCE:" parser.c) + L001=$(get_line ":t_input_EARLYCOMMON:" parser.c) + L002=$(get_line ":t_imp_0_EARLYSOURCE:" parser.c) + L003=$(get_line ":t_imp_0_EARLYCOMMON:" parser.c) + L004=$(get_line ":t_imp_1_EARLYSOURCE:" parser.c) + L005=$(get_line ":t_imp_1_EARLYCOMMON:" parser.c) + L006=$(get_line ":t_imp_2_EARLYSOURCE:" parser.c) + L007=$(get_line ":t_imp_2_EARLYCOMMON:" parser.c) + L008=$(get_line ":t_imp_3_EARLYSOURCE:" parser.c) + L009=$(get_line ":t_imp_3_EARLYCOMMON:" parser.c) + L010=$(get_line ":t_imp_4_EARLYSOURCE:" parser.c) + L011=$(get_line ":t_imp_4_EARLYCOMMON:" parser.c) + L012=$(get_line ":t_imp_5_EARLYSOURCE:" parser.c) + L013=$(get_line ":t_imp_5_EARLYCOMMON:" parser.c) + L014=$(get_line ":t_imp_6_EARLYSOURCE:" parser.c) + L015=$(get_line ":t_imp_6_EARLYCOMMON:" parser.c) + L016=$(get_line ":t_imp_7_EARLYSOURCE:" parser.c) + L017=$(get_line ":t_imp_7_EARLYCOMMON:" parser.c) + L018=$(get_line ":t_imp_8_EARLYSOURCE:" parser.c) + L019=$(get_line ":t_imp_8_EARLYCOMMON:" parser.c) + L020=$(get_line ":t_imp_9_EARLYSOURCE:" parser.c) + L021=$(get_line ":t_imp_9_EARLYCOMMON:" parser.c) + L022=$(get_line ":t_imp_a_EARLYSOURCE:" parser.c) + L023=$(get_line ":t_imp_a_EARLYCOMMON:" parser.c) + L024=$(get_line ":t_imp_b_EARLYSOURCE:" parser.c) + L025=$(get_line ":t_imp_b_EARLYCOMMON:" parser.c) + L026=$(get_line ":t_imp_c_EARLYSOURCE:" parser.c) + L027=$(get_line ":t_imp_c_EARLYCOMMON:" parser.c) + L028=$(get_line ":t_imp_d_EARLYSOURCE:" parser.c) + L029=$(get_line ":t_imp_d_EARLYCOMMON:" parser.c) + L098=$(get_line '#include ' parser.c) + L099=$(get_line '#include "parser.h"' parser.c) + L100=$(get_line ":t_input_SOURCE:" parser.c) + L101=$(get_line ":t_input_COMMON:" parser.c) + L102=$(get_line ":t_imp_0_SOURCE:" parser.c) + L103=$(get_line ":t_imp_0_COMMON:" parser.c) + L104=$(get_line ":t_imp_1_SOURCE:" parser.c) + L105=$(get_line ":t_imp_1_COMMON:" parser.c) + L106=$(get_line ":t_imp_2_SOURCE:" parser.c) + L107=$(get_line ":t_imp_2_COMMON:" parser.c) + L108=$(get_line ":t_imp_3_SOURCE:" parser.c) + L109=$(get_line ":t_imp_3_COMMON:" parser.c) + L110=$(get_line ":t_imp_4_SOURCE:" parser.c) + L111=$(get_line ":t_imp_4_COMMON:" parser.c) + L112=$(get_line ":t_imp_5_SOURCE:" parser.c) + L113=$(get_line ":t_imp_5_COMMON:" parser.c) + L114=$(get_line ":t_imp_6_SOURCE:" parser.c) + L115=$(get_line ":t_imp_6_COMMON:" parser.c) + L116=$(get_line ":t_imp_7_SOURCE:" parser.c) + L117=$(get_line ":t_imp_7_COMMON:" parser.c) + L118=$(get_line ":t_imp_8_SOURCE:" parser.c) + L119=$(get_line ":t_imp_8_COMMON:" parser.c) + L120=$(get_line ":t_imp_9_SOURCE:" parser.c) + L121=$(get_line ":t_imp_9_COMMON:" parser.c) + L122=$(get_line ":t_imp_a_SOURCE:" parser.c) + L123=$(get_line ":t_imp_a_COMMON:" parser.c) + L124=$(get_line ":t_imp_b_SOURCE:" parser.c) + L125=$(get_line ":t_imp_b_COMMON:" parser.c) + L126=$(get_line ":t_imp_c_SOURCE:" parser.c) + L127=$(get_line ":t_imp_c_COMMON:" parser.c) + L128=$(get_line ":t_imp_d_SOURCE:" parser.c) + L129=$(get_line ":t_imp_d_COMMON:" parser.c) + L198=$(get_line "#define PCC_BUFFER_MIN_SIZE" parser.c) + L199=$(get_line "pcc_destroy" parser.c) + L200=$(get_line ":t_imp_3_CODE:" parser.c) + L201=$(get_line ":t_imp_2_CODE:" parser.c) + L202=$(get_line ":t_imp_1_CODE:" parser.c) + L203=$(get_line ":t_imp_0_CODE:" parser.c) + L204=$(get_line ":t_imp_6_CODE:" parser.c) + L205=$(get_line ":t_imp_9_CODE:" parser.c) + L206=$(get_line ":t_imp_8_CODE:" parser.c) + L207=$(get_line ":t_imp_c_CODE:" parser.c) + L208=$(get_line ":t_imp_d_CODE:" parser.c) + L209=$(get_line ":t_imp_b_CODE:" parser.c) + L210=$(get_line ":t_imp_a_CODE:" parser.c) + L211=$(get_line ":t_imp_7_CODE:" parser.c) + L212=$(get_line ":t_imp_5_CODE:" parser.c) + L213=$(get_line ":t_imp_4_CODE:" parser.c) + L214=$(get_line ":t_input_CODE:" parser.c) + [ "$L000" -lt "$L001" ] + [ "$L001" -lt "$L002" ] + [ "$L002" -lt "$L003" ] + [ "$L003" -lt "$L004" ] + [ "$L004" -lt "$L005" ] + [ "$L005" -lt "$L006" ] + [ "$L006" -lt "$L007" ] + [ "$L007" -lt "$L008" ] + [ "$L008" -lt "$L009" ] + [ "$L009" -lt "$L010" ] + [ "$L010" -lt "$L011" ] + [ "$L011" -lt "$L012" ] + [ "$L012" -lt "$L013" ] + [ "$L013" -lt "$L014" ] + [ "$L014" -lt "$L015" ] + [ "$L015" -lt "$L016" ] + [ "$L016" -lt "$L017" ] + [ "$L017" -lt "$L018" ] + [ "$L018" -lt "$L019" ] + [ "$L019" -lt "$L020" ] + [ "$L020" -lt "$L021" ] + [ "$L021" -lt "$L022" ] + [ "$L022" -lt "$L023" ] + [ "$L023" -lt "$L024" ] + [ "$L024" -lt "$L025" ] + [ "$L025" -lt "$L026" ] + [ "$L026" -lt "$L027" ] + [ "$L027" -lt "$L028" ] + [ "$L028" -lt "$L029" ] + [ "$L029" -lt "$L098" ] + [ "$L098" -lt "$L099" ] + [ "$L099" -lt "$L100" ] + [ "$L100" -lt "$L101" ] + [ "$L101" -lt "$L102" ] + [ "$L102" -lt "$L103" ] + [ "$L103" -lt "$L104" ] + [ "$L104" -lt "$L105" ] + [ "$L105" -lt "$L106" ] + [ "$L106" -lt "$L107" ] + [ "$L107" -lt "$L108" ] + [ "$L108" -lt "$L109" ] + [ "$L109" -lt "$L110" ] + [ "$L110" -lt "$L111" ] + [ "$L111" -lt "$L112" ] + [ "$L112" -lt "$L113" ] + [ "$L113" -lt "$L114" ] + [ "$L114" -lt "$L115" ] + [ "$L115" -lt "$L116" ] + [ "$L116" -lt "$L117" ] + [ "$L117" -lt "$L118" ] + [ "$L118" -lt "$L119" ] + [ "$L119" -lt "$L120" ] + [ "$L120" -lt "$L121" ] + [ "$L121" -lt "$L122" ] + [ "$L122" -lt "$L123" ] + [ "$L123" -lt "$L124" ] + [ "$L124" -lt "$L125" ] + [ "$L125" -lt "$L126" ] + [ "$L126" -lt "$L127" ] + [ "$L127" -lt "$L128" ] + [ "$L128" -lt "$L129" ] + [ "$L129" -lt "$L198" ] + [ "$L198" -lt "$L199" ] + [ "$L199" -lt "$L200" ] + [ "$L200" -lt "$L201" ] + [ "$L201" -lt "$L202" ] + [ "$L202" -lt "$L203" ] + [ "$L203" -lt "$L204" ] + [ "$L204" -lt "$L205" ] + [ "$L205" -lt "$L206" ] + [ "$L206" -lt "$L207" ] + [ "$L207" -lt "$L208" ] + [ "$L208" -lt "$L209" ] + [ "$L209" -lt "$L210" ] + [ "$L210" -lt "$L211" ] + [ "$L211" -lt "$L212" ] + [ "$L212" -lt "$L213" ] + [ "$L213" -lt "$L214" ] +} + +check_line_number() { + "${PYTHON:-python3}" "$BATS_TEST_DIRNAME/check_line_number.py" "$1" "$BATS_TEST_DIRNAME/$2" +} + +check_line_number_pre() { + "${PYTHON:-python3}" "$BATS_TEST_DIRNAME/check_line_number.py" --only-pre "$1" "$BATS_TEST_DIRNAME/$2" +} + +@test "Testing import.d - header line numbers" { + check_line_number ":t_input_EARLYHEADER:" parser.h + check_line_number ":t_input_EARLYCOMMON:" parser.h + check_line_number ":t_imp_0_EARLYHEADER:" parser.h + check_line_number ":t_imp_0_EARLYCOMMON:" parser.h + check_line_number ":t_imp_1_EARLYHEADER:" parser.h + check_line_number ":t_imp_1_EARLYCOMMON:" parser.h + check_line_number ":t_imp_2_EARLYHEADER:" parser.h + check_line_number ":t_imp_2_EARLYCOMMON:" parser.h + check_line_number ":t_imp_3_EARLYHEADER:" parser.h + check_line_number ":t_imp_3_EARLYCOMMON:" parser.h + check_line_number ":t_imp_4_EARLYHEADER:" parser.h + check_line_number ":t_imp_4_EARLYCOMMON:" parser.h + check_line_number ":t_imp_5_EARLYHEADER:" parser.h + check_line_number ":t_imp_5_EARLYCOMMON:" parser.h + check_line_number ":t_imp_6_EARLYHEADER:" parser.h + check_line_number ":t_imp_6_EARLYCOMMON:" parser.h + check_line_number ":t_imp_7_EARLYHEADER:" parser.h + check_line_number ":t_imp_7_EARLYCOMMON:" parser.h + check_line_number ":t_imp_8_EARLYHEADER:" parser.h + check_line_number ":t_imp_8_EARLYCOMMON:" parser.h + check_line_number ":t_imp_9_EARLYHEADER:" parser.h + check_line_number ":t_imp_9_EARLYCOMMON:" parser.h + check_line_number ":t_imp_a_EARLYHEADER:" parser.h + check_line_number ":t_imp_a_EARLYCOMMON:" parser.h + check_line_number ":t_imp_b_EARLYHEADER:" parser.h + check_line_number ":t_imp_b_EARLYCOMMON:" parser.h + check_line_number ":t_imp_c_EARLYHEADER:" parser.h + check_line_number ":t_imp_c_EARLYCOMMON:" parser.h + check_line_number ":t_imp_d_EARLYHEADER:" parser.h + check_line_number ":t_imp_d_EARLYCOMMON:" parser.h + check_line_number ":t_input_HEADER:" parser.h + check_line_number ":t_input_COMMON:" parser.h + check_line_number ":t_imp_0_HEADER:" parser.h + check_line_number ":t_imp_0_COMMON:" parser.h + check_line_number ":t_imp_1_HEADER:" parser.h + check_line_number ":t_imp_1_COMMON:" parser.h + check_line_number ":t_imp_2_HEADER:" parser.h + check_line_number ":t_imp_2_COMMON:" parser.h + check_line_number ":t_imp_3_HEADER:" parser.h + check_line_number ":t_imp_3_COMMON:" parser.h + check_line_number ":t_imp_4_HEADER:" parser.h + check_line_number ":t_imp_4_COMMON:" parser.h + check_line_number ":t_imp_5_HEADER:" parser.h + check_line_number ":t_imp_5_COMMON:" parser.h + check_line_number ":t_imp_6_HEADER:" parser.h + check_line_number ":t_imp_6_COMMON:" parser.h + check_line_number ":t_imp_7_HEADER:" parser.h + check_line_number ":t_imp_7_COMMON:" parser.h + check_line_number ":t_imp_8_HEADER:" parser.h + check_line_number ":t_imp_8_COMMON:" parser.h + check_line_number ":t_imp_9_HEADER:" parser.h + check_line_number ":t_imp_9_COMMON:" parser.h + check_line_number ":t_imp_a_HEADER:" parser.h + check_line_number ":t_imp_a_COMMON:" parser.h + check_line_number ":t_imp_b_HEADER:" parser.h + check_line_number ":t_imp_b_COMMON:" parser.h + check_line_number ":t_imp_c_HEADER:" parser.h + check_line_number ":t_imp_c_COMMON:" parser.h + check_line_number ":t_imp_d_HEADER:" parser.h + check_line_number ":t_imp_d_COMMON:" parser.h +} + +@test "Testing import.d - source line numbers" { + check_line_number ":t_input_EARLYSOURCE:" parser.c + check_line_number ":t_input_EARLYCOMMON:" parser.c + check_line_number ":t_imp_0_EARLYSOURCE:" parser.c + check_line_number ":t_imp_0_EARLYCOMMON:" parser.c + check_line_number ":t_imp_1_EARLYSOURCE:" parser.c + check_line_number ":t_imp_1_EARLYCOMMON:" parser.c + check_line_number ":t_imp_2_EARLYSOURCE:" parser.c + check_line_number ":t_imp_2_EARLYCOMMON:" parser.c + check_line_number ":t_imp_3_EARLYSOURCE:" parser.c + check_line_number ":t_imp_3_EARLYCOMMON:" parser.c + check_line_number ":t_imp_4_EARLYSOURCE:" parser.c + check_line_number ":t_imp_4_EARLYCOMMON:" parser.c + check_line_number ":t_imp_5_EARLYSOURCE:" parser.c + check_line_number ":t_imp_5_EARLYCOMMON:" parser.c + check_line_number ":t_imp_6_EARLYSOURCE:" parser.c + check_line_number ":t_imp_6_EARLYCOMMON:" parser.c + check_line_number ":t_imp_7_EARLYSOURCE:" parser.c + check_line_number ":t_imp_7_EARLYCOMMON:" parser.c + check_line_number ":t_imp_8_EARLYSOURCE:" parser.c + check_line_number ":t_imp_8_EARLYCOMMON:" parser.c + check_line_number ":t_imp_9_EARLYSOURCE:" parser.c + check_line_number ":t_imp_9_EARLYCOMMON:" parser.c + check_line_number ":t_imp_a_EARLYSOURCE:" parser.c + check_line_number ":t_imp_a_EARLYCOMMON:" parser.c + check_line_number ":t_imp_b_EARLYSOURCE:" parser.c + check_line_number ":t_imp_b_EARLYCOMMON:" parser.c + check_line_number ":t_imp_c_EARLYSOURCE:" parser.c + check_line_number ":t_imp_c_EARLYCOMMON:" parser.c + check_line_number ":t_imp_d_EARLYSOURCE:" parser.c + check_line_number ":t_imp_d_EARLYCOMMON:" parser.c + check_line_number ":t_input_SOURCE:" parser.c + check_line_number ":t_input_COMMON:" parser.c + check_line_number ":t_imp_0_SOURCE:" parser.c + check_line_number ":t_imp_0_COMMON:" parser.c + check_line_number ":t_imp_1_SOURCE:" parser.c + check_line_number ":t_imp_1_COMMON:" parser.c + check_line_number ":t_imp_2_SOURCE:" parser.c + check_line_number ":t_imp_2_COMMON:" parser.c + check_line_number ":t_imp_3_SOURCE:" parser.c + check_line_number ":t_imp_3_COMMON:" parser.c + check_line_number ":t_imp_4_SOURCE:" parser.c + check_line_number ":t_imp_4_COMMON:" parser.c + check_line_number ":t_imp_5_SOURCE:" parser.c + check_line_number ":t_imp_5_COMMON:" parser.c + check_line_number ":t_imp_6_SOURCE:" parser.c + check_line_number ":t_imp_6_COMMON:" parser.c + check_line_number ":t_imp_7_SOURCE:" parser.c + check_line_number ":t_imp_7_COMMON:" parser.c + check_line_number ":t_imp_8_SOURCE:" parser.c + check_line_number ":t_imp_8_COMMON:" parser.c + check_line_number ":t_imp_9_SOURCE:" parser.c + check_line_number ":t_imp_9_COMMON:" parser.c + check_line_number ":t_imp_a_SOURCE:" parser.c + check_line_number ":t_imp_a_COMMON:" parser.c + check_line_number ":t_imp_b_SOURCE:" parser.c + check_line_number ":t_imp_b_COMMON:" parser.c + check_line_number ":t_imp_c_SOURCE:" parser.c + check_line_number ":t_imp_c_COMMON:" parser.c + check_line_number ":t_imp_d_SOURCE:" parser.c + check_line_number ":t_imp_d_COMMON:" parser.c + check_line_number_pre ":t_imp_3_CODE:" parser.c + check_line_number_pre ":t_imp_2_CODE:" parser.c + check_line_number_pre ":t_imp_1_CODE:" parser.c + check_line_number_pre ":t_imp_0_CODE:" parser.c + check_line_number_pre ":t_imp_6_CODE:" parser.c + check_line_number_pre ":t_imp_9_CODE:" parser.c + check_line_number_pre ":t_imp_8_CODE:" parser.c + check_line_number_pre ":t_imp_c_CODE:" parser.c + check_line_number_pre ":t_imp_d_CODE:" parser.c + check_line_number_pre ":t_imp_b_CODE:" parser.c + check_line_number_pre ":t_imp_a_CODE:" parser.c + check_line_number_pre ":t_imp_7_CODE:" parser.c + check_line_number_pre ":t_imp_5_CODE:" parser.c + check_line_number_pre ":t_imp_4_CODE:" parser.c + check_line_number_pre ":t_input_CODE:" parser.c +} diff --git a/src/subprojects/packcc/tests/import.d/make_input.py b/src/subprojects/packcc/tests/import.d/make_input.py new file mode 100644 index 00000000..69a65ce3 --- /dev/null +++ b/src/subprojects/packcc/tests/import.d/make_input.py @@ -0,0 +1,48 @@ +#!/usr/bin/python3 + +# Copyright (c) 2024 Arihiro Yoshida. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import sys +import os +import re + +def main(): + args = sys.argv + if len(args) < 4: + print('Too few arguments') + sys.exit(1) + root = args.pop(1) + path = args.pop(1) + more = args.pop(1) + os.makedirs(os.path.dirname(root + '/' + path), exist_ok=True) + id = re.sub(r'[^_a-zA-Z0-9]', '_', re.sub(r'\.peg$', '', os.path.basename(path))) + with open(root + '/template.peg', 'r') as file: + text = file.read() + text = text.replace('${ID}', id + '_') + text = text.replace('${MORE}', ' / ' + more + '_FILE' if more != '' else '') + for i in range(4): + imp = args.pop(1) if len(args) > 1 else '' + text = text.replace('${IMPORT_' + str(i) + '}', '%import "' + imp + '"' if imp != '' else '') + with open(root + '/' + path, 'w', newline='\n') as file: + file.write(text) + +if __name__ == '__main__': + main() diff --git a/src/subprojects/packcc/tests/import.d/reference.peg b/src/subprojects/packcc/tests/import.d/reference.peg new file mode 100644 index 00000000..f57b8c50 --- /dev/null +++ b/src/subprojects/packcc/tests/import.d/reference.peg @@ -0,0 +1,526 @@ +%header { /* :t_input_HEADER: */ } + +%source { + /* :t_input_SOURCE: */ +} + +%common { + /* :t_input_COMMON: */ +} + +%earlyheader { /* :t_input_EARLYHEADER: */ } + +%earlysource { /* :t_input_EARLYSOURCE: */ } + +%earlycommon { + /* :t_input_EARLYCOMMON: */ +} + +t_input_FILE + <- t_input_RULE1 + { + /* :t_input_RULE1: */ + } + / t_input_RULE2 + { /* :t_input_RULE2: */ } + / t_input_RULE3 { /* :t_input_RULE3: */ } + / t_imp_0_FILE + +t_input_RULE1 <- '1' + +%header { /* :t_imp_0_HEADER: */ } + +%source { + /* :t_imp_0_SOURCE: */ +} + +%common { + /* :t_imp_0_COMMON: */ +} + +%earlyheader { /* :t_imp_0_EARLYHEADER: */ } + +%earlysource { /* :t_imp_0_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_0_EARLYCOMMON: */ +} + +t_imp_0_FILE + <- t_imp_0_RULE1 + { + /* :t_imp_0_RULE1: */ + } + / t_imp_0_RULE2 + { /* :t_imp_0_RULE2: */ } + / t_imp_0_RULE3 { /* :t_imp_0_RULE3: */ } + / t_imp_1_FILE + +t_imp_0_RULE1 <- '1' + +%header { /* :t_imp_1_HEADER: */ } + +%source { + /* :t_imp_1_SOURCE: */ +} + +%common { + /* :t_imp_1_COMMON: */ +} + +%earlyheader { /* :t_imp_1_EARLYHEADER: */ } + +%earlysource { /* :t_imp_1_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_1_EARLYCOMMON: */ +} + +t_imp_1_FILE + <- t_imp_1_RULE1 + { + /* :t_imp_1_RULE1: */ + } + / t_imp_1_RULE2 + { /* :t_imp_1_RULE2: */ } + / t_imp_1_RULE3 { /* :t_imp_1_RULE3: */ } + / t_imp_2_FILE + +t_imp_1_RULE1 <- '1' + +t_imp_1_RULE2 <- '2' + +t_imp_1_RULE3 <- '3' + +%header { /* :t_imp_2_HEADER: */ } + +%source { + /* :t_imp_2_SOURCE: */ +} + +%common { + /* :t_imp_2_COMMON: */ +} + +%earlyheader { /* :t_imp_2_EARLYHEADER: */ } + +%earlysource { /* :t_imp_2_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_2_EARLYCOMMON: */ +} + +t_imp_2_FILE + <- t_imp_2_RULE1 + { + /* :t_imp_2_RULE1: */ + } + / t_imp_2_RULE2 + { /* :t_imp_2_RULE2: */ } + / t_imp_2_RULE3 { /* :t_imp_2_RULE3: */ } + / t_imp_3_FILE + +t_imp_2_RULE1 <- '1' + +%header { /* :t_imp_3_HEADER: */ } + +%source { + /* :t_imp_3_SOURCE: */ +} + +%common { + /* :t_imp_3_COMMON: */ +} + +%earlyheader { /* :t_imp_3_EARLYHEADER: */ } + +%earlysource { /* :t_imp_3_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_3_EARLYCOMMON: */ +} + +t_imp_3_FILE + <- t_imp_3_RULE1 + { + /* :t_imp_3_RULE1: */ + } + / t_imp_3_RULE2 + { /* :t_imp_3_RULE2: */ } + / t_imp_3_RULE3 { /* :t_imp_3_RULE3: */ } + / t_imp_4_FILE + +t_imp_3_RULE1 <- '1' + +t_imp_3_RULE2 <- '2' + +t_imp_3_RULE3 <- '3' + +t_imp_2_RULE2 <- '2' + +t_imp_2_RULE3 <- '3' + +t_imp_0_RULE2 <- '2' + +t_imp_0_RULE3 <- '3' + + +t_input_RULE2 <- '2' + +t_input_RULE3 <- '3' + +%header { /* :t_imp_4_HEADER: */ } + +%source { + /* :t_imp_4_SOURCE: */ +} + +%common { + /* :t_imp_4_COMMON: */ +} + +%earlyheader { /* :t_imp_4_EARLYHEADER: */ } + +%earlysource { /* :t_imp_4_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_4_EARLYCOMMON: */ +} + +t_imp_4_FILE + <- t_imp_4_RULE1 + { + /* :t_imp_4_RULE1: */ + } + / t_imp_4_RULE2 + { /* :t_imp_4_RULE2: */ } + / t_imp_4_RULE3 { /* :t_imp_4_RULE3: */ } + / t_imp_5_FILE + +t_imp_4_RULE1 <- '1' + +%header { /* :t_imp_5_HEADER: */ } + +%source { + /* :t_imp_5_SOURCE: */ +} + +%common { + /* :t_imp_5_COMMON: */ +} + +%earlyheader { /* :t_imp_5_EARLYHEADER: */ } + +%earlysource { /* :t_imp_5_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_5_EARLYCOMMON: */ +} + +t_imp_5_FILE + <- t_imp_5_RULE1 + { + /* :t_imp_5_RULE1: */ + } + / t_imp_5_RULE2 + { /* :t_imp_5_RULE2: */ } + / t_imp_5_RULE3 { /* :t_imp_5_RULE3: */ } + / t_imp_6_FILE + +%header { /* :t_imp_6_HEADER: */ } + +%source { + /* :t_imp_6_SOURCE: */ +} + +%common { + /* :t_imp_6_COMMON: */ +} + +%earlyheader { /* :t_imp_6_EARLYHEADER: */ } + +%earlysource { /* :t_imp_6_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_6_EARLYCOMMON: */ +} + +t_imp_6_FILE + <- t_imp_6_RULE1 + { + /* :t_imp_6_RULE1: */ + } + / t_imp_6_RULE2 + { /* :t_imp_6_RULE2: */ } + / t_imp_6_RULE3 { /* :t_imp_6_RULE3: */ } + / t_imp_7_FILE + +t_imp_6_RULE1 <- '1' + +t_imp_6_RULE2 <- '2' + +t_imp_6_RULE3 <- '3' + +t_imp_5_RULE1 <- '1' + +%header { /* :t_imp_7_HEADER: */ } + +%source { + /* :t_imp_7_SOURCE: */ +} + +%common { + /* :t_imp_7_COMMON: */ +} + +%earlyheader { /* :t_imp_7_EARLYHEADER: */ } + +%earlysource { /* :t_imp_7_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_7_EARLYCOMMON: */ +} + +t_imp_7_FILE + <- t_imp_7_RULE1 + { + /* :t_imp_7_RULE1: */ + } + / t_imp_7_RULE2 + { /* :t_imp_7_RULE2: */ } + / t_imp_7_RULE3 { /* :t_imp_7_RULE3: */ } + / t_imp_8_FILE + +%header { /* :t_imp_8_HEADER: */ } + +%source { + /* :t_imp_8_SOURCE: */ +} + +%common { + /* :t_imp_8_COMMON: */ +} + +%earlyheader { /* :t_imp_8_EARLYHEADER: */ } + +%earlysource { /* :t_imp_8_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_8_EARLYCOMMON: */ +} + +t_imp_8_FILE + <- t_imp_8_RULE1 + { + /* :t_imp_8_RULE1: */ + } + / t_imp_8_RULE2 + { /* :t_imp_8_RULE2: */ } + / t_imp_8_RULE3 { /* :t_imp_8_RULE3: */ } + / t_imp_9_FILE + +t_imp_8_RULE1 <- '1' + +%header { /* :t_imp_9_HEADER: */ } + +%source { + /* :t_imp_9_SOURCE: */ +} + +%common { + /* :t_imp_9_COMMON: */ +} + +%earlyheader { /* :t_imp_9_EARLYHEADER: */ } + +%earlysource { /* :t_imp_9_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_9_EARLYCOMMON: */ +} + +t_imp_9_FILE + <- t_imp_9_RULE1 + { + /* :t_imp_9_RULE1: */ + } + / t_imp_9_RULE2 + { /* :t_imp_9_RULE2: */ } + / t_imp_9_RULE3 { /* :t_imp_9_RULE3: */ } + / t_imp_a_FILE + +t_imp_9_RULE1 <- '1' + +t_imp_9_RULE2 <- '2' + +t_imp_9_RULE3 <- '3' + +t_imp_8_RULE2 <- '2' + +t_imp_8_RULE3 <- '3' + +t_imp_7_RULE1 <- '1' + +%header { /* :t_imp_a_HEADER: */ } + +%source { + /* :t_imp_a_SOURCE: */ +} + +%common { + /* :t_imp_a_COMMON: */ +} + +%earlyheader { /* :t_imp_a_EARLYHEADER: */ } + +%earlysource { /* :t_imp_a_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_a_EARLYCOMMON: */ +} + +t_imp_a_FILE + <- t_imp_a_RULE1 + { + /* :t_imp_a_RULE1: */ + } + / t_imp_a_RULE2 + { /* :t_imp_a_RULE2: */ } + / t_imp_a_RULE3 { /* :t_imp_a_RULE3: */ } + / t_imp_b_FILE + +t_imp_a_RULE1 <- '1' + +%header { /* :t_imp_b_HEADER: */ } + +%source { + /* :t_imp_b_SOURCE: */ +} + +%common { + /* :t_imp_b_COMMON: */ +} + +%earlyheader { /* :t_imp_b_EARLYHEADER: */ } + +%earlysource { /* :t_imp_b_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_b_EARLYCOMMON: */ +} + +t_imp_b_FILE + <- t_imp_b_RULE1 + { + /* :t_imp_b_RULE1: */ + } + / t_imp_b_RULE2 + { /* :t_imp_b_RULE2: */ } + / t_imp_b_RULE3 { /* :t_imp_b_RULE3: */ } + / t_imp_c_FILE + +%header { /* :t_imp_c_HEADER: */ } + +%source { + /* :t_imp_c_SOURCE: */ +} + +%common { + /* :t_imp_c_COMMON: */ +} + +%earlyheader { /* :t_imp_c_EARLYHEADER: */ } + +%earlysource { /* :t_imp_c_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_c_EARLYCOMMON: */ +} + +t_imp_c_FILE + <- t_imp_c_RULE1 + { + /* :t_imp_c_RULE1: */ + } + / t_imp_c_RULE2 + { /* :t_imp_c_RULE2: */ } + / t_imp_c_RULE3 { /* :t_imp_c_RULE3: */ } + / t_imp_d_FILE + +t_imp_c_RULE1 <- '1' + +t_imp_c_RULE2 <- '2' + +t_imp_c_RULE3 <- '3' + +t_imp_b_RULE1 <- '1' + +%header { /* :t_imp_d_HEADER: */ } + +%source { + /* :t_imp_d_SOURCE: */ +} + +%common { + /* :t_imp_d_COMMON: */ +} + +%earlyheader { /* :t_imp_d_EARLYHEADER: */ } + +%earlysource { /* :t_imp_d_EARLYSOURCE: */ } + +%earlycommon { + /* :t_imp_d_EARLYCOMMON: */ +} + +t_imp_d_FILE + <- t_imp_d_RULE1 + { + /* :t_imp_d_RULE1: */ + } + / t_imp_d_RULE2 + { /* :t_imp_d_RULE2: */ } + / t_imp_d_RULE3 { /* :t_imp_d_RULE3: */ } + +t_imp_d_RULE1 <- '1' + +t_imp_d_RULE2 <- '2' + +t_imp_d_RULE3 <- '3' + +t_imp_b_RULE2 <- '2' + +t_imp_b_RULE3 <- '3' + +t_imp_a_RULE2 <- '2' + +t_imp_a_RULE3 <- '3' + +t_imp_7_RULE2 <- '2' + +t_imp_7_RULE3 <- '3' + +t_imp_5_RULE2 <- '2' + +t_imp_5_RULE3 <- '3' + +t_imp_4_RULE2 <- '2' + +t_imp_4_RULE3 <- '3' + +%% +/* :t_imp_3_CODE: */ +/* :t_imp_2_CODE: */ +/* :t_imp_1_CODE: */ +/* :t_imp_0_CODE: */ +/* :t_imp_6_CODE: */ +/* :t_imp_9_CODE: */ +/* :t_imp_8_CODE: */ +/* :t_imp_c_CODE: */ +/* :t_imp_d_CODE: */ +/* :t_imp_b_CODE: */ +/* :t_imp_a_CODE: */ +/* :t_imp_7_CODE: */ +/* :t_imp_5_CODE: */ +/* :t_imp_4_CODE: */ +/* :t_input_CODE: */ diff --git a/src/subprojects/packcc/tests/import.d/template.peg b/src/subprojects/packcc/tests/import.d/template.peg new file mode 100644 index 00000000..9fc123db --- /dev/null +++ b/src/subprojects/packcc/tests/import.d/template.peg @@ -0,0 +1,37 @@ +%header { /* :${ID}HEADER: */ } + +%source { + /* :${ID}SOURCE: */ +} + +%common { + /* :${ID}COMMON: */ +} + +%earlyheader { /* :${ID}EARLYHEADER: */ } + +%earlysource { /* :${ID}EARLYSOURCE: */ } + +%earlycommon { + /* :${ID}EARLYCOMMON: */ +} + +${ID}FILE + <- ${ID}RULE1 + { + /* :${ID}RULE1: */ + } + / ${ID}RULE2 + { /* :${ID}RULE2: */ } + / ${ID}RULE3 { /* :${ID}RULE3: */ } +${MORE} +${IMPORT_0} +${ID}RULE1 <- '1' +${IMPORT_1} +${ID}RULE2 <- '2' +${IMPORT_2} +${ID}RULE3 <- '3' +${IMPORT_3} + +%% +/* :${ID}CODE: */ diff --git a/src/subprojects/packcc/tests/import_char.d/import_char.bats b/src/subprojects/packcc/tests/import_char.d/import_char.bats new file mode 100644 index 00000000..f49f6a61 --- /dev/null +++ b/src/subprojects/packcc/tests/import_char.d/import_char.bats @@ -0,0 +1,8 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing import_char.d - generation" { + run test_generate + [ "$status" -eq 0 ] +} diff --git a/src/subprojects/packcc/tests/import_char.d/input.peg b/src/subprojects/packcc/tests/import_char.d/input.peg new file mode 100644 index 00000000..8d92e53d --- /dev/null +++ b/src/subprojects/packcc/tests/import_char.d/input.peg @@ -0,0 +1,3 @@ +%import "char/ascii_character_group.peg" +%import "char/unicode_general_category.peg" +%import "char/unicode_derived_core.peg" diff --git a/src/subprojects/packcc/tests/issue_28.d/expected.txt b/src/subprojects/packcc/tests/issue_28.d/expected.txt new file mode 100644 index 00000000..79775f6c --- /dev/null +++ b/src/subprojects/packcc/tests/issue_28.d/expected.txt @@ -0,0 +1,3 @@ +A; + +Syntax error diff --git a/src/subprojects/packcc/tests/issue_28.d/input.peg b/src/subprojects/packcc/tests/issue_28.d/input.peg new file mode 100644 index 00000000..01d0ea84 --- /dev/null +++ b/src/subprojects/packcc/tests/issue_28.d/input.peg @@ -0,0 +1,9 @@ +%source { +#define PCC_ERROR(auxil) \ + do { printf("Syntax error\n"); exit(1); } while (0) + /* NOTE: To guarantee the output order, stderr, which can lead a race condition with stdout, is not used. */ +} + +top <- rule+ { PRINT($0); } +rule <- "A;" / _ +_ <- [ \n]* diff --git a/src/subprojects/packcc/tests/issue_28.d/input.txt b/src/subprojects/packcc/tests/issue_28.d/input.txt new file mode 100644 index 00000000..bcdaa9bb --- /dev/null +++ b/src/subprojects/packcc/tests/issue_28.d/input.txt @@ -0,0 +1,2 @@ +A; +A diff --git a/src/subprojects/packcc/tests/issue_78.d/input.peg b/src/subprojects/packcc/tests/issue_78.d/input.peg new file mode 100644 index 00000000..60dad1ae --- /dev/null +++ b/src/subprojects/packcc/tests/issue_78.d/input.peg @@ -0,0 +1 @@ +main <- ( "A" diff --git a/src/subprojects/packcc/tests/issue_78.d/issue_78.bats b/src/subprojects/packcc/tests/issue_78.d/issue_78.bats new file mode 100644 index 00000000..bb0b47a4 --- /dev/null +++ b/src/subprojects/packcc/tests/issue_78.d/issue_78.bats @@ -0,0 +1,9 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing issue_78.d - generation" { + run test_generate + [ "$status" -eq 10 ] + [[ "$output" =~ ': input.peg:1:1: Illegal rule syntax'$ ]] +} diff --git a/src/subprojects/packcc/tests/lines.d/input.peg b/src/subprojects/packcc/tests/lines.d/input.peg new file mode 100644 index 00000000..d4288139 --- /dev/null +++ b/src/subprojects/packcc/tests/lines.d/input.peg @@ -0,0 +1,33 @@ +%header { /* :HEADER: */ } + +%source { + /* :SOURCE: */ +} + +%common { + /* :COMMON: */ +} + +%earlyheader { /* :EARLYHEADER: */ } + +%earlysource { /* :EARLYSOURCE: */ } + +%earlycommon { + /* :EARLYCOMMON: */ +} + +FILE + <- RULE1 + { + /* :RULE1: */ + } + / RULE2 + { /* :RULE2: */ } + / RULE3 { /* :RULE3: */ } + +RULE1 <- '1' +RULE2 <- '2' +RULE3 <- '3' + +%% +/* :CODE: */ diff --git a/src/subprojects/packcc/tests/lines.d/lines.bats b/src/subprojects/packcc/tests/lines.d/lines.bats new file mode 100644 index 00000000..82edb827 --- /dev/null +++ b/src/subprojects/packcc/tests/lines.d/lines.bats @@ -0,0 +1,118 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing lines.d - generation" { + PACKCC_OPTS=("--lines") + test_generate +} + +@test "Testing lines.d - header" { + in_header ":EARLYHEADER:" + in_header ":EARLYCOMMON:" + in_header ":HEADER:" + in_header ":COMMON:" + + ! in_header ":EARLYSOURCE:" + ! in_header ":SOURCE:" + ! in_header ":CODE:" + ! in_header ":RULE1:" + ! in_header ":RULE2:" + ! in_header ":RULE3:" + + EARLYHEADER_I=$(get_line ":EARLYHEADER:" input.peg) + EARLYHEADER_O=$(get_line ":EARLYHEADER:" parser.h) + EARLYHEADER_S=$(get_line "^#line $EARLYHEADER_I \"input.peg\"" parser.h) + EARLYHEADER_E=$(get_line "^#line $(($EARLYHEADER_O + 2)) \"parser.h\"" parser.h) + [ "$EARLYHEADER_S" -eq $((EARLYHEADER_O - 1)) ] + [ "$EARLYHEADER_E" -eq $((EARLYHEADER_O + 1)) ] + + EARLYCOMMON_I=$(get_line ":EARLYCOMMON:" input.peg) + EARLYCOMMON_O=$(get_line ":EARLYCOMMON:" parser.h) + EARLYCOMMON_S=$(get_line "^#line $EARLYCOMMON_I \"input.peg\"" parser.h) + EARLYCOMMON_E=$(get_line "^#line $(($EARLYCOMMON_O + 2)) \"parser.h\"" parser.h) + [ "$EARLYCOMMON_S" -eq $((EARLYCOMMON_O - 1)) ] + [ "$EARLYCOMMON_E" -eq $((EARLYCOMMON_O + 1)) ] + + HEADER_I=$(get_line ":HEADER:" input.peg) + HEADER_O=$(get_line ":HEADER:" parser.h) + HEADER_S=$(get_line "^#line $HEADER_I \"input.peg\"" parser.h) + HEADER_E=$(get_line "^#line $(($HEADER_O + 2)) \"parser.h\"" parser.h) + [ "$HEADER_S" -eq $((HEADER_O - 1)) ] + [ "$HEADER_E" -eq $((HEADER_O + 1)) ] + + COMMON_I=$(get_line ":COMMON:" input.peg) + COMMON_O=$(get_line ":COMMON:" parser.h) + COMMON_S=$(get_line "^#line $COMMON_I \"input.peg\"" parser.h) + COMMON_E=$(get_line "^#line $(($COMMON_O + 2)) \"parser.h\"" parser.h) + [ "$COMMON_S" -eq $((COMMON_O - 1)) ] + [ "$COMMON_E" -eq $((COMMON_O + 1)) ] +} + +@test "Testing lines.d - source" { + in_source ":EARLYSOURCE:" + in_source ":EARLYCOMMON:" + in_source ":SOURCE:" + in_source ":COMMON:" + in_source ":CODE:" + in_source ":RULE1:" + in_source ":RULE2:" + in_source ":RULE3:" + + ! in_source ":EARLYHEADER:" + ! in_source ":HEADER:" + + EARLYSOURCE_I=$(get_line ":EARLYSOURCE:" input.peg) + EARLYSOURCE_O=$(get_line ":EARLYSOURCE:" parser.c) + EARLYSOURCE_S=$(get_line "^#line $EARLYSOURCE_I \"input.peg\"" parser.c) + EARLYSOURCE_E=$(get_line "^#line $(($EARLYSOURCE_O + 2)) \"parser.c\"" parser.c) + [ "$EARLYSOURCE_S" -eq $((EARLYSOURCE_O - 1)) ] + [ "$EARLYSOURCE_E" -eq $((EARLYSOURCE_O + 1)) ] + + EARLYCOMMON_I=$(get_line ":EARLYCOMMON:" input.peg) + EARLYCOMMON_O=$(get_line ":EARLYCOMMON:" parser.c) + EARLYCOMMON_S=$(get_line "^#line $EARLYCOMMON_I \"input.peg\"" parser.c) + EARLYCOMMON_E=$(get_line "^#line $(($EARLYCOMMON_O + 2)) \"parser.c\"" parser.c) + [ "$EARLYCOMMON_S" -eq $((EARLYCOMMON_O - 1)) ] + [ "$EARLYCOMMON_E" -eq $((EARLYCOMMON_O + 1)) ] + + SOURCE_I=$(get_line ":SOURCE:" input.peg) + SOURCE_O=$(get_line ":SOURCE:" parser.c) + SOURCE_S=$(get_line "^#line $SOURCE_I \"input.peg\"" parser.c) + SOURCE_E=$(get_line "^#line $(($SOURCE_O + 2)) \"parser.c\"" parser.c) + [ "$SOURCE_S" -eq $((SOURCE_O - 1)) ] + [ "$SOURCE_E" -eq $((SOURCE_O + 1)) ] + + COMMON_I=$(get_line ":COMMON:" input.peg) + COMMON_O=$(get_line ":COMMON:" parser.c) + COMMON_S=$(get_line "^#line $COMMON_I \"input.peg\"" parser.c) + COMMON_E=$(get_line "^#line $(($COMMON_O + 2)) \"parser.c\"" parser.c) + [ "$COMMON_S" -eq $((COMMON_O - 1)) ] + [ "$COMMON_E" -eq $((COMMON_O + 1)) ] + + RULE1_I=$(get_line ":RULE1:" input.peg) + RULE1_O=$(get_line ":RULE1:" parser.c) + RULE1_S=$(get_line "^#line $RULE1_I \"input.peg\"" parser.c) + RULE1_E=$(get_line "^#line $(($RULE1_O + 2)) \"parser.c\"" parser.c) + [ "$RULE1_S" -eq $((RULE1_O - 1)) ] + [ "$RULE1_E" -eq $((RULE1_O + 1)) ] + + RULE2_I=$(get_line ":RULE2:" input.peg) + RULE2_O=$(get_line ":RULE2:" parser.c) + RULE2_S=$(get_line "^#line $RULE2_I \"input.peg\"" parser.c) + RULE2_E=$(get_line "^#line $(($RULE2_O + 2)) \"parser.c\"" parser.c) + [ "$RULE2_S" -eq $((RULE2_O - 1)) ] + [ "$RULE2_E" -eq $((RULE2_O + 1)) ] + + RULE3_I=$(get_line ":RULE3:" input.peg) + RULE3_O=$(get_line ":RULE3:" parser.c) + RULE3_S=$(get_line "^#line $RULE3_I \"input.peg\"" parser.c) + RULE3_E=$(get_line "^#line $(($RULE3_O + 2)) \"parser.c\"" parser.c) + [ "$RULE3_S" -eq $((RULE3_O - 1)) ] + [ "$RULE3_E" -eq $((RULE3_O + 1)) ] + + CODE_I=$(get_line ":CODE:" input.peg) + CODE_O=$(get_line ":CODE:" parser.c) + CODE_S=$(get_line "^#line $CODE_I \"input.peg\"" parser.c) + [ "$CODE_S" -eq $((CODE_O - 1)) ] +} diff --git a/src/subprojects/packcc/tests/main.c b/src/subprojects/packcc/tests/main.c new file mode 100644 index 00000000..4b33dd0d --- /dev/null +++ b/src/subprojects/packcc/tests/main.c @@ -0,0 +1,20 @@ +#include + +#include "parser.h" + +#define PRINT(X) printf("%s\n", X); +#define PRINT_L(LBL, X) printf("%s: %s\n", LBL, X); + +#ifndef RET_TYPE +#define RET_TYPE int +#endif + +#include "parser.c" + +int main(int argc, char **argv) { + RET_TYPE ret; + pcc_context_t *ctx = pcc_create(NULL); + while (pcc_parse(ctx, &ret)); + pcc_destroy(ctx); + return 0; +} diff --git a/src/subprojects/packcc/tests/negative_predicate.d/expected.txt b/src/subprojects/packcc/tests/negative_predicate.d/expected.txt new file mode 100644 index 00000000..ce073d95 --- /dev/null +++ b/src/subprojects/packcc/tests/negative_predicate.d/expected.txt @@ -0,0 +1,4 @@ +FOLLOWED BY SPACE: second +BEGINS WITH UPPER: LINE +FOLLOWED BY SPACE: third +BEGINS WITH UPPER: Fourth diff --git a/src/subprojects/packcc/tests/negative_predicate.d/input.peg b/src/subprojects/packcc/tests/negative_predicate.d/input.peg new file mode 100644 index 00000000..666ff011 --- /dev/null +++ b/src/subprojects/packcc/tests/negative_predicate.d/input.peg @@ -0,0 +1,4 @@ +FILE <- (BEGINS_WITH_UPPER / FOLLOWED_BY_SPACE / .)* + +BEGINS_WITH_UPPER <- ![a-z] [a-zA-Z]+ { printf("BEGINS WITH UPPER: %s\n", $0); } +FOLLOWED_BY_SPACE <- [a-zA-Z]+ ![a-zA-Z0-9\n] { printf("FOLLOWED BY SPACE: %s\n", $0); } diff --git a/src/subprojects/packcc/tests/negative_predicate.d/input.txt b/src/subprojects/packcc/tests/negative_predicate.d/input.txt new file mode 100644 index 00000000..6079c0af --- /dev/null +++ b/src/subprojects/packcc/tests/negative_predicate.d/input.txt @@ -0,0 +1,4 @@ +first123 +second LINE +third line +Fourth line diff --git a/src/subprojects/packcc/tests/position.d/expected.txt b/src/subprojects/packcc/tests/position.d/expected.txt new file mode 100644 index 00000000..1b8d8f21 --- /dev/null +++ b/src/subprojects/packcc/tests/position.d/expected.txt @@ -0,0 +1,2 @@ +NUMBER AT START POSITION: 12345 +NUMBER NOT AT START POSITION: 67890 diff --git a/src/subprojects/packcc/tests/position.d/input.peg b/src/subprojects/packcc/tests/position.d/input.peg new file mode 100644 index 00000000..50f80ec7 --- /dev/null +++ b/src/subprojects/packcc/tests/position.d/input.peg @@ -0,0 +1,6 @@ +FILE <- (NUMBER_AT_START_POSITION / NUMBER_NOT_AT_START_POSITION / .)* + +NUMBER_AT_START_POSITION + <- ^ ( [0] / [1-9][0-9]+ ) { printf("NUMBER AT START POSITION: %s\n", $0); } +NUMBER_NOT_AT_START_POSITION + <- !^ ( [0] / [1-9][0-9]+ ) { printf("NUMBER NOT AT START POSITION: %s\n", $0); } diff --git a/src/subprojects/packcc/tests/position.d/input.txt b/src/subprojects/packcc/tests/position.d/input.txt new file mode 100644 index 00000000..8e879b6a --- /dev/null +++ b/src/subprojects/packcc/tests/position.d/input.txt @@ -0,0 +1 @@ +12345 67890 diff --git a/src/subprojects/packcc/tests/positive_predicate.d/expected.txt b/src/subprojects/packcc/tests/positive_predicate.d/expected.txt new file mode 100644 index 00000000..ce073d95 --- /dev/null +++ b/src/subprojects/packcc/tests/positive_predicate.d/expected.txt @@ -0,0 +1,4 @@ +FOLLOWED BY SPACE: second +BEGINS WITH UPPER: LINE +FOLLOWED BY SPACE: third +BEGINS WITH UPPER: Fourth diff --git a/src/subprojects/packcc/tests/positive_predicate.d/input.peg b/src/subprojects/packcc/tests/positive_predicate.d/input.peg new file mode 100644 index 00000000..4d5abdfc --- /dev/null +++ b/src/subprojects/packcc/tests/positive_predicate.d/input.peg @@ -0,0 +1,4 @@ +FILE <- (BEGINS_WITH_UPPER / FOLLOWED_BY_SPACE / .)* + +BEGINS_WITH_UPPER <- &[A-Z] [a-zA-Z]+ { printf("BEGINS WITH UPPER: %s\n", $0); } +FOLLOWED_BY_SPACE <- [a-zA-Z]+ &" " { printf("FOLLOWED BY SPACE: %s\n", $0); } diff --git a/src/subprojects/packcc/tests/positive_predicate.d/input.txt b/src/subprojects/packcc/tests/positive_predicate.d/input.txt new file mode 100644 index 00000000..6079c0af --- /dev/null +++ b/src/subprojects/packcc/tests/positive_predicate.d/input.txt @@ -0,0 +1,4 @@ +first123 +second LINE +third line +Fourth line diff --git a/src/subprojects/packcc/tests/quantifiers.d/expected-optional-repeatable.txt b/src/subprojects/packcc/tests/quantifiers.d/expected-optional-repeatable.txt new file mode 100644 index 00000000..7e4d7bbd --- /dev/null +++ b/src/subprojects/packcc/tests/quantifiers.d/expected-optional-repeatable.txt @@ -0,0 +1,4 @@ +* +*C +*CC +*CCCCCCCCCCCCCCCCCC diff --git a/src/subprojects/packcc/tests/quantifiers.d/expected-optional.txt b/src/subprojects/packcc/tests/quantifiers.d/expected-optional.txt new file mode 100644 index 00000000..cff3458f --- /dev/null +++ b/src/subprojects/packcc/tests/quantifiers.d/expected-optional.txt @@ -0,0 +1,2 @@ +? +?A diff --git a/src/subprojects/packcc/tests/quantifiers.d/expected-repeatable.txt b/src/subprojects/packcc/tests/quantifiers.d/expected-repeatable.txt new file mode 100644 index 00000000..4c5478aa --- /dev/null +++ b/src/subprojects/packcc/tests/quantifiers.d/expected-repeatable.txt @@ -0,0 +1,3 @@ ++B ++BB ++BBBBBBBBBBB diff --git a/src/subprojects/packcc/tests/quantifiers.d/input-optional-repeatable.txt b/src/subprojects/packcc/tests/quantifiers.d/input-optional-repeatable.txt new file mode 100644 index 00000000..7e4d7bbd --- /dev/null +++ b/src/subprojects/packcc/tests/quantifiers.d/input-optional-repeatable.txt @@ -0,0 +1,4 @@ +* +*C +*CC +*CCCCCCCCCCCCCCCCCC diff --git a/src/subprojects/packcc/tests/quantifiers.d/input-optional.txt b/src/subprojects/packcc/tests/quantifiers.d/input-optional.txt new file mode 100644 index 00000000..cff3458f --- /dev/null +++ b/src/subprojects/packcc/tests/quantifiers.d/input-optional.txt @@ -0,0 +1,2 @@ +? +?A diff --git a/src/subprojects/packcc/tests/quantifiers.d/input-repeatable.txt b/src/subprojects/packcc/tests/quantifiers.d/input-repeatable.txt new file mode 100644 index 00000000..4c5478aa --- /dev/null +++ b/src/subprojects/packcc/tests/quantifiers.d/input-repeatable.txt @@ -0,0 +1,3 @@ ++B ++BB ++BBBBBBBBBBB diff --git a/src/subprojects/packcc/tests/quantifiers.d/input.peg b/src/subprojects/packcc/tests/quantifiers.d/input.peg new file mode 100644 index 00000000..5743f7a5 --- /dev/null +++ b/src/subprojects/packcc/tests/quantifiers.d/input.peg @@ -0,0 +1,6 @@ +FILE <- (LINE '\n')* +LINE <- (REPEATABLE_OPTIONAL / OPTIONAL / REPEATABLE) { PRINT($0); } + +OPTIONAL <- "?" "A"? +REPEATABLE <- "+" "B"+ +REPEATABLE_OPTIONAL <- "*" "C"* diff --git a/src/subprojects/packcc/tests/strings.d/expected-escapes.txt b/src/subprojects/packcc/tests/strings.d/expected-escapes.txt new file mode 100644 index 00000000..92892fa9 --- /dev/null +++ b/src/subprojects/packcc/tests/strings.d/expected-escapes.txt @@ -0,0 +1 @@ +\'" =€ diff --git a/src/subprojects/packcc/tests/strings.d/expected-utf8.txt b/src/subprojects/packcc/tests/strings.d/expected-utf8.txt new file mode 100644 index 00000000..3b6ffce8 --- /dev/null +++ b/src/subprojects/packcc/tests/strings.d/expected-utf8.txt @@ -0,0 +1,3 @@ +Hello +world +😊 diff --git a/src/subprojects/packcc/tests/strings.d/expected.txt b/src/subprojects/packcc/tests/strings.d/expected.txt new file mode 100644 index 00000000..65a56c31 --- /dev/null +++ b/src/subprojects/packcc/tests/strings.d/expected.txt @@ -0,0 +1,2 @@ +Hello +world diff --git a/src/subprojects/packcc/tests/strings.d/input-escapes.txt b/src/subprojects/packcc/tests/strings.d/input-escapes.txt new file mode 100644 index 00000000..92892fa9 --- /dev/null +++ b/src/subprojects/packcc/tests/strings.d/input-escapes.txt @@ -0,0 +1 @@ +\'" =€ diff --git a/src/subprojects/packcc/tests/strings.d/input-utf8.txt b/src/subprojects/packcc/tests/strings.d/input-utf8.txt new file mode 100644 index 00000000..24485e46 --- /dev/null +++ b/src/subprojects/packcc/tests/strings.d/input-utf8.txt @@ -0,0 +1 @@ +Hello world 😊 diff --git a/src/subprojects/packcc/tests/strings.d/input.peg b/src/subprojects/packcc/tests/strings.d/input.peg new file mode 100644 index 00000000..7f8b3da5 --- /dev/null +++ b/src/subprojects/packcc/tests/strings.d/input.peg @@ -0,0 +1,7 @@ +FILE <- TOKEN (_ TOKEN)* _* +TOKEN <- (HELLO / WORLD / SMILEY / ESCAPES) { PRINT($0); } +HELLO <- "Hello" +WORLD <- 'world' +SMILEY <- "😊" +ESCAPES <- '\\\'\"\a\b\f\t\v\x3d\u20AC' +_ <- ' ' / '\r\n' / '\n' diff --git a/src/subprojects/packcc/tests/strings.d/input.txt b/src/subprojects/packcc/tests/strings.d/input.txt new file mode 100644 index 00000000..802992c4 --- /dev/null +++ b/src/subprojects/packcc/tests/strings.d/input.txt @@ -0,0 +1 @@ +Hello world diff --git a/src/subprojects/packcc/tests/style.d/style.bats b/src/subprojects/packcc/tests/style.d/style.bats new file mode 100644 index 00000000..0ed545a5 --- /dev/null +++ b/src/subprojects/packcc/tests/style.d/style.bats @@ -0,0 +1,34 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +check_uncrustify_version() { + version="$(uncrustify --version)" + major="$(echo "$version" | cut -d. -f1 | grep -oE '[0-9]+$')" + minor="$(echo "$version" | cut -d. -f2)" + [ "$major" -gt 0 ] || { [ "$major" -eq 0 ] && [ "$minor" -ge 72 ]; } +} + +test_style() { + if ! command -v "uncrustify" &> /dev/null; then + skip "uncrustify is not installed" + elif ! check_uncrustify_version &> /dev/null; then + skip "uncrustify is too old (minimal required version is 0.72.0)" + else + run uncrustify -q -c "$TESTDIR/uncrustify.cfg" -f "$1" + [ "$status" -eq 0 ] + diff --strip-trailing-cr -uN "$1" --label "$1" <(echo "$output") --label "formatted" + fi +} + +@test "Testing style.d - sources" { + for file in "$ROOTDIR"/*/*.c; do + test_style "$file" + done +} + +@test "Testing style.d - generated" { + test_generate "$ROOTDIR/examples/calc.peg" + test_style "style.d/parser.h" + test_style "style.d/parser.c" +} diff --git a/src/subprojects/packcc/tests/substitution.d/expected.c.txt b/src/subprojects/packcc/tests/substitution.d/expected.c.txt new file mode 100644 index 00000000..ff3d34a6 --- /dev/null +++ b/src/subprojects/packcc/tests/substitution.d/expected.c.txt @@ -0,0 +1,83 @@ +TEST EARLYSOURCE $$ +TEST EARLYSOURCE $0 +TEST EARLYSOURCE $0s +TEST EARLYSOURCE $0e +TEST EARLYSOURCE $123 +TEST EARLYSOURCE $123s +TEST EARLYSOURCE $123e +TEST EARLYSOURCE foo1 +TEST EARLYSOURCE FOO1 +TEST EARLYSOURCE ${bar} +TEST EARLYCOMMON $$ +TEST EARLYCOMMON $0 +TEST EARLYCOMMON $0s +TEST EARLYCOMMON $0e +TEST EARLYCOMMON $123 +TEST EARLYCOMMON $123s +TEST EARLYCOMMON $123e +TEST EARLYCOMMON foo1 +TEST EARLYCOMMON FOO1 +TEST EARLYCOMMON ${bar} +TEST SOURCE $$ +TEST SOURCE $0 +TEST SOURCE $0s +TEST SOURCE $0e +TEST SOURCE $123 +TEST SOURCE $123s +TEST SOURCE $123e +TEST SOURCE foo1 +TEST SOURCE FOO1 +TEST SOURCE ${bar} +TEST COMMON $$ +TEST COMMON $0 +TEST COMMON $0s +TEST COMMON $0e +TEST COMMON $123 +TEST COMMON $123s +TEST COMMON $123e +TEST COMMON foo1 +TEST COMMON FOO1 +TEST COMMON ${bar} + TEST ACTION0 __. + TEST ACTION0 $__ + TEST ACTION0 $_0 + TEST ACTION0 _0. + TEST ACTION0 $0$ + TEST ACTION0 $01 + TEST ACTION0 _0s. + TEST ACTION0 $0s$ + TEST ACTION0 $0s1 + TEST ACTION0 $01s + TEST ACTION0 _0e. + TEST ACTION0 $0e$ + TEST ACTION0 $0e1 + TEST ACTION0 $01e + TEST ACTION0 _123. + TEST ACTION0 $123$ + TEST ACTION0 $123_ + TEST ACTION0 _123s. + TEST ACTION0 $123s$ + TEST ACTION0 $123s_ + TEST ACTION0 _123e. + TEST ACTION0 $123e$ + TEST ACTION0 $123e_ + TEST ACTION0 foo1 + TEST ACTION0 FOO1 + TEST ACTION0 ${bar} + TEST ACTION1 __ + TEST ACTION2 _0 + TEST ACTION3 _0s + TEST ACTION4 _0e + TEST ACTION5 _123 + TEST ACTION6 _123s + TEST ACTION7 _123e +TEST FOOTER $$ +TEST FOOTER $0 +TEST FOOTER $0s +TEST FOOTER $0e +TEST FOOTER $123 +TEST FOOTER $123s +TEST FOOTER $123e +TEST FOOTER foo1 +TEST FOOTER FOO1 +TEST FOOTER ${bar} diff --git a/src/subprojects/packcc/tests/substitution.d/expected.h.txt b/src/subprojects/packcc/tests/substitution.d/expected.h.txt new file mode 100644 index 00000000..e5c04318 --- /dev/null +++ b/src/subprojects/packcc/tests/substitution.d/expected.h.txt @@ -0,0 +1,40 @@ +TEST EARLYHEADER $$ +TEST EARLYHEADER $0 +TEST EARLYHEADER $0s +TEST EARLYHEADER $0e +TEST EARLYHEADER $123 +TEST EARLYHEADER $123s +TEST EARLYHEADER $123e +TEST EARLYHEADER foo1 +TEST EARLYHEADER FOO1 +TEST EARLYHEADER ${bar} +TEST EARLYCOMMON $$ +TEST EARLYCOMMON $0 +TEST EARLYCOMMON $0s +TEST EARLYCOMMON $0e +TEST EARLYCOMMON $123 +TEST EARLYCOMMON $123s +TEST EARLYCOMMON $123e +TEST EARLYCOMMON foo1 +TEST EARLYCOMMON FOO1 +TEST EARLYCOMMON ${bar} +TEST HEADER $$ +TEST HEADER $0 +TEST HEADER $0s +TEST HEADER $0e +TEST HEADER $123 +TEST HEADER $123s +TEST HEADER $123e +TEST HEADER foo1 +TEST HEADER FOO1 +TEST HEADER ${bar} +TEST COMMON $$ +TEST COMMON $0 +TEST COMMON $0s +TEST COMMON $0e +TEST COMMON $123 +TEST COMMON $123s +TEST COMMON $123e +TEST COMMON foo1 +TEST COMMON FOO1 +TEST COMMON ${bar} diff --git a/src/subprojects/packcc/tests/substitution.d/input.peg b/src/subprojects/packcc/tests/substitution.d/input.peg new file mode 100644 index 00000000..7f92307b --- /dev/null +++ b/src/subprojects/packcc/tests/substitution.d/input.peg @@ -0,0 +1,134 @@ +%header { +TEST HEADER $$ +TEST HEADER $0 +TEST HEADER $0s +TEST HEADER $0e +TEST HEADER $123 +TEST HEADER $123s +TEST HEADER $123e +TEST HEADER ${prefix} +TEST HEADER ${PREFIX} +TEST HEADER ${bar} +} + +%source { +TEST SOURCE $$ +TEST SOURCE $0 +TEST SOURCE $0s +TEST SOURCE $0e +TEST SOURCE $123 +TEST SOURCE $123s +TEST SOURCE $123e +TEST SOURCE ${prefix} +TEST SOURCE ${PREFIX} +TEST SOURCE ${bar} +} + +%common { +TEST COMMON $$ +TEST COMMON $0 +TEST COMMON $0s +TEST COMMON $0e +TEST COMMON $123 +TEST COMMON $123s +TEST COMMON $123e +TEST COMMON ${prefix} +TEST COMMON ${PREFIX} +TEST COMMON ${bar} +} + +%earlyheader { +TEST EARLYHEADER $$ +TEST EARLYHEADER $0 +TEST EARLYHEADER $0s +TEST EARLYHEADER $0e +TEST EARLYHEADER $123 +TEST EARLYHEADER $123s +TEST EARLYHEADER $123e +TEST EARLYHEADER ${prefix} +TEST EARLYHEADER ${PREFIX} +TEST EARLYHEADER ${bar} +} + +%earlysource { +TEST EARLYSOURCE $$ +TEST EARLYSOURCE $0 +TEST EARLYSOURCE $0s +TEST EARLYSOURCE $0e +TEST EARLYSOURCE $123 +TEST EARLYSOURCE $123s +TEST EARLYSOURCE $123e +TEST EARLYSOURCE ${prefix} +TEST EARLYSOURCE ${PREFIX} +TEST EARLYSOURCE ${bar} +} + +%earlycommon { +TEST EARLYCOMMON $$ +TEST EARLYCOMMON $0 +TEST EARLYCOMMON $0s +TEST EARLYCOMMON $0e +TEST EARLYCOMMON $123 +TEST EARLYCOMMON $123s +TEST EARLYCOMMON $123e +TEST EARLYCOMMON ${prefix} +TEST EARLYCOMMON ${PREFIX} +TEST EARLYCOMMON ${bar} +} + +%value "double" + +%auxil "long" + +%prefix "foo1" + +FILE + <- '_' + { + TEST ACTION0 $$. + TEST ACTION0 $$$ + TEST ACTION0 $$0 + TEST ACTION0 $0. + TEST ACTION0 $0$ + TEST ACTION0 $01 + TEST ACTION0 $0s. + TEST ACTION0 $0s$ + TEST ACTION0 $0s1 + TEST ACTION0 $01s + TEST ACTION0 $0e. + TEST ACTION0 $0e$ + TEST ACTION0 $0e1 + TEST ACTION0 $01e + TEST ACTION0 $123. + TEST ACTION0 $123$ + TEST ACTION0 $123_ + TEST ACTION0 $123s. + TEST ACTION0 $123s$ + TEST ACTION0 $123s_ + TEST ACTION0 $123e. + TEST ACTION0 $123e$ + TEST ACTION0 $123e_ + TEST ACTION0 ${prefix} + TEST ACTION0 ${PREFIX} + TEST ACTION0 ${bar} + } + / '$' {TEST ACTION1 $$} + / '0' {TEST ACTION2 $0} + / '0s' {TEST ACTION3 $0s} + / '0e' {TEST ACTION4 $0e} + / '123' {TEST ACTION5 $123} + / '123s' {TEST ACTION6 $123s} + / '123e' {TEST ACTION7 $123e} + +%% + +TEST FOOTER $$ +TEST FOOTER $0 +TEST FOOTER $0s +TEST FOOTER $0e +TEST FOOTER $123 +TEST FOOTER $123s +TEST FOOTER $123e +TEST FOOTER ${prefix} +TEST FOOTER ${PREFIX} +TEST FOOTER ${bar} diff --git a/src/subprojects/packcc/tests/substitution.d/subst.bats b/src/subprojects/packcc/tests/substitution.d/subst.bats new file mode 100644 index 00000000..53dcb46b --- /dev/null +++ b/src/subprojects/packcc/tests/substitution.d/subst.bats @@ -0,0 +1,13 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +check_output_parser() { + diff --strip-trailing-cr -uN "${1/parser/expected}.txt" --label "${1/parser/expected}" <(grep '^ *TEST ' < "$1") --label "output" +} + +@test "Testing substitution.d - generation" { + test_generate + check_output_parser "substitution.d/parser.h" + check_output_parser "substitution.d/parser.c" +} diff --git a/src/subprojects/packcc/tests/test.sh b/src/subprojects/packcc/tests/test.sh new file mode 100755 index 00000000..79ba0ef5 --- /dev/null +++ b/src/subprojects/packcc/tests/test.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +generate_bats() { + skip_all="" + if [ -f "$1/input.skip.peg" ]; then + skip_all=$'skip\n' + fi + cat < /dev/null && continue + generate_bats "$DIR" > "$DIR/test.bats" + done + + bats "$@" ./*.d + + if [ -f "packcc.gcda" ]; then + echo "$(gcov packcc | grep "Lines executed") (see $TESTDIR/packcc.c.gcov for details)" + fi +} + +main "$@" diff --git a/src/subprojects/packcc/tests/uncrustify.cfg b/src/subprojects/packcc/tests/uncrustify.cfg new file mode 100644 index 00000000..da213db8 --- /dev/null +++ b/src/subprojects/packcc/tests/uncrustify.cfg @@ -0,0 +1,3128 @@ +# Uncrustify_d-0.72.0_f + +# +# General options +# + +# The type of line endings. +# +# Default: auto +newlines = lf # lf/crlf/cr/auto + +# The original size of tabs in the input. +# +# Default: 8 +input_tab_size = 4 # unsigned number + +# The size of tabs in the output (only used if align_with_tabs=true). +# +# Default: 8 +output_tab_size = 4 # unsigned number + +# The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). +# +# Default: 92 +string_escape_char = 92 # unsigned number + +# Alternate string escape char (usually only used for Pawn). +# Only works right before the quote char. +string_escape_char2 = 0 # unsigned number + +# Replace tab characters found in string literals with the escape sequence \t +# instead. +string_replace_tab_chars = true # true/false + +# Allow interpreting '>=' and '>>=' as part of a template in code like +# 'void f(list>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. +# Improvements to template detection may make this option obsolete. +tok_split_gte = false # true/false + +# Disable formatting of NL_CONT ('\\n') ended lines (e.g. multiline macros) +disable_processing_nl_cont = false # true/false + +# Specify the marker used in comments to disable processing of part of the +# file. +# The comment should be used alone in one line. +# +# Default: *INDENT-OFF* +disable_processing_cmt = " *INDENT-OFF*" # string + +# Specify the marker used in comments to (re)enable processing in a file. +# The comment should be used alone in one line. +# +# Default: *INDENT-ON* +enable_processing_cmt = " *INDENT-ON*" # string + +# Enable parsing of digraphs. +enable_digraphs = false # true/false + +# Add or remove the UTF-8 BOM (recommend 'remove'). +utf8_bom = remove # ignore/add/remove/force + +# If the file contains bytes with values between 128 and 255, but is not +# UTF-8, then output as UTF-8. +utf8_byte = false # true/false + +# Force the output encoding to UTF-8. +utf8_force = false # true/false + +# Add or remove space between 'do' and '{'. +sp_do_brace_open = add # ignore/add/remove/force + +# Add or remove space between '}' and 'while'. +sp_brace_close_while = add # ignore/add/remove/force + +# Add or remove space between 'while' and '('. +sp_while_paren_open = add # ignore/add/remove/force + +# +# Spacing options +# + +# Add or remove space around non-assignment symbolic operators ('+', '/', '%', +# '<<', and so forth). +sp_arith = add # ignore/add/remove/force + +# Add or remove space around arithmetic operators '+' and '-'. +# +# Overrides sp_arith. +sp_arith_additive = add # ignore/add/remove/force + +# Add or remove space around assignment operator '=', '+=', etc. +sp_assign = add # ignore/add/remove/force + +# Add or remove space around '=' in C++11 lambda capture specifications. +# +# Overrides sp_assign. +sp_cpp_lambda_assign = ignore # ignore/add/remove/force + +# Add or remove space after the capture specification of a C++11 lambda when +# an argument list is present, as in '[] (int x){ ... }'. +sp_cpp_lambda_square_paren = ignore # ignore/add/remove/force + +# Add or remove space after the capture specification of a C++11 lambda with +# no argument list is present, as in '[] { ... }'. +sp_cpp_lambda_square_brace = ignore # ignore/add/remove/force + +# Add or remove space after the argument list of a C++11 lambda, as in +# '[](int x) { ... }'. +sp_cpp_lambda_paren_brace = ignore # ignore/add/remove/force + +# Add or remove space between a lambda body and its call operator of an +# immediately invoked lambda, as in '[]( ... ){ ... } ( ... )'. +sp_cpp_lambda_fparen = ignore # ignore/add/remove/force + +# Add or remove space around assignment operator '=' in a prototype. +# +# If set to ignore, use sp_assign. +sp_assign_default = ignore # ignore/add/remove/force + +# Add or remove space before assignment operator '=', '+=', etc. +# +# Overrides sp_assign. +sp_before_assign = ignore # ignore/add/remove/force + +# Add or remove space after assignment operator '=', '+=', etc. +# +# Overrides sp_assign. +sp_after_assign = ignore # ignore/add/remove/force + +# Add or remove space in 'NS_ENUM ('. +sp_enum_paren = ignore # ignore/add/remove/force + +# Add or remove space around assignment '=' in enum. +sp_enum_assign = ignore # ignore/add/remove/force + +# Add or remove space before assignment '=' in enum. +# +# Overrides sp_enum_assign. +sp_enum_before_assign = ignore # ignore/add/remove/force + +# Add or remove space after assignment '=' in enum. +# +# Overrides sp_enum_assign. +sp_enum_after_assign = ignore # ignore/add/remove/force + +# Add or remove space around assignment ':' in enum. +sp_enum_colon = ignore # ignore/add/remove/force + +# Add or remove space around preprocessor '##' concatenation operator. +# +# Default: add +sp_pp_concat = add # ignore/add/remove/force + +# Add or remove space after preprocessor '#' stringify operator. +# Also affects the '#@' charizing operator. +sp_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space before preprocessor '#' stringify operator +# as in '#define x(y) L#y'. +sp_before_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space around boolean operators '&&' and '||'. +sp_bool = ignore # ignore/add/remove/force + +# Add or remove space around compare operator '<', '>', '==', etc. +sp_compare = ignore # ignore/add/remove/force + +# Add or remove space inside '(' and ')'. +sp_inside_paren = ignore # ignore/add/remove/force + +# Add or remove space between nested parentheses, i.e. '((' vs. ') )'. +sp_paren_paren = ignore # ignore/add/remove/force + +# Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. +sp_cparen_oparen = ignore # ignore/add/remove/force + +# Whether to balance spaces inside nested parentheses. +sp_balance_nested_parens = false # true/false + +# Add or remove space between ')' and '{'. +sp_paren_brace = ignore # ignore/add/remove/force + +# Add or remove space between nested braces, i.e. '{{' vs '{ {'. +sp_brace_brace = ignore # ignore/add/remove/force + +# Add or remove space before pointer star '*'. +sp_before_ptr_star = force # ignore/add/remove/force + +# Add or remove space before pointer star '*' that isn't followed by a +# variable name. If set to ignore, sp_before_ptr_star is used instead. +sp_before_unnamed_ptr_star = force # ignore/add/remove/force + +# Add or remove space between pointer stars '*'. +sp_between_ptr_star = remove # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a word. +# +# Overrides sp_type_func. +sp_after_ptr_star = remove # ignore/add/remove/force + +# Add or remove space after pointer caret '^', if followed by a word. +sp_after_ptr_block_caret = ignore # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a qualifier. +sp_after_ptr_star_qualifier = remove # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by a function +# prototype or function definition. +# +# Overrides sp_after_ptr_star and sp_type_func. +sp_after_ptr_star_func = ignore # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by an open +# parenthesis, as in 'void* (*)(). +sp_ptr_star_paren = ignore # ignore/add/remove/force + +# Add or remove space before a pointer star '*', if followed by a function +# prototype or function definition. +sp_before_ptr_star_func = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&'. +sp_before_byref = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&' that isn't followed by a +# variable name. If set to ignore, sp_before_byref is used instead. +sp_before_unnamed_byref = ignore # ignore/add/remove/force + +# Add or remove space after reference sign '&', if followed by a word. +# +# Overrides sp_type_func. +sp_after_byref = ignore # ignore/add/remove/force + +# Add or remove space after a reference sign '&', if followed by a function +# prototype or function definition. +# +# Overrides sp_after_byref and sp_type_func. +sp_after_byref_func = ignore # ignore/add/remove/force + +# Add or remove space before a reference sign '&', if followed by a function +# prototype or function definition. +sp_before_byref_func = ignore # ignore/add/remove/force + +# Add or remove space between type and word. In cases where total removal of +# whitespace would be a syntax error, a value of 'remove' is treated the same +# as 'force'. +# +# This also affects some other instances of space following a type that are +# not covered by other options; for example, between the return type and +# parenthesis of a function type template argument, between the type and +# parenthesis of an array parameter, or between 'decltype(...)' and the +# following word. +# +# Default: force +sp_after_type = add # ignore/add/remove/force + +# Add or remove space between 'decltype(...)' and word. +# +# Overrides sp_after_type. +sp_after_decltype = ignore # ignore/add/remove/force + +# (D) Add or remove space before the parenthesis in the D constructs +# 'template Foo(' and 'class Foo('. +sp_before_template_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'template' and '<'. +# If set to ignore, sp_before_angle is used. +sp_template_angle = ignore # ignore/add/remove/force + +# Add or remove space before '<'. +sp_before_angle = ignore # ignore/add/remove/force + +# Add or remove space inside '<' and '>'. +sp_inside_angle = ignore # ignore/add/remove/force + +# Add or remove space inside '<>'. +sp_inside_angle_empty = ignore # ignore/add/remove/force + +# Add or remove space between '>' and ':'. +sp_angle_colon = ignore # ignore/add/remove/force + +# Add or remove space after '>'. +sp_after_angle = ignore # ignore/add/remove/force + +# Add or remove space between '>' and '(' as found in 'new List(foo);'. +sp_angle_paren = ignore # ignore/add/remove/force + +# Add or remove space between '>' and '()' as found in 'new List();'. +sp_angle_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between '>' and a word as in 'List m;' or +# 'template static ...'. +sp_angle_word = ignore # ignore/add/remove/force + +# Add or remove space between '>' and '>' in '>>' (template stuff). +# +# Default: add +sp_angle_shift = add # ignore/add/remove/force + +# (C++11) Permit removal of the space between '>>' in 'foo >'. Note +# that sp_angle_shift cannot remove the space without this option. +sp_permit_cpp11_shift = false # true/false + +# Add or remove space before '(' of control statements ('if', 'for', 'switch', +# 'while', etc.). +sp_before_sparen = force # ignore/add/remove/force + +# Add or remove space inside '(' and ')' of control statements. +sp_inside_sparen = ignore # ignore/add/remove/force + +# Add or remove space after '(' of control statements. +# +# Overrides sp_inside_sparen. +sp_inside_sparen_open = ignore # ignore/add/remove/force + +# Add or remove space before ')' of control statements. +# +# Overrides sp_inside_sparen. +sp_inside_sparen_close = ignore # ignore/add/remove/force + +# Add or remove space after ')' of control statements. +sp_after_sparen = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '{' of of control statements. +sp_sparen_brace = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'invariant' and '('. +sp_invariant_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space after the ')' in 'invariant (C) c'. +sp_after_invariant_paren = ignore # ignore/add/remove/force + +# Add or remove space before empty statement ';' on 'if', 'for' and 'while'. +sp_special_semi = ignore # ignore/add/remove/force + +# Add or remove space before ';'. +# +# Default: remove +sp_before_semi = remove # ignore/add/remove/force + +# Add or remove space before ';' in non-empty 'for' statements. +sp_before_semi_for = ignore # ignore/add/remove/force + +# Add or remove space before a semicolon of an empty part of a for statement. +sp_before_semi_for_empty = ignore # ignore/add/remove/force + +# Add or remove space after ';', except when followed by a comment. +# +# Default: add +sp_after_semi = add # ignore/add/remove/force + +# Add or remove space after ';' in non-empty 'for' statements. +# +# Default: force +sp_after_semi_for = force # ignore/add/remove/force + +# Add or remove space after the final semicolon of an empty part of a for +# statement, as in 'for ( ; ; )'. +sp_after_semi_for_empty = ignore # ignore/add/remove/force + +# Add or remove space before '[' (except '[]'). +sp_before_square = ignore # ignore/add/remove/force + +# Add or remove space before '[' for a variable definition. +# +# Default: remove +sp_before_vardef_square = remove # ignore/add/remove/force + +# Add or remove space before '[' for asm block. +sp_before_square_asm_block = ignore # ignore/add/remove/force + +# Add or remove space before '[]'. +sp_before_squares = ignore # ignore/add/remove/force + +# Add or remove space before C++17 structured bindings. +sp_cpp_before_struct_binding = ignore # ignore/add/remove/force + +# Add or remove space inside a non-empty '[' and ']'. +sp_inside_square = ignore # ignore/add/remove/force + +# Add or remove space inside '[]'. +sp_inside_square_empty = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and +# ']'. If set to ignore, sp_inside_square is used. +sp_inside_square_oc_array = ignore # ignore/add/remove/force + +# Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. +sp_after_comma = ignore # ignore/add/remove/force + +# Add or remove space before ','. +# +# Default: remove +sp_before_comma = remove # ignore/add/remove/force + +# (C#) Add or remove space between ',' and ']' in multidimensional array type +# like 'int[,,]'. +sp_after_mdatype_commas = ignore # ignore/add/remove/force + +# (C#) Add or remove space between '[' and ',' in multidimensional array type +# like 'int[,,]'. +sp_before_mdatype_commas = ignore # ignore/add/remove/force + +# (C#) Add or remove space between ',' in multidimensional array type +# like 'int[,,]'. +sp_between_mdatype_commas = ignore # ignore/add/remove/force + +# Add or remove space between an open parenthesis and comma, +# i.e. '(,' vs. '( ,'. +# +# Default: force +sp_paren_comma = force # ignore/add/remove/force + +# Add or remove space before the variadic '...' when preceded by a +# non-punctuator. +sp_before_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space between a type and '...'. +sp_type_ellipsis = ignore # ignore/add/remove/force + +# (D) Add or remove space between a type and '?'. +sp_type_question = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '...'. +sp_paren_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space between ')' and a qualifier such as 'const'. +sp_paren_qualifier = ignore # ignore/add/remove/force + +# Add or remove space between ')' and 'noexcept'. +sp_paren_noexcept = ignore # ignore/add/remove/force + +# Add or remove space after class ':'. +sp_after_class_colon = ignore # ignore/add/remove/force + +# Add or remove space before class ':'. +sp_before_class_colon = ignore # ignore/add/remove/force + +# Add or remove space after class constructor ':'. +sp_after_constr_colon = ignore # ignore/add/remove/force + +# Add or remove space before class constructor ':'. +sp_before_constr_colon = ignore # ignore/add/remove/force + +# Add or remove space before case ':'. +# +# Default: remove +sp_before_case_colon = remove # ignore/add/remove/force + +# Add or remove space between 'operator' and operator sign. +sp_after_operator = ignore # ignore/add/remove/force + +# Add or remove space between the operator symbol and the open parenthesis, as +# in 'operator ++('. +sp_after_operator_sym = ignore # ignore/add/remove/force + +# Overrides sp_after_operator_sym when the operator has no arguments, as in +# 'operator *()'. +sp_after_operator_sym_empty = ignore # ignore/add/remove/force + +# Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or +# '(int)a' vs. '(int) a'. +sp_after_cast = ignore # ignore/add/remove/force + +# Add or remove spaces inside cast parentheses. +sp_inside_paren_cast = ignore # ignore/add/remove/force + +# Add or remove space between the type and open parenthesis in a C++ cast, +# i.e. 'int(exp)' vs. 'int (exp)'. +sp_cpp_cast_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '('. +sp_sizeof_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '...'. +sp_sizeof_ellipsis = ignore # ignore/add/remove/force + +# Add or remove space between 'sizeof...' and '('. +sp_sizeof_ellipsis_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'decltype' and '('. +sp_decltype_paren = ignore # ignore/add/remove/force + +# (Pawn) Add or remove space after the tag keyword. +sp_after_tag = ignore # ignore/add/remove/force + +# Add or remove space inside enum '{' and '}'. +sp_inside_braces_enum = ignore # ignore/add/remove/force + +# Add or remove space inside struct/union '{' and '}'. +sp_inside_braces_struct = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}' +sp_inside_braces_oc_dict = ignore # ignore/add/remove/force + +# Add or remove space after open brace in an unnamed temporary +# direct-list-initialization. +sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force + +# Add or remove space before close brace in an unnamed temporary +# direct-list-initialization. +sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force + +# Add or remove space inside an unnamed temporary direct-list-initialization. +sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force + +# Add or remove space inside '{' and '}'. +sp_inside_braces = ignore # ignore/add/remove/force + +# Add or remove space inside '{}'. +sp_inside_braces_empty = ignore # ignore/add/remove/force + +# Add or remove space around trailing return operator '->'. +sp_trailing_return = ignore # ignore/add/remove/force + +# Add or remove space between return type and function name. A minimum of 1 +# is forced except for pointer return types. +sp_type_func = ignore # ignore/add/remove/force + +# Add or remove space between type and open brace of an unnamed temporary +# direct-list-initialization. +sp_type_brace_init_lst = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' on function declaration. +sp_func_proto_paren = ignore # ignore/add/remove/force + +# Add or remove space between function name and '()' on function declaration +# without parameters. +sp_func_proto_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' with a typedef specifier. +sp_func_type_paren = ignore # ignore/add/remove/force + +# Add or remove space between alias name and '(' of a non-pointer function type typedef. +sp_func_def_paren = ignore # ignore/add/remove/force + +# Add or remove space between function name and '()' on function definition +# without parameters. +sp_func_def_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space inside empty function '()'. +# Overrides sp_after_angle unless use_sp_after_angle_always is set to true. +sp_inside_fparens = ignore # ignore/add/remove/force + +# Add or remove space inside function '(' and ')'. +sp_inside_fparen = ignore # ignore/add/remove/force + +# Add or remove space inside the first parentheses in a function type, as in +# 'void (*x)(...)'. +sp_inside_tparen = ignore # ignore/add/remove/force + +# Add or remove space between the ')' and '(' in a function type, as in +# 'void (*x)(...)'. +sp_after_tparen_close = ignore # ignore/add/remove/force + +# Add or remove space between ']' and '(' when part of a function call. +sp_square_fparen = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '{' of function. +sp_fparen_brace = ignore # ignore/add/remove/force + +# Add or remove space between ')' and '{' of a function call in object +# initialization. +# +# Overrides sp_fparen_brace. +sp_fparen_brace_initializer = ignore # ignore/add/remove/force + +# (Java) Add or remove space between ')' and '{{' of double brace initializer. +sp_fparen_dbrace = ignore # ignore/add/remove/force + +# Add or remove space between function name and '(' on function calls. +sp_func_call_paren = ignore # ignore/add/remove/force + +# Add or remove space between function name and '()' on function calls without +# parameters. If set to ignore (the default), sp_func_call_paren is used. +sp_func_call_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between the user function name and '(' on function +# calls. You need to set a keyword to be a user function in the config file, +# like: +# set func_call_user tr _ i18n +sp_func_call_user_paren = ignore # ignore/add/remove/force + +# Add or remove space inside user function '(' and ')'. +sp_func_call_user_inside_fparen = ignore # ignore/add/remove/force + +# Add or remove space between nested parentheses with user functions, +# i.e. '((' vs. '( ('. +sp_func_call_user_paren_paren = ignore # ignore/add/remove/force + +# Add or remove space between a constructor/destructor and the open +# parenthesis. +sp_func_class_paren = ignore # ignore/add/remove/force + +# Add or remove space between a constructor without parameters or destructor +# and '()'. +sp_func_class_paren_empty = ignore # ignore/add/remove/force + +# Add or remove space between 'return' and '('. +sp_return_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'return' and '{'. +sp_return_brace = ignore # ignore/add/remove/force + +# Add or remove space between '__attribute__' and '('. +sp_attribute_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'defined' and '(' in '#if defined (FOO)'. +sp_defined_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'throw' and '(' in 'throw (something)'. +sp_throw_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'throw' and anything other than '(' as in +# '@throw [...];'. +sp_after_throw = ignore # ignore/add/remove/force + +# Add or remove space between 'catch' and '(' in 'catch (something) { }'. +# If set to ignore, sp_before_sparen is used. +sp_catch_paren = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@catch' and '(' +# in '@catch (something) { }'. If set to ignore, sp_catch_paren is used. +sp_oc_catch_paren = ignore # ignore/add/remove/force + +# (OC) Add or remove space before Objective-C protocol list +# as in '@protocol Protocol' or '@interface MyClass : NSObject'. +sp_before_oc_proto_list = ignore # ignore/add/remove/force + +# (OC) Add or remove space between class name and '(' +# in '@interface className(categoryName):BaseClass' +sp_oc_classname_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'version' and '(' +# in 'version (something) { }'. If set to ignore, sp_before_sparen is used. +sp_version_paren = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'scope' and '(' +# in 'scope (something) { }'. If set to ignore, sp_before_sparen is used. +sp_scope_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'super' and '(' in 'super (something)'. +# +# Default: remove +sp_super_paren = remove # ignore/add/remove/force + +# Add or remove space between 'this' and '(' in 'this (something)'. +# +# Default: remove +sp_this_paren = remove # ignore/add/remove/force + +# Add or remove space between a macro name and its definition. +sp_macro = ignore # ignore/add/remove/force + +# Add or remove space between a macro function ')' and its definition. +sp_macro_func = ignore # ignore/add/remove/force + +# Add or remove space between 'else' and '{' if on the same line. +sp_else_brace = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'else' if on the same line. +sp_brace_else = ignore # ignore/add/remove/force + +# Add or remove space between '}' and the name of a typedef on the same line. +sp_brace_typedef = ignore # ignore/add/remove/force + +# Add or remove space before the '{' of a 'catch' statement, if the '{' and +# 'catch' are on the same line, as in 'catch (decl) {'. +sp_catch_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the '{' of a '@catch' statement, if the '{' +# and '@catch' are on the same line, as in '@catch (decl) {'. +# If set to ignore, sp_catch_brace is used. +sp_oc_catch_brace = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'catch' if on the same line. +sp_brace_catch = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '}' and '@catch' if on the same line. +# If set to ignore, sp_brace_catch is used. +sp_oc_brace_catch = ignore # ignore/add/remove/force + +# Add or remove space between 'finally' and '{' if on the same line. +sp_finally_brace = ignore # ignore/add/remove/force + +# Add or remove space between '}' and 'finally' if on the same line. +sp_brace_finally = ignore # ignore/add/remove/force + +# Add or remove space between 'try' and '{' if on the same line. +sp_try_brace = ignore # ignore/add/remove/force + +# Add or remove space between get/set and '{' if on the same line. +sp_getset_brace = ignore # ignore/add/remove/force + +# Add or remove space between a variable and '{' for C++ uniform +# initialization. +sp_word_brace_init_lst = ignore # ignore/add/remove/force + +# Add or remove space between a variable and '{' for a namespace. +# +# Default: add +sp_word_brace_ns = add # ignore/add/remove/force + +# Add or remove space before the '::' operator. +sp_before_dc = ignore # ignore/add/remove/force + +# Add or remove space after the '::' operator. +sp_after_dc = ignore # ignore/add/remove/force + +# (D) Add or remove around the D named array initializer ':' operator. +sp_d_array_colon = ignore # ignore/add/remove/force + +# Add or remove space after the '!' (not) unary operator. +# +# Default: remove +sp_not = remove # ignore/add/remove/force + +# Add or remove space after the '~' (invert) unary operator. +# +# Default: remove +sp_inv = remove # ignore/add/remove/force + +# Add or remove space after the '&' (address-of) unary operator. This does not +# affect the spacing after a '&' that is part of a type. +# +# Default: remove +sp_addr = remove # ignore/add/remove/force + +# Add or remove space around the '.' or '->' operators. +# +# Default: remove +sp_member = remove # ignore/add/remove/force + +# Add or remove space after the '*' (dereference) unary operator. This does +# not affect the spacing after a '*' that is part of a type. +# +# Default: remove +sp_deref = remove # ignore/add/remove/force + +# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. +# +# Default: remove +sp_sign = remove # ignore/add/remove/force + +# Add or remove space between '++' and '--' the word to which it is being +# applied, as in '(--x)' or 'y++;'. +# +# Default: remove +sp_incdec = remove # ignore/add/remove/force + +# Add or remove space before a backslash-newline at the end of a line. +# +# Default: add +sp_before_nl_cont = add # ignore/add/remove/force + +# (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;' +# or '+(int) bar;'. +sp_after_oc_scope = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in message specs, +# i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'. +sp_after_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in message specs, +# i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'. +sp_before_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};'. +sp_after_oc_dict_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};'. +sp_before_oc_dict_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the colon in message specs, +# i.e. '[object setValue:1];' vs. '[object setValue: 1];'. +sp_after_send_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space before the colon in message specs, +# i.e. '[object setValue:1];' vs. '[object setValue :1];'. +sp_before_send_oc_colon = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the (type) in message specs, +# i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'. +sp_after_oc_type = ignore # ignore/add/remove/force + +# (OC) Add or remove space after the first (type) in message specs, +# i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'. +sp_after_oc_return_type = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@selector' and '(', +# i.e. '@selector(msgName)' vs. '@selector (msgName)'. +# Also applies to '@protocol()' constructs. +sp_after_oc_at_sel = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@selector(x)' and the following word, +# i.e. '@selector(foo) a:' vs. '@selector(foo)a:'. +sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force + +# (OC) Add or remove space inside '@selector' parentheses, +# i.e. '@selector(foo)' vs. '@selector( foo )'. +# Also applies to '@protocol()' constructs. +sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force + +# (OC) Add or remove space before a block pointer caret, +# i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'. +sp_before_oc_block_caret = ignore # ignore/add/remove/force + +# (OC) Add or remove space after a block pointer caret, +# i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'. +sp_after_oc_block_caret = ignore # ignore/add/remove/force + +# (OC) Add or remove space between the receiver and selector in a message, +# as in '[receiver selector ...]'. +sp_after_oc_msg_receiver = ignore # ignore/add/remove/force + +# (OC) Add or remove space after '@property'. +sp_after_oc_property = ignore # ignore/add/remove/force + +# (OC) Add or remove space between '@synchronized' and the open parenthesis, +# i.e. '@synchronized(foo)' vs. '@synchronized (foo)'. +sp_after_oc_synchronized = ignore # ignore/add/remove/force + +# Add or remove space around the ':' in 'b ? t : f'. +sp_cond_colon = ignore # ignore/add/remove/force + +# Add or remove space before the ':' in 'b ? t : f'. +# +# Overrides sp_cond_colon. +sp_cond_colon_before = ignore # ignore/add/remove/force + +# Add or remove space after the ':' in 'b ? t : f'. +# +# Overrides sp_cond_colon. +sp_cond_colon_after = ignore # ignore/add/remove/force + +# Add or remove space around the '?' in 'b ? t : f'. +sp_cond_question = ignore # ignore/add/remove/force + +# Add or remove space before the '?' in 'b ? t : f'. +# +# Overrides sp_cond_question. +sp_cond_question_before = ignore # ignore/add/remove/force + +# Add or remove space after the '?' in 'b ? t : f'. +# +# Overrides sp_cond_question. +sp_cond_question_after = ignore # ignore/add/remove/force + +# In the abbreviated ternary form '(a ?: b)', add or remove space between '?' +# and ':'. +# +# Overrides all other sp_cond_* options. +sp_cond_ternary_short = ignore # ignore/add/remove/force + +# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make +# sense here. +sp_case_label = ignore # ignore/add/remove/force + +# (D) Add or remove space around the D '..' operator. +sp_range = ignore # ignore/add/remove/force + +# Add or remove space after ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_after_for_colon = ignore # ignore/add/remove/force + +# Add or remove space before ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_before_for_colon = ignore # ignore/add/remove/force + +# (D) Add or remove space between 'extern' and '(' as in 'extern (C)'. +sp_extern_paren = ignore # ignore/add/remove/force + +# Add or remove space after the opening of a C++ comment, +# i.e. '// A' vs. '//A'. +sp_cmt_cpp_start = ignore # ignore/add/remove/force + +# If true, space is added with sp_cmt_cpp_start will be added after doxygen +# sequences like '///', '///<', '//!' and '//!<'. +sp_cmt_cpp_doxygen = false # true/false + +# If true, space is added with sp_cmt_cpp_start will be added after Qt +# translator or meta-data comments like '//:', '//=', and '//~'. +sp_cmt_cpp_qttr = false # true/false + +# Add or remove space between #else or #endif and a trailing comment. +sp_endif_cmt = ignore # ignore/add/remove/force + +# Add or remove space after 'new', 'delete' and 'delete[]'. +sp_after_new = ignore # ignore/add/remove/force + +# Add or remove space between 'new' and '(' in 'new()'. +sp_between_new_paren = ignore # ignore/add/remove/force + +# Add or remove space between ')' and type in 'new(foo) BAR'. +sp_after_newop_paren = ignore # ignore/add/remove/force + +# Add or remove space inside parenthesis of the new operator +# as in 'new(foo) BAR'. +sp_inside_newop_paren = ignore # ignore/add/remove/force + +# Add or remove space after the open parenthesis of the new operator, +# as in 'new(foo) BAR'. +# +# Overrides sp_inside_newop_paren. +sp_inside_newop_paren_open = ignore # ignore/add/remove/force + +# Add or remove space before the close parenthesis of the new operator, +# as in 'new(foo) BAR'. +# +# Overrides sp_inside_newop_paren. +sp_inside_newop_paren_close = ignore # ignore/add/remove/force + +# Add or remove space before a trailing or embedded comment. +sp_before_tr_emb_cmt = ignore # ignore/add/remove/force + +# Number of spaces before a trailing or embedded comment. +sp_num_before_tr_emb_cmt = 0 # unsigned number + +# (Java) Add or remove space between an annotation and the open parenthesis. +sp_annotation_paren = ignore # ignore/add/remove/force + +# If true, vbrace tokens are dropped to the previous token and skipped. +sp_skip_vbrace_tokens = false # true/false + +# Add or remove space after 'noexcept'. +sp_after_noexcept = ignore # ignore/add/remove/force + +# Add or remove space after '_'. +sp_vala_after_translation = ignore # ignore/add/remove/force + +# If true, a is inserted after #define. +force_tab_after_define = false # true/false + +# +# Indenting options +# + +# The number of columns to indent per level. Usually 2, 3, 4, or 8. +# +# Default: 8 +indent_columns = 4 # unsigned number + +# The continuation indent. If non-zero, this overrides the indent of '(', '[' +# and '=' continuation indents. Negative values are OK; negative value is +# absolute and not increased for each '(' or '[' level. +# +# For FreeBSD, this is set to 4. +indent_continue = 4 # number + +# The continuation indent, only for class header line(s). If non-zero, this +# overrides the indent of 'class' continuation indents. +indent_continue_class_head = 0 # unsigned number + +# Whether to indent empty lines (i.e. lines which contain only spaces before +# the newline character). +indent_single_newlines = false # true/false + +# The continuation indent for func_*_param if they are true. If non-zero, this +# overrides the indent. +indent_param = 0 # unsigned number + +# How to use tabs when indenting code. +# +# 0: Spaces only +# 1: Indent with tabs to brace level, align with spaces (default) +# 2: Indent and align with tabs, using spaces when not on a tabstop +# +# Default: 1 +indent_with_tabs = 0 # unsigned number + +# Whether to indent comments that are not at a brace level with tabs on a +# tabstop. Requires indent_with_tabs=2. If false, will use spaces. +indent_cmt_with_tabs = false # true/false + +# Whether to indent strings broken by '\' so that they line up. +indent_align_string = false # true/false + +# The number of spaces to indent multi-line XML strings. +# Requires indent_align_string=true. +indent_xml_string = 0 # unsigned number + +# Spaces to indent '{' from level. +indent_brace = 0 # unsigned number + +# Whether braces are indented to the body level. +indent_braces = false # true/false + +# Whether to disable indenting function braces if indent_braces=true. +indent_braces_no_func = false # true/false + +# Whether to disable indenting class braces if indent_braces=true. +indent_braces_no_class = false # true/false + +# Whether to disable indenting struct braces if indent_braces=true. +indent_braces_no_struct = false # true/false + +# Whether to indent based on the size of the brace parent, +# i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. +indent_brace_parent = false # true/false + +# Whether to indent based on the open parenthesis instead of the open brace +# in '({\n'. +indent_paren_open_brace = false # true/false + +# (C#) Whether to indent the brace of a C# delegate by another level. +indent_cs_delegate_brace = false # true/false + +# (C#) Whether to indent a C# delegate (to handle delegates with no brace) by +# another level. +indent_cs_delegate_body = false # true/false + +# Whether to indent the body of a 'namespace'. +indent_namespace = false # true/false + +# Whether to indent only the first namespace, and not any nested namespaces. +# Requires indent_namespace=true. +indent_namespace_single_indent = false # true/false + +# The number of spaces to indent a namespace block. +# If set to zero, use the value indent_columns +indent_namespace_level = 0 # unsigned number + +# If the body of the namespace is longer than this number, it won't be +# indented. Requires indent_namespace=true. 0 means no limit. +indent_namespace_limit = 0 # unsigned number + +# Whether the 'extern "C"' body is indented. +indent_extern = false # true/false + +# Whether the 'class' body is indented. +indent_class = false # true/false + +# Whether to indent the stuff after a leading base class colon. +indent_class_colon = false # true/false + +# Whether to indent based on a class colon instead of the stuff after the +# colon. Requires indent_class_colon=true. +indent_class_on_colon = false # true/false + +# Whether to indent the stuff after a leading class initializer colon. +indent_constr_colon = false # true/false + +# Virtual indent from the ':' for member initializers. +# +# Default: 2 +indent_ctor_init_leading = 2 # unsigned number + +# Additional indent for constructor initializer list. +# Negative values decrease indent down to the first column. +indent_ctor_init = 0 # number + +# Whether to indent 'if' following 'else' as a new block under the 'else'. +# If false, 'else\nif' is treated as 'else if' for indenting purposes. +indent_else_if = false # true/false + +# Amount to indent variable declarations after a open brace. +# +# <0: Relative +# >=0: Absolute +indent_var_def_blk = 0 # number + +# Whether to indent continued variable declarations instead of aligning. +indent_var_def_cont = false # true/false + +# Whether to indent continued shift expressions ('<<' and '>>') instead of +# aligning. Set align_left_shift=false when enabling this. +indent_shift = false # true/false + +# Whether to force indentation of function definitions to start in column 1. +indent_func_def_force_col1 = false # true/false + +# Whether to indent continued function call parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_call_param = false # true/false + +# Whether to indent continued function definition parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_def_param = false # true/false + +# for function definitions, only if indent_func_def_param is false +# Allows to align params when appropriate and indent them when not +# behave as if it was true if paren position is more than this value +# if paren position is more than the option value +indent_func_def_param_paren_pos_threshold = 0 # unsigned number + +# Whether to indent continued function call prototype one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_proto_param = false # true/false + +# Whether to indent continued function call declaration one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_class_param = false # true/false + +# Whether to indent continued class variable constructors one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_ctor_var_param = false # true/false + +# Whether to indent continued template parameter list one indent level, +# rather than aligning parameters under the open parenthesis. +indent_template_param = false # true/false + +# Double the indent for indent_func_xxx_param options. +# Use both values of the options indent_columns and indent_param. +indent_func_param_double = false # true/false + +# Indentation column for standalone 'const' qualifier on a function +# prototype. +indent_func_const = 0 # unsigned number + +# Indentation column for standalone 'throw' qualifier on a function +# prototype. +indent_func_throw = 0 # unsigned number + +# How to indent within a macro followed by a brace on the same line +# This allows reducing the indent in macros that have (for example) +# `do { ... } while (0)` blocks bracketing them. +# +# true: add an indent for the brace on the same line as the macro +# false: do not add an indent for the brace on the same line as the macro +# +# Default: true +indent_macro_brace = true # true/false + +# The number of spaces to indent a continued '->' or '.'. +# Usually set to 0, 1, or indent_columns. +indent_member = 0 # unsigned number + +# Whether lines broken at '.' or '->' should be indented by a single indent. +# The indent_member option will not be effective if this is set to true. +indent_member_single = false # true/false + +# Spaces to indent single line ('//') comments on lines before code. +indent_sing_line_comments = 0 # unsigned number + +# When opening a paren for a control statement (if, for, while, etc), increase +# the indent level by this value. Negative values decrease the indent level. +indent_sparen_extra = -4 # number + +# Whether to indent trailing single line ('//') comments relative to the code +# instead of trying to keep the same absolute column. +indent_relative_single_line_comments = false # true/false + +# Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. +indent_switch_case = 0 # unsigned number + +# indent 'break' with 'case' from 'switch'. +indent_switch_break_with_case = false # true/false + +# Whether to indent preprocessor statements inside of switch statements. +# +# Default: true +indent_switch_pp = true # true/false + +# Spaces to shift the 'case' line, without affecting any other lines. +# Usually 0. +indent_case_shift = 0 # unsigned number + +# Spaces to indent '{' from 'case'. By default, the brace will appear under +# the 'c' in case. Usually set to 0 or indent_columns. Negative values are OK. +indent_case_brace = 4 # number + +# Whether to indent comments found in first column. +indent_col1_comment = false # true/false + +# Whether to indent multi string literal in first column. +indent_col1_multi_string_literal = false # true/false + +# How to indent goto labels. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_label = -4 # number + +# How to indent access specifiers that are followed by a +# colon. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_access_spec = 1 # number + +# Whether to indent the code after an access specifier by one level. +# If true, this option forces 'indent_access_spec=0'. +indent_access_spec_body = false # true/false + +# If an open parenthesis is followed by a newline, whether to indent the next +# line so that it lines up after the open parenthesis (not recommended). +indent_paren_nl = false # true/false + +# How to indent a close parenthesis after a newline. +# +# 0: Indent to body level (default) +# 1: Align under the open parenthesis +# 2: Indent to the brace level +indent_paren_close = 2 # unsigned number + +# Whether to indent the open parenthesis of a function definition, +# if the parenthesis is on its own line. +indent_paren_after_func_def = false # true/false + +# Whether to indent the open parenthesis of a function declaration, +# if the parenthesis is on its own line. +indent_paren_after_func_decl = false # true/false + +# Whether to indent the open parenthesis of a function call, +# if the parenthesis is on its own line. +indent_paren_after_func_call = false # true/false + +# Whether to indent a comma when inside a parenthesis. +# If true, aligns under the open parenthesis. +indent_comma_paren = false # true/false + +# Whether to indent a Boolean operator when inside a parenthesis. +# If true, aligns under the open parenthesis. +indent_bool_paren = false # true/false + +# Whether to indent a semicolon when inside a for parenthesis. +# If true, aligns under the open for parenthesis. +indent_semicolon_for_paren = false # true/false + +# Whether to align the first expression to following ones +# if indent_bool_paren=true. +indent_first_bool_expr = false # true/false + +# Whether to align the first expression to following ones +# if indent_semicolon_for_paren=true. +indent_first_for_expr = false # true/false + +# If an open square is followed by a newline, whether to indent the next line +# so that it lines up after the open square (not recommended). +indent_square_nl = false # true/false + +# (ESQL/C) Whether to preserve the relative indent of 'EXEC SQL' bodies. +indent_preserve_sql = false # true/false + +# Whether to align continued statements at the '='. If false or if the '=' is +# followed by a newline, the next line is indent one tab. +# +# Default: true +indent_align_assign = true # true/false + +# If true, the indentation of the chunks after a '=' sequence will be set at +# LHS token indentation column before '='. +indent_off_after_assign = false # true/false + +# Whether to align continued statements at the '('. If false or the '(' is +# followed by a newline, the next line indent is one tab. +# +# Default: true +indent_align_paren = true # true/false + +# (OC) Whether to indent Objective-C code inside message selectors. +indent_oc_inside_msg_sel = false # true/false + +# (OC) Whether to indent Objective-C blocks at brace level instead of usual +# rules. +indent_oc_block = false # true/false + +# (OC) Indent for Objective-C blocks in a message relative to the parameter +# name. +# +# =0: Use indent_oc_block rules +# >0: Use specified number of spaces to indent +indent_oc_block_msg = 0 # unsigned number + +# (OC) Minimum indent for subsequent parameters +indent_oc_msg_colon = 0 # unsigned number + +# (OC) Whether to prioritize aligning with initial colon (and stripping spaces +# from lines, if necessary). +# +# Default: true +indent_oc_msg_prioritize_first_colon = true # true/false + +# (OC) Whether to indent blocks the way that Xcode does by default +# (from the keyword if the parameter is on its own line; otherwise, from the +# previous indentation level). Requires indent_oc_block_msg=true. +indent_oc_block_msg_xcode_style = false # true/false + +# (OC) Whether to indent blocks from where the brace is, relative to a +# message keyword. Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_keyword = false # true/false + +# (OC) Whether to indent blocks from where the brace is, relative to a message +# colon. Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_colon = false # true/false + +# (OC) Whether to indent blocks from where the block caret is. +# Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_caret = false # true/false + +# (OC) Whether to indent blocks from where the brace caret is. +# Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_brace = false # true/false + +# When indenting after virtual brace open and newline add further spaces to +# reach this minimum indent. +indent_min_vbrace_open = 0 # unsigned number + +# Whether to add further spaces after regular indent to reach next tabstop +# when indenting after virtual brace open and newline. +indent_vbrace_open_on_tabstop = false # true/false + +# How to indent after a brace followed by another token (not a newline). +# true: indent all contained lines to match the token +# false: indent all contained lines to match the brace +# +# Default: true +indent_token_after_brace = true # true/false + +# Whether to indent the body of a C++11 lambda. +indent_cpp_lambda_body = false # true/false + +# How to indent compound literals that are being returned. +# true: add both the indent from return & the compound literal open brace (ie: +# 2 indent levels) +# false: only indent 1 level, don't add the indent for the open brace, only add +# the indent for the return. +# +# Default: true +indent_compound_literal_return = true # true/false + +# (C#) Whether to indent a 'using' block if no braces are used. +# +# Default: true +indent_using_block = true # true/false + +# How to indent the continuation of ternary operator. +# +# 0: Off (default) +# 1: When the `if_false` is a continuation, indent it under `if_false` +# 2: When the `:` is a continuation, indent it under `?` +indent_ternary_operator = 2 # unsigned number + +# Whether to indent the statments inside ternary operator. +indent_inside_ternary_operator = false # true/false + +# If true, the indentation of the chunks after a `return` sequence will be set at return indentation column. +indent_off_after_return = false # true/false + +# If true, the indentation of the chunks after a `return new` sequence will be set at return indentation column. +indent_off_after_return_new = false # true/false + +# If true, the tokens after return are indented with regular single indentation. By default (false) the indentation is after the return token. +indent_single_after_return = false # true/false + +# Whether to ignore indent and alignment for 'asm' blocks (i.e. assume they +# have their own indentation). +indent_ignore_asm_block = false # true/false + +# Don't indent the close parenthesis of a function definition, +# if the parenthesis is on its own line. +donot_indent_func_def_close_paren = false # true/false + +# +# Newline adding and removing options +# + +# Whether to collapse empty blocks between '{' and '}'. +# If true, overrides nl_inside_empty_func +nl_collapse_empty_body = false # true/false + +# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. +nl_assign_leave_one_liners = false # true/false + +# Don't split one-line braced statements inside a 'class xx { }' body. +nl_class_leave_one_liners = false # true/false + +# Don't split one-line enums, as in 'enum foo { BAR = 15 };' +nl_enum_leave_one_liners = false # true/false + +# Don't split one-line get or set functions. +nl_getset_leave_one_liners = false # true/false + +# (C#) Don't split one-line property get or set functions. +nl_cs_property_leave_one_liners = false # true/false + +# Don't split one-line function definitions, as in 'int foo() { return 0; }'. +# might modify nl_func_type_name +nl_func_leave_one_liners = false # true/false + +# Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. +nl_cpp_lambda_leave_one_liners = false # true/false + +# Don't split one-line if/else statements, as in 'if(...) b++;'. +nl_if_leave_one_liners = false # true/false + +# Don't split one-line while statements, as in 'while(...) b++;'. +nl_while_leave_one_liners = false # true/false + +# Don't split one-line for statements, as in 'for(...) b++;'. +nl_for_leave_one_liners = false # true/false + +# (OC) Don't split one-line Objective-C messages. +nl_oc_msg_leave_one_liner = false # true/false + +# (OC) Add or remove newline between method declaration and '{'. +nl_oc_mdef_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between Objective-C block signature and '{'. +nl_oc_block_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove blank line before '@interface' statement. +nl_oc_before_interface = ignore # ignore/add/remove/force + +# (OC) Add or remove blank line before '@implementation' statement. +nl_oc_before_implementation = ignore # ignore/add/remove/force + +# (OC) Add or remove blank line before '@end' statement. +nl_oc_before_end = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between '@interface' and '{'. +nl_oc_interface_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between '@implementation' and '{'. +nl_oc_implementation_brace = ignore # ignore/add/remove/force + +# Add or remove newlines at the start of the file. +nl_start_of_file = ignore # ignore/add/remove/force + +# The minimum number of newlines at the start of the file (only used if +# nl_start_of_file is 'add' or 'force'). +nl_start_of_file_min = 0 # unsigned number + +# Add or remove newline at the end of the file. +nl_end_of_file = ignore # ignore/add/remove/force + +# The minimum number of newlines at the end of the file (only used if +# nl_end_of_file is 'add' or 'force'). +nl_end_of_file_min = 0 # unsigned number + +# Add or remove newline between '=' and '{'. +nl_assign_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between '=' and '['. +nl_assign_square = ignore # ignore/add/remove/force + +# Add or remove newline between '[]' and '{'. +nl_tsquare_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline after '= ['. Will also affect the newline before +# the ']'. +nl_after_square_assign = ignore # ignore/add/remove/force + +# Add or remove newline between a function call's ')' and '{', as in +# 'list_for_each(item, &list) { }'. +nl_fcall_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum' and '{'. +nl_enum_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum' and 'class'. +nl_enum_class = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class' and the identifier. +nl_enum_class_identifier = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class' type and ':'. +nl_enum_identifier_colon = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum class identifier :' and type. +nl_enum_colon_type = ignore # ignore/add/remove/force + +# Add or remove newline between 'struct and '{'. +nl_struct_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'union' and '{'. +nl_union_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'if' and '{'. +nl_if_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'else'. +nl_brace_else = ignore # ignore/add/remove/force + +# Add or remove newline between 'else if' and '{'. If set to ignore, +# nl_if_brace is used instead. +nl_elseif_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'else' and '{'. +nl_else_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'else' and 'if'. +nl_else_if = ignore # ignore/add/remove/force + +# Add or remove newline before '{' opening brace +nl_before_opening_brace_func_class_def = ignore # ignore/add/remove/force + +# Add or remove newline before 'if'/'else if' closing parenthesis. +nl_before_if_closing_paren = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'finally'. +nl_brace_finally = ignore # ignore/add/remove/force + +# Add or remove newline between 'finally' and '{'. +nl_finally_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'try' and '{'. +nl_try_brace = ignore # ignore/add/remove/force + +# Add or remove newline between get/set and '{'. +nl_getset_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'for' and '{'. +nl_for_brace = ignore # ignore/add/remove/force + +# Add or remove newline before the '{' of a 'catch' statement, as in +# 'catch (decl) {'. +nl_catch_brace = ignore # ignore/add/remove/force + +# (OC) Add or remove newline before the '{' of a '@catch' statement, as in +# '@catch (decl) {'. If set to ignore, nl_catch_brace is used. +nl_oc_catch_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'catch'. +nl_brace_catch = ignore # ignore/add/remove/force + +# (OC) Add or remove newline between '}' and '@catch'. If set to ignore, +# nl_brace_catch is used. +nl_oc_brace_catch = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and ']'. +nl_brace_square = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and ')' in a function invocation. +nl_brace_fparen = ignore # ignore/add/remove/force + +# Add or remove newline between 'while' and '{'. +nl_while_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between 'scope (x)' and '{'. +nl_scope_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between 'unittest' and '{'. +nl_unittest_brace = ignore # ignore/add/remove/force + +# (D) Add or remove newline between 'version (x)' and '{'. +nl_version_brace = ignore # ignore/add/remove/force + +# (C#) Add or remove newline between 'using' and '{'. +nl_using_brace = ignore # ignore/add/remove/force + +# Add or remove newline between two open or close braces. Due to general +# newline/brace handling, REMOVE may not work. +nl_brace_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'do' and '{'. +nl_do_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '}' and 'while' of 'do' statement. +nl_brace_while = ignore # ignore/add/remove/force + +# Add or remove newline between 'switch' and '{'. +nl_switch_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'synchronized' and '{'. +nl_synchronized_brace = ignore # ignore/add/remove/force + +# Add a newline between ')' and '{' if the ')' is on a different line than the +# if/for/etc. +# +# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and +# nl_catch_brace. +nl_multi_line_cond = false # true/false + +# Add a newline after '(' if an if/for/while/switch condition spans multiple +# lines +nl_multi_line_sparen_open = ignore # ignore/add/remove/force + +# Add a newline before ')' if an if/for/while/switch condition spans multiple +# lines. Overrides nl_before_if_closing_paren if both are specified. +nl_multi_line_sparen_close = ignore # ignore/add/remove/force + +# Force a newline in a define after the macro name for multi-line defines. +nl_multi_line_define = false # true/false + +# Whether to add a newline before 'case', and a blank line before a 'case' +# statement that follows a ';' or '}'. +nl_before_case = false # true/false + +# Whether to add a newline after a 'case' statement. +nl_after_case = false # true/false + +# Add or remove newline between a case ':' and '{'. +# +# Overrides nl_after_case. +nl_case_colon_brace = ignore # ignore/add/remove/force + +# Add or remove newline between ')' and 'throw'. +nl_before_throw = ignore # ignore/add/remove/force + +# Add or remove newline between 'namespace' and '{'. +nl_namespace_brace = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class. +nl_template_class = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class declaration. +# +# Overrides nl_template_class. +nl_template_class_decl = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<>' of a specialized class declaration. +# +# Overrides nl_template_class_decl. +nl_template_class_decl_special = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class definition. +# +# Overrides nl_template_class. +nl_template_class_def = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<>' of a specialized class definition. +# +# Overrides nl_template_class_def. +nl_template_class_def_special = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template function. +nl_template_func = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template function +# declaration. +# +# Overrides nl_template_func. +nl_template_func_decl = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<>' of a specialized function +# declaration. +# +# Overrides nl_template_func_decl. +nl_template_func_decl_special = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template function +# definition. +# +# Overrides nl_template_func. +nl_template_func_def = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<>' of a specialized function +# definition. +# +# Overrides nl_template_func_def. +nl_template_func_def_special = ignore # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template variable. +nl_template_var = ignore # ignore/add/remove/force + +# Add or remove newline between 'template<...>' and 'using' of a templated +# type alias. +nl_template_using = ignore # ignore/add/remove/force + +# Add or remove newline between 'class' and '{'. +nl_class_brace = ignore # ignore/add/remove/force + +# Add or remove newline before or after (depending on pos_class_comma, +# may not be IGNORE) each',' in the base class list. +nl_class_init_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in the constructor member +# initialization. Related to nl_constr_colon, pos_constr_colon and +# pos_constr_comma. +nl_constr_init_args = ignore # ignore/add/remove/force + +# Add or remove newline before first element, after comma, and after last +# element, in 'enum'. +nl_enum_own_lines = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a function +# definition. +# might be modified by nl_func_leave_one_liners +nl_func_type_name = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name inside a class +# definition. If set to ignore, nl_func_type_name or nl_func_proto_type_name +# is used instead. +nl_func_type_name_class = ignore # ignore/add/remove/force + +# Add or remove newline between class specification and '::' +# in 'void A::f() { }'. Only appears in separate member implementation (does +# not appear with in-line implementation). +nl_func_class_scope = ignore # ignore/add/remove/force + +# Add or remove newline between function scope and name, as in +# 'void A :: f() { }'. +nl_func_scope_name = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a prototype. +nl_func_proto_type_name = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# declaration. +nl_func_paren = ignore # ignore/add/remove/force + +# Overrides nl_func_paren for functions with no parameters. +nl_func_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# definition. +nl_func_def_paren = ignore # ignore/add/remove/force + +# Overrides nl_func_def_paren for functions with no parameters. +nl_func_def_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# call. +nl_func_call_paren = ignore # ignore/add/remove/force + +# Overrides nl_func_call_paren for functions with no parameters. +nl_func_call_paren_empty = ignore # ignore/add/remove/force + +# Add or remove newline after '(' in a function declaration. +nl_func_decl_start = ignore # ignore/add/remove/force + +# Add or remove newline after '(' in a function definition. +nl_func_def_start = ignore # ignore/add/remove/force + +# Overrides nl_func_decl_start when there is only one parameter. +nl_func_decl_start_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_start when there is only one parameter. +nl_func_def_start_single = ignore # ignore/add/remove/force + +# Whether to add a newline after '(' in a function declaration if '(' and ')' +# are in different lines. If false, nl_func_decl_start is used instead. +nl_func_decl_start_multi_line = false # true/false + +# Whether to add a newline after '(' in a function definition if '(' and ')' +# are in different lines. If false, nl_func_def_start is used instead. +nl_func_def_start_multi_line = false # true/false + +# Add or remove newline after each ',' in a function declaration. +nl_func_decl_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function definition. +nl_func_def_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function call. +nl_func_call_args = ignore # ignore/add/remove/force + +# Whether to add a newline after each ',' in a function declaration if '(' +# and ')' are in different lines. If false, nl_func_decl_args is used instead. +nl_func_decl_args_multi_line = false # true/false + +# Whether to add a newline after each ',' in a function definition if '(' +# and ')' are in different lines. If false, nl_func_def_args is used instead. +nl_func_def_args_multi_line = false # true/false + +# Add or remove newline before the ')' in a function declaration. +nl_func_decl_end = ignore # ignore/add/remove/force + +# Add or remove newline before the ')' in a function definition. +nl_func_def_end = ignore # ignore/add/remove/force + +# Overrides nl_func_decl_end when there is only one parameter. +nl_func_decl_end_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_end when there is only one parameter. +nl_func_def_end_single = ignore # ignore/add/remove/force + +# Whether to add a newline before ')' in a function declaration if '(' and ')' +# are in different lines. If false, nl_func_decl_end is used instead. +nl_func_decl_end_multi_line = false # true/false + +# Whether to add a newline before ')' in a function definition if '(' and ')' +# are in different lines. If false, nl_func_def_end is used instead. +nl_func_def_end_multi_line = false # true/false + +# Add or remove newline between '()' in a function declaration. +nl_func_decl_empty = ignore # ignore/add/remove/force + +# Add or remove newline between '()' in a function definition. +nl_func_def_empty = ignore # ignore/add/remove/force + +# Add or remove newline between '()' in a function call. +nl_func_call_empty = ignore # ignore/add/remove/force + +# Whether to add a newline after '(' in a function call, +# has preference over nl_func_call_start_multi_line. +nl_func_call_start = ignore # ignore/add/remove/force + +# Whether to add a newline before ')' in a function call. +nl_func_call_end = ignore # ignore/add/remove/force + +# Whether to add a newline after '(' in a function call if '(' and ')' are in +# different lines. +nl_func_call_start_multi_line = false # true/false + +# Whether to add a newline after each ',' in a function call if '(' and ')' +# are in different lines. +nl_func_call_args_multi_line = false # true/false + +# Whether to add a newline before ')' in a function call if '(' and ')' are in +# different lines. +nl_func_call_end_multi_line = false # true/false + +# Whether to respect nl_func_call_XXX option incase of closure args. +nl_func_call_args_multi_line_ignore_closures = false # true/false + +# Whether to add a newline after '<' of a template parameter list. +nl_template_start = false # true/false + +# Whether to add a newline after each ',' in a template parameter list. +nl_template_args = false # true/false + +# Whether to add a newline before '>' of a template parameter list. +nl_template_end = false # true/false + +# (OC) Whether to put each Objective-C message parameter on a separate line. +# See nl_oc_msg_leave_one_liner. +nl_oc_msg_args = false # true/false + +# Add or remove newline between function signature and '{'. +nl_fdef_brace = ignore # ignore/add/remove/force + +# Add or remove newline between function signature and '{', +# if signature ends with ')'. Overrides nl_fdef_brace. +nl_fdef_brace_cond = ignore # ignore/add/remove/force + +# Add or remove newline between C++11 lambda signature and '{'. +nl_cpp_ldef_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'return' and the return expression. +nl_return_expr = ignore # ignore/add/remove/force + +# Whether to add a newline after semicolons, except in 'for' statements. +nl_after_semicolon = false # true/false + +# (Java) Add or remove newline between the ')' and '{{' of the double brace +# initializer. +nl_paren_dbrace_open = ignore # ignore/add/remove/force + +# Whether to add a newline after the type in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst = ignore # ignore/add/remove/force + +# Whether to add a newline after the open brace in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst_open = ignore # ignore/add/remove/force + +# Whether to add a newline before the close brace in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst_close = ignore # ignore/add/remove/force + +# Whether to add a newline after '{'. This also adds a newline before the +# matching '}'. +nl_after_brace_open = false # true/false + +# Whether to add a newline between the open brace and a trailing single-line +# comment. Requires nl_after_brace_open=true. +nl_after_brace_open_cmt = false # true/false + +# Whether to add a newline after a virtual brace open with a non-empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open = false # true/false + +# Whether to add a newline after a virtual brace open with an empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open_empty = false # true/false + +# Whether to add a newline after '}'. Does not apply if followed by a +# necessary ';'. +nl_after_brace_close = false # true/false + +# Whether to add a newline after a virtual brace close, +# as in 'if (foo) a++; return;'. +nl_after_vbrace_close = false # true/false + +# Add or remove newline between the close brace and identifier, +# as in 'struct { int a; } b;'. Affects enumerations, unions and +# structures. If set to ignore, uses nl_after_brace_close. +nl_brace_struct_var = ignore # ignore/add/remove/force + +# Whether to alter newlines in '#define' macros. +nl_define_macro = false # true/false + +# Whether to alter newlines between consecutive parenthesis closes. The number +# of closing parentheses in a line will depend on respective open parenthesis +# lines. +nl_squeeze_paren_close = false # true/false + +# Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and +# '#endif'. Does not affect top-level #ifdefs. +nl_squeeze_ifdef = false # true/false + +# Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well. +nl_squeeze_ifdef_top_level = false # true/false + +# Add or remove blank line before 'if'. +nl_before_if = ignore # ignore/add/remove/force + +# Add or remove blank line after 'if' statement. Add/Force work only if the +# next token is not a closing brace. +nl_after_if = ignore # ignore/add/remove/force + +# Add or remove blank line before 'for'. +nl_before_for = ignore # ignore/add/remove/force + +# Add or remove blank line after 'for' statement. +nl_after_for = ignore # ignore/add/remove/force + +# Add or remove blank line before 'while'. +nl_before_while = ignore # ignore/add/remove/force + +# Add or remove blank line after 'while' statement. +nl_after_while = ignore # ignore/add/remove/force + +# Add or remove blank line before 'switch'. +nl_before_switch = ignore # ignore/add/remove/force + +# Add or remove blank line after 'switch' statement. +nl_after_switch = ignore # ignore/add/remove/force + +# Add or remove blank line before 'synchronized'. +nl_before_synchronized = ignore # ignore/add/remove/force + +# Add or remove blank line after 'synchronized' statement. +nl_after_synchronized = ignore # ignore/add/remove/force + +# Add or remove blank line before 'do'. +nl_before_do = ignore # ignore/add/remove/force + +# Add or remove blank line after 'do/while' statement. +nl_after_do = ignore # ignore/add/remove/force + +# Whether to put a blank line before 'return' statements, unless after an open +# brace. +nl_before_return = false # true/false + +# Whether to put a blank line after 'return' statements, unless followed by a +# close brace. +nl_after_return = false # true/false + +# Whether to put a blank line before a member '.' or '->' operators. +nl_before_member = ignore # ignore/add/remove/force + +# (Java) Whether to put a blank line after a member '.' or '->' operators. +nl_after_member = ignore # ignore/add/remove/force + +# Whether to double-space commented-entries in 'struct'/'union'/'enum'. +nl_ds_struct_enum_cmt = false # true/false + +# Whether to force a newline before '}' of a 'struct'/'union'/'enum'. +# (Lower priority than eat_blanks_before_close_brace.) +nl_ds_struct_enum_close_brace = false # true/false + +# Add or remove newline before or after (depending on pos_class_colon) a class +# colon, as in 'class Foo : public Bar'. +nl_class_colon = ignore # ignore/add/remove/force + +# Add or remove newline around a class constructor colon. The exact position +# depends on nl_constr_init_args, pos_constr_colon and pos_constr_comma. +nl_constr_colon = ignore # ignore/add/remove/force + +# Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }' +# into a single line. If true, prevents other brace newline rules from turning +# such code into four lines. +nl_namespace_two_to_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced if statements, turning them +# into one-liners, as in 'if(b)\n i++;' => 'if(b) i++;'. +nl_create_if_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced for statements, turning them +# into one-liners, as in 'for (...)\n stmt;' => 'for (...) stmt;'. +nl_create_for_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced while statements, turning +# them into one-liners, as in 'while (expr)\n stmt;' => 'while (expr) stmt;'. +nl_create_while_one_liner = false # true/false + +# Whether to collapse a function definition whose body (not counting braces) +# is only one line so that the entire definition (prototype, braces, body) is +# a single line. +nl_create_func_def_one_liner = false # true/false + +# Whether to collapse a function definition whose body (not counting braces) +# is only one line so that the entire definition (prototype, braces, body) is +# a single line. +nl_create_list_one_liner = false # true/false + +# Whether to split one-line simple unbraced if statements into two lines by +# adding a newline, as in 'if(b) i++;'. +nl_split_if_one_liner = false # true/false + +# Whether to split one-line simple unbraced for statements into two lines by +# adding a newline, as in 'for (...) stmt;'. +nl_split_for_one_liner = false # true/false + +# Whether to split one-line simple unbraced while statements into two lines by +# adding a newline, as in 'while (expr) stmt;'. +nl_split_while_one_liner = false # true/false + +# Don't add a newline before a cpp-comment in a parameter list of a function +# call. +donot_add_nl_before_cpp_comment = false # true/false + +# +# Blank line options +# + +# The maximum number of consecutive newlines (3 = 2 blank lines). +nl_max = 0 # unsigned number + +# The maximum number of consecutive newlines in a function. +nl_max_blank_in_func = 0 # unsigned number + +# The number of newlines inside an empty function body. +# This option is overridden by nl_collapse_empty_body=true +nl_inside_empty_func = 0 # unsigned number + +# The number of newlines before a function prototype. +nl_before_func_body_proto = 0 # unsigned number + +# The number of newlines before a multi-line function definition. +nl_before_func_body_def = 0 # unsigned number + +# The number of newlines before a class constructor/destructor prototype. +nl_before_func_class_proto = 0 # unsigned number + +# The number of newlines before a class constructor/destructor definition. +nl_before_func_class_def = 0 # unsigned number + +# The number of newlines after a function prototype. +nl_after_func_proto = 0 # unsigned number + +# The number of newlines after a function prototype, if not followed by +# another function prototype. +nl_after_func_proto_group = 0 # unsigned number + +# The number of newlines after a class constructor/destructor prototype. +nl_after_func_class_proto = 0 # unsigned number + +# The number of newlines after a class constructor/destructor prototype, +# if not followed by another constructor/destructor prototype. +nl_after_func_class_proto_group = 0 # unsigned number + +# Whether one-line method definitions inside a class body should be treated +# as if they were prototypes for the purposes of adding newlines. +# +# Requires nl_class_leave_one_liners=true. Overrides nl_before_func_body_def +# and nl_before_func_class_def for one-liners. +nl_class_leave_one_liner_groups = false # true/false + +# The number of newlines after '}' of a multi-line function body. +nl_after_func_body = 0 # unsigned number + +# The number of newlines after '}' of a multi-line function body in a class +# declaration. Also affects class constructors/destructors. +# +# Overrides nl_after_func_body. +nl_after_func_body_class = 0 # unsigned number + +# The number of newlines after '}' of a single line function body. Also +# affects class constructors/destructors. +# +# Overrides nl_after_func_body and nl_after_func_body_class. +nl_after_func_body_one_liner = 0 # unsigned number + +# The number of blank lines after a block of variable definitions at the top +# of a function body. +# +# 0: No change (default). +nl_func_var_def_blk = 0 # unsigned number + +# The number of newlines before a block of typedefs. If nl_after_access_spec +# is non-zero, that option takes precedence. +# +# 0: No change (default). +nl_typedef_blk_start = 0 # unsigned number + +# The number of newlines after a block of typedefs. +# +# 0: No change (default). +nl_typedef_blk_end = 0 # unsigned number + +# The maximum number of consecutive newlines within a block of typedefs. +# +# 0: No change (default). +nl_typedef_blk_in = 0 # unsigned number + +# The number of newlines before a block of variable definitions not at the top +# of a function body. If nl_after_access_spec is non-zero, that option takes +# precedence. +# +# 0: No change (default). +nl_var_def_blk_start = 0 # unsigned number + +# The number of newlines after a block of variable definitions not at the top +# of a function body. +# +# 0: No change (default). +nl_var_def_blk_end = 0 # unsigned number + +# The maximum number of consecutive newlines within a block of variable +# definitions. +# +# 0: No change (default). +nl_var_def_blk_in = 0 # unsigned number + +# The minimum number of newlines before a multi-line comment. +# Doesn't apply if after a brace open or another multi-line comment. +nl_before_block_comment = 0 # unsigned number + +# The minimum number of newlines before a single-line C comment. +# Doesn't apply if after a brace open or other single-line C comments. +nl_before_c_comment = 0 # unsigned number + +# The minimum number of newlines before a CPP comment. +# Doesn't apply if after a brace open or other CPP comments. +nl_before_cpp_comment = 0 # unsigned number + +# Whether to force a newline after a multi-line comment. +nl_after_multiline_comment = false # true/false + +# Whether to force a newline after a label's colon. +nl_after_label_colon = false # true/false + +# The number of newlines after '}' or ';' of a struct/enum/union definition. +nl_after_struct = 0 # unsigned number + +# The number of newlines before a class definition. +nl_before_class = 0 # unsigned number + +# The number of newlines after '}' or ';' of a class definition. +nl_after_class = 0 # unsigned number + +# The number of newlines before a namespace. +nl_before_namespace = 0 # unsigned number + +# The number of newlines after '{' of a namespace. This also adds newlines +# before the matching '}'. +# +# 0: Apply eat_blanks_after_open_brace or eat_blanks_before_close_brace if +# applicable, otherwise no change. +# +# Overrides eat_blanks_after_open_brace and eat_blanks_before_close_brace. +nl_inside_namespace = 0 # unsigned number + +# The number of newlines after '}' of a namespace. +nl_after_namespace = 0 # unsigned number + +# The number of newlines before an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +nl_before_access_spec = 0 # unsigned number + +# The number of newlines after an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +# +# Overrides nl_typedef_blk_start and nl_var_def_blk_start. +nl_after_access_spec = 0 # unsigned number + +# The number of newlines between a function definition and the function +# comment, as in '// comment\n void foo() {...}'. +# +# 0: No change (default). +nl_comment_func_def = 0 # unsigned number + +# The number of newlines after a try-catch-finally block that isn't followed +# by a brace close. +# +# 0: No change (default). +nl_after_try_catch_finally = 0 # unsigned number + +# (C#) The number of newlines before and after a property, indexer or event +# declaration. +# +# 0: No change (default). +nl_around_cs_property = 0 # unsigned number + +# (C#) The number of newlines between the get/set/add/remove handlers. +# +# 0: No change (default). +nl_between_get_set = 0 # unsigned number + +# (C#) Add or remove newline between property and the '{'. +nl_property_brace = ignore # ignore/add/remove/force + +# Whether to remove blank lines after '{'. +eat_blanks_after_open_brace = false # true/false + +# Whether to remove blank lines before '}'. +eat_blanks_before_close_brace = false # true/false + +# How aggressively to remove extra newlines not in preprocessor. +# +# 0: No change (default) +# 1: Remove most newlines not handled by other config +# 2: Remove all newlines and reformat completely by config +nl_remove_extra_newlines = 0 # unsigned number + +# (Java) Add or remove newline after an annotation statement. Only affects +# annotations that are after a newline. +nl_after_annotation = ignore # ignore/add/remove/force + +# (Java) Add or remove newline between two annotations. +nl_between_annotation = ignore # ignore/add/remove/force + +# The number of newlines before a whole-file #ifdef. +# +# 0: No change (default). +nl_before_whole_file_ifdef = 0 # unsigned number + +# The number of newlines after a whole-file #ifdef. +# +# 0: No change (default). +nl_after_whole_file_ifdef = 0 # unsigned number + +# The number of newlines before a whole-file #endif. +# +# 0: No change (default). +nl_before_whole_file_endif = 0 # unsigned number + +# The number of newlines after a whole-file #endif. +# +# 0: No change (default). +nl_after_whole_file_endif = 0 # unsigned number + +# +# Positioning options +# + +# The position of arithmetic operators in wrapped expressions. +pos_arith = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of assignment in wrapped expressions. Do not affect '=' +# followed by '{'. +pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of Boolean operators in wrapped expressions. +pos_bool = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of comparison operators in wrapped expressions. +pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of conditional operators, as in the '?' and ':' of +# 'expr ? stmt : stmt', in wrapped expressions. +pos_conditional = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in wrapped expressions. +pos_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in enum entries. +pos_enum_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the base class list if there is more than one +# line. Affects nl_class_init_args. +pos_class_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the constructor initialization list. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. +pos_constr_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of trailing/leading class colon, between class and base class +# list. Affects nl_class_colon. +pos_class_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of colons between constructor and member initialization. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. +pos_constr_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of shift operators in wrapped expressions. +pos_shift = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# +# Line splitting options +# + +# Try to limit code width to N columns. +code_width = 0 # unsigned number + +# Whether to fully split long 'for' statements at semi-colons. +ls_for_split_full = false # true/false + +# Whether to fully split long function prototypes/calls at commas. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_func_split_full = false # true/false + +# Whether to split lines as close to code_width as possible and ignore some +# groupings. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_code_width = false # true/false + +# +# Code alignment options (not left column spaces/tabs) +# + +# Whether to keep non-indenting tabs. +align_keep_tabs = false # true/false + +# Whether to use tabs for aligning. +align_with_tabs = false # true/false + +# Whether to bump out to the next tab when aligning. +align_on_tabstop = false # true/false + +# Whether to right-align numbers. +align_number_right = false # true/false + +# Whether to keep whitespace not required for alignment. +align_keep_extra_space = false # true/false + +# Whether to align variable definitions in prototypes and functions. +align_func_params = false # true/false + +# The span for aligning parameter definitions in function on parameter name. +# +# 0: Don't align (default). +align_func_params_span = 0 # unsigned number + +# The threshold for aligning function parameter definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_func_params_thresh = 0 # number + +# The gap for aligning function parameter definitions. +align_func_params_gap = 0 # unsigned number + +# The span for aligning constructor value. +# +# 0: Don't align (default). +align_constr_value_span = 0 # unsigned number + +# The threshold for aligning constructor value. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_constr_value_thresh = 0 # number + +# The gap for aligning constructor value. +align_constr_value_gap = 0 # unsigned number + +# Whether to align parameters in single-line functions that have the same +# name. The function names must already be aligned with each other. +align_same_func_call_params = false # true/false + +# The span for aligning function-call parameters for single line functions. +# +# 0: Don't align (default). +align_same_func_call_params_span = 0 # unsigned number + +# The threshold for aligning function-call parameters for single line +# functions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_same_func_call_params_thresh = 0 # number + +# The span for aligning variable definitions. +# +# 0: Don't align (default). +align_var_def_span = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of variable definitions. +# +# 0: Part of the type 'void * foo;' (default) +# 1: Part of the variable 'void *foo;' +# 2: Dangling 'void *foo;' +# Dangling: the '*' will not be taken into account when aligning. +align_var_def_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of variable definitions. +# +# 0: Part of the type 'long & foo;' (default) +# 1: Part of the variable 'long &foo;' +# 2: Dangling 'long &foo;' +# Dangling: the '&' will not be taken into account when aligning. +align_var_def_amp_style = 0 # unsigned number + +# The threshold for aligning variable definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_def_thresh = 0 # number + +# The gap for aligning variable definitions. +align_var_def_gap = 0 # unsigned number + +# Whether to align the colon in struct bit fields. +align_var_def_colon = false # true/false + +# The gap for aligning the colon in struct bit fields. +align_var_def_colon_gap = 0 # unsigned number + +# Whether to align any attribute after the variable name. +align_var_def_attribute = false # true/false + +# Whether to align inline struct/enum/union variable definitions. +align_var_def_inline = false # true/false + +# The span for aligning on '=' in assignments. +# +# 0: Don't align (default). +align_assign_span = 0 # unsigned number + +# The span for aligning on '=' in function prototype modifier. +# +# 0: Don't align (default). +align_assign_func_proto_span = 0 # unsigned number + +# The threshold for aligning on '=' in assignments. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_assign_thresh = 0 # number + +# How to apply align_assign_span to function declaration "assignments", i.e. +# 'virtual void foo() = 0' or '~foo() = {default|delete}'. +# +# 0: Align with other assignments (default) +# 1: Align with each other, ignoring regular assignments +# 2: Don't align +align_assign_decl_func = 0 # unsigned number + +# The span for aligning on '=' in enums. +# +# 0: Don't align (default). +align_enum_equ_span = 0 # unsigned number + +# The threshold for aligning on '=' in enums. +# Use a negative number for absolute thresholds. +# +# 0: no limit (default). +align_enum_equ_thresh = 0 # number + +# The span for aligning class member definitions. +# +# 0: Don't align (default). +align_var_class_span = 0 # unsigned number + +# The threshold for aligning class member definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_class_thresh = 0 # number + +# The gap for aligning class member definitions. +align_var_class_gap = 0 # unsigned number + +# The span for aligning struct/union member definitions. +# +# 0: Don't align (default). +align_var_struct_span = 0 # unsigned number + +# The threshold for aligning struct/union member definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_struct_thresh = 0 # number + +# The gap for aligning struct/union member definitions. +align_var_struct_gap = 0 # unsigned number + +# The span for aligning struct initializer values. +# +# 0: Don't align (default). +align_struct_init_span = 0 # unsigned number + +# The span for aligning single-line typedefs. +# +# 0: Don't align (default). +align_typedef_span = 0 # unsigned number + +# The minimum space between the type and the synonym of a typedef. +align_typedef_gap = 0 # unsigned number + +# How to align typedef'd functions with other typedefs. +# +# 0: Don't mix them at all (default) +# 1: Align the open parenthesis with the types +# 2: Align the function type name with the other type names +align_typedef_func = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of typedefs. +# +# 0: Part of the typedef type, 'typedef int * pint;' (default) +# 1: Part of type name: 'typedef int *pint;' +# 2: Dangling: 'typedef int *pint;' +# Dangling: the '*' will not be taken into account when aligning. +align_typedef_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of typedefs. +# +# 0: Part of the typedef type, 'typedef int & intref;' (default) +# 1: Part of type name: 'typedef int &intref;' +# 2: Dangling: 'typedef int &intref;' +# Dangling: the '&' will not be taken into account when aligning. +align_typedef_amp_style = 0 # unsigned number + +# The span for aligning comments that end lines. +# +# 0: Don't align (default). +align_right_cmt_span = 0 # unsigned number + +# Minimum number of columns between preceding text and a trailing comment in +# order for the comment to qualify for being aligned. Must be non-zero to have +# an effect. +align_right_cmt_gap = 0 # unsigned number + +# If aligning comments, whether to mix with comments after '}' and #endif with +# less than three spaces before the comment. +align_right_cmt_mix = false # true/false + +# Whether to only align trailing comments that are at the same brace level. +align_right_cmt_same_level = false # true/false + +# Minimum column at which to align trailing comments. Comments which are +# aligned beyond this column, but which can be aligned in a lesser column, +# may be "pulled in". +# +# 0: Ignore (default). +align_right_cmt_at_col = 0 # unsigned number + +# The span for aligning function prototypes. +# +# 0: Don't align (default). +align_func_proto_span = 0 # unsigned number + +# The threshold for aligning function prototypes. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_func_proto_thresh = 0 # number + +# Minimum gap between the return type and the function name. +align_func_proto_gap = 0 # unsigned number + +# Whether to align function prototypes on the 'operator' keyword instead of +# what follows. +align_on_operator = false # true/false + +# Whether to mix aligning prototype and variable declarations. If true, +# align_var_def_XXX options are used instead of align_func_proto_XXX options. +align_mix_var_proto = false # true/false + +# Whether to align single-line functions with function prototypes. +# Uses align_func_proto_span. +align_single_line_func = false # true/false + +# Whether to align the open brace of single-line functions. +# Requires align_single_line_func=true. Uses align_func_proto_span. +align_single_line_brace = false # true/false + +# Gap for align_single_line_brace. +align_single_line_brace_gap = 0 # unsigned number + +# (OC) The span for aligning Objective-C message specifications. +# +# 0: Don't align (default). +align_oc_msg_spec_span = 0 # unsigned number + +# Whether to align macros wrapped with a backslash and a newline. This will +# not work right if the macro contains a multi-line comment. +align_nl_cont = false # true/false + +# Whether to align macro functions and variables together. +align_pp_define_together = false # true/false + +# The span for aligning on '#define' bodies. +# +# =0: Don't align (default) +# >0: Number of lines (including comments) between blocks +align_pp_define_span = 0 # unsigned number + +# The minimum space between label and value of a preprocessor define. +align_pp_define_gap = 0 # unsigned number + +# Whether to align lines that start with '<<' with previous '<<'. +# +# Default: true +align_left_shift = true # true/false + +# Whether to align comma-separated statements following '<<' (as used to +# initialize Eigen matrices). +align_eigen_comma_init = false # true/false + +# Whether to align text after 'asm volatile ()' colons. +align_asm_colon = false # true/false + +# (OC) Span for aligning parameters in an Objective-C message call +# on the ':'. +# +# 0: Don't align. +align_oc_msg_colon_span = 0 # unsigned number + +# (OC) Whether to always align with the first parameter, even if it is too +# short. +align_oc_msg_colon_first = false # true/false + +# (OC) Whether to align parameters in an Objective-C '+' or '-' declaration +# on the ':'. +align_oc_decl_colon = false # true/false + +# (OC) Whether to not align parameters in an Objectve-C message call if first +# colon is not on next line of the message call (the same way Xcode does +# aligment) +align_oc_msg_colon_xcode_like = false # true/false + +# +# Comment modification options +# + +# Try to wrap comments at N columns. +cmt_width = 0 # unsigned number + +# How to reflow comments. +# +# 0: No reflowing (apart from the line wrapping due to cmt_width) (default) +# 1: No touching at all +# 2: Full reflow +cmt_reflow_mode = 0 # unsigned number + +# Whether to convert all tabs to spaces in comments. If false, tabs in +# comments are left alone, unless used for indenting. +cmt_convert_tab_to_spaces = false # true/false + +# Whether to apply changes to multi-line comments, including cmt_width, +# keyword substitution and leading chars. +# +# Default: true +cmt_indent_multi = false # true/false + +# Whether to group c-comments that look like they are in a block. +cmt_c_group = false # true/false + +# Whether to put an empty '/*' on the first line of the combined c-comment. +cmt_c_nl_start = false # true/false + +# Whether to add a newline before the closing '*/' of the combined c-comment. +cmt_c_nl_end = false # true/false + +# Whether to change cpp-comments into c-comments. +cmt_cpp_to_c = false # true/false + +# Whether to group cpp-comments that look like they are in a block. Only +# meaningful if cmt_cpp_to_c=true. +cmt_cpp_group = false # true/false + +# Whether to put an empty '/*' on the first line of the combined cpp-comment +# when converting to a c-comment. +# +# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. +cmt_cpp_nl_start = false # true/false + +# Whether to add a newline before the closing '*/' of the combined cpp-comment +# when converting to a c-comment. +# +# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. +cmt_cpp_nl_end = false # true/false + +# Whether to put a star on subsequent comment lines. +cmt_star_cont = false # true/false + +# The number of spaces to insert at the start of subsequent comment lines. +cmt_sp_before_star_cont = 0 # unsigned number + +# The number of spaces to insert after the star on subsequent comment lines. +cmt_sp_after_star_cont = 0 # unsigned number + +# For multi-line comments with a '*' lead, remove leading spaces if the first +# and last lines of the comment are the same length. +# +# Default: true +cmt_multi_check_last = true # true/false + +# For multi-line comments with a '*' lead, remove leading spaces if the first +# and last lines of the comment are the same length AND if the length is +# bigger as the first_len minimum. +# +# Default: 4 +cmt_multi_first_len_minimum = 4 # unsigned number + +# Path to a file that contains text to insert at the beginning of a file if +# the file doesn't start with a C/C++ comment. If the inserted text contains +# '$(filename)', that will be replaced with the current file's name. +cmt_insert_file_header = "" # string + +# Path to a file that contains text to insert at the end of a file if the +# file doesn't end with a C/C++ comment. If the inserted text contains +# '$(filename)', that will be replaced with the current file's name. +cmt_insert_file_footer = "" # string + +# Path to a file that contains text to insert before a function definition if +# the function isn't preceded by a C/C++ comment. If the inserted text +# contains '$(function)', '$(javaparam)' or '$(fclass)', these will be +# replaced with, respectively, the name of the function, the javadoc '@param' +# and '@return' stuff, or the name of the class to which the member function +# belongs. +cmt_insert_func_header = "" # string + +# Path to a file that contains text to insert before a class if the class +# isn't preceded by a C/C++ comment. If the inserted text contains '$(class)', +# that will be replaced with the class name. +cmt_insert_class_header = "" # string + +# Path to a file that contains text to insert before an Objective-C message +# specification, if the method isn't preceded by a C/C++ comment. If the +# inserted text contains '$(message)' or '$(javaparam)', these will be +# replaced with, respectively, the name of the function, or the javadoc +# '@param' and '@return' stuff. +cmt_insert_oc_msg_header = "" # string + +# Whether a comment should be inserted if a preprocessor is encountered when +# stepping backwards from a function name. +# +# Applies to cmt_insert_oc_msg_header, cmt_insert_func_header and +# cmt_insert_class_header. +cmt_insert_before_preproc = false # true/false + +# Whether a comment should be inserted if a function is declared inline to a +# class definition. +# +# Applies to cmt_insert_func_header. +# +# Default: true +cmt_insert_before_inlines = true # true/false + +# Whether a comment should be inserted if the function is a class constructor +# or destructor. +# +# Applies to cmt_insert_func_header. +cmt_insert_before_ctor_dtor = false # true/false + +# +# Code modifying options (non-whitespace) +# + +# Add or remove braces on a single-line 'do' statement. +mod_full_brace_do = ignore # ignore/add/remove/force + +# Add or remove braces on a single-line 'for' statement. +mod_full_brace_for = ignore # ignore/add/remove/force + +# (Pawn) Add or remove braces on a single-line function definition. +mod_full_brace_function = ignore # ignore/add/remove/force + +# Add or remove braces on a single-line 'if' statement. Braces will not be +# removed if the braced statement contains an 'else'. +mod_full_brace_if = ignore # ignore/add/remove/force + +# Whether to enforce that all blocks of an 'if'/'else if'/'else' chain either +# have, or do not have, braces. If true, braces will be added if any block +# needs braces, and will only be removed if they can be removed from all +# blocks. +# +# Overrides mod_full_brace_if. +mod_full_brace_if_chain = false # true/false + +# Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. +# If true, mod_full_brace_if_chain will only remove braces from an 'if' that +# does not have an 'else if' or 'else'. +mod_full_brace_if_chain_only = false # true/false + +# Add or remove braces on single-line 'while' statement. +mod_full_brace_while = ignore # ignore/add/remove/force + +# Add or remove braces on single-line 'using ()' statement. +mod_full_brace_using = ignore # ignore/add/remove/force + +# Don't remove braces around statements that span N newlines +mod_full_brace_nl = 0 # unsigned number + +# Whether to prevent removal of braces from 'if'/'for'/'while'/etc. blocks +# which span multiple lines. +# +# Affects: +# mod_full_brace_for +# mod_full_brace_if +# mod_full_brace_if_chain +# mod_full_brace_if_chain_only +# mod_full_brace_while +# mod_full_brace_using +# +# Does not affect: +# mod_full_brace_do +# mod_full_brace_function +mod_full_brace_nl_block_rem_mlcond = false # true/false + +# Add or remove unnecessary parenthesis on 'return' statement. +mod_paren_on_return = ignore # ignore/add/remove/force + +# (Pawn) Whether to change optional semicolons to real semicolons. +mod_pawn_semicolon = false # true/false + +# Whether to fully parenthesize Boolean expressions in 'while' and 'if' +# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. +mod_full_paren_if_bool = false # true/false + +# Whether to remove superfluous semicolons. +mod_remove_extra_semicolon = false # true/false + +# If a function body exceeds the specified number of newlines and doesn't have +# a comment after the close brace, a comment will be added. +mod_add_long_function_closebrace_comment = 0 # unsigned number + +# If a namespace body exceeds the specified number of newlines and doesn't +# have a comment after the close brace, a comment will be added. +mod_add_long_namespace_closebrace_comment = 0 # unsigned number + +# If a class body exceeds the specified number of newlines and doesn't have a +# comment after the close brace, a comment will be added. +mod_add_long_class_closebrace_comment = 0 # unsigned number + +# If a switch body exceeds the specified number of newlines and doesn't have a +# comment after the close brace, a comment will be added. +mod_add_long_switch_closebrace_comment = 0 # unsigned number + +# If an #ifdef body exceeds the specified number of newlines and doesn't have +# a comment after the #endif, a comment will be added. +mod_add_long_ifdef_endif_comment = 0 # unsigned number + +# If an #ifdef or #else body exceeds the specified number of newlines and +# doesn't have a comment after the #else, a comment will be added. +mod_add_long_ifdef_else_comment = 0 # unsigned number + +# Whether to take care of the case by the mod_sort_xx options. +mod_sort_case_sensitive = false # true/false + +# Whether to sort consecutive single-line 'import' statements. +mod_sort_import = false # true/false + +# (C#) Whether to sort consecutive single-line 'using' statements. +mod_sort_using = false # true/false + +# Whether to sort consecutive single-line '#include' statements (C/C++) and +# '#import' statements (Objective-C). Be aware that this has the potential to +# break your code if your includes/imports have ordering dependencies. +mod_sort_include = false # true/false + +# Whether to prioritize '#include' and '#import' statements that contain +# filename without extension when sorting is enabled. +mod_sort_incl_import_prioritize_filename = false # true/false + +# Whether to prioritize '#include' and '#import' statements that does not +# contain extensions when sorting is enabled. +mod_sort_incl_import_prioritize_extensionless = false # true/false + +# Whether to prioritize '#include' and '#import' statements that contain +# angle over quotes when sorting is enabled. +mod_sort_incl_import_prioritize_angle_over_quotes = false # true/false + +# Whether to ignore file extension in '#include' and '#import' statements +# for sorting comparison. +mod_sort_incl_import_ignore_extension = false # true/false + +# Whether to group '#include' and '#import' statements when sorting is enabled. +mod_sort_incl_import_grouping_enabled = false # true/false + +# Whether to move a 'break' that appears after a fully braced 'case' before +# the close brace, as in 'case X: { ... } break;' => 'case X: { ... break; }'. +mod_move_case_break = false # true/false + +# Add or remove braces around a fully braced case statement. Will only remove +# braces if there are no variable declarations in the block. +mod_case_brace = ignore # ignore/add/remove/force + +# Whether to remove a void 'return;' that appears as the last statement in a +# function. +mod_remove_empty_return = false # true/false + +# Add or remove the comma after the last value of an enumeration. +mod_enum_last_comma = ignore # ignore/add/remove/force + +# (OC) Whether to organize the properties. If true, properties will be +# rearranged according to the mod_sort_oc_property_*_weight factors. +mod_sort_oc_properties = false # true/false + +# (OC) Weight of a class property modifier. +mod_sort_oc_property_class_weight = 0 # number + +# (OC) Weight of 'atomic' and 'nonatomic'. +mod_sort_oc_property_thread_safe_weight = 0 # number + +# (OC) Weight of 'readwrite' when organizing properties. +mod_sort_oc_property_readwrite_weight = 0 # number + +# (OC) Weight of a reference type specifier ('retain', 'copy', 'assign', +# 'weak', 'strong') when organizing properties. +mod_sort_oc_property_reference_weight = 0 # number + +# (OC) Weight of getter type ('getter=') when organizing properties. +mod_sort_oc_property_getter_weight = 0 # number + +# (OC) Weight of setter type ('setter=') when organizing properties. +mod_sort_oc_property_setter_weight = 0 # number + +# (OC) Weight of nullability type ('nullable', 'nonnull', 'null_unspecified', +# 'null_resettable') when organizing properties. +mod_sort_oc_property_nullability_weight = 0 # number + +# +# Preprocessor options +# + +# Add or remove indentation of preprocessor directives inside #if blocks +# at brace level 0 (file-level). +pp_indent = ignore # ignore/add/remove/force + +# Whether to indent #if/#else/#endif at the brace level. If false, these are +# indented from column 1. +pp_indent_at_level = false # true/false + +# Specifies the number of columns to indent preprocessors per level +# at brace level 0 (file-level). If pp_indent_at_level=false, also specifies +# the number of columns to indent preprocessors per level +# at brace level > 0 (function-level). +# +# Default: 1 +pp_indent_count = 1 # unsigned number + +# Add or remove space after # based on pp_level of #if blocks. +pp_space = ignore # ignore/add/remove/force + +# Sets the number of spaces per level added with pp_space. +pp_space_count = 0 # unsigned number + +# The indent for '#region' and '#endregion' in C# and '#pragma region' in +# C/C++. Negative values decrease indent down to the first column. +pp_indent_region = 0 # number + +# Whether to indent the code between #region and #endregion. +pp_region_indent_code = false # true/false + +# If pp_indent_at_level=true, sets the indent for #if, #else and #endif when +# not at file-level. Negative values decrease indent down to the first column. +# +# =0: Indent preprocessors using output_tab_size +# >0: Column at which all preprocessors will be indented +pp_indent_if = 0 # number + +# Whether to indent the code between #if, #else and #endif. +pp_if_indent_code = false # true/false + +# Whether to indent '#define' at the brace level. If false, these are +# indented from column 1. +pp_define_at_level = false # true/false + +# Whether to ignore the '#define' body while formatting. +pp_ignore_define_body = false # true/false + +# Whether to indent case statements between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the case statements +# directly inside of. +# +# Default: true +pp_indent_case = true # true/false + +# Whether to indent whole function definitions between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the function definition +# is directly inside of. +# +# Default: true +pp_indent_func_def = true # true/false + +# Whether to indent extern C blocks between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the extern block is +# directly inside of. +# +# Default: true +pp_indent_extern = true # true/false + +# Whether to indent braces directly inside #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the braces are directly +# inside of. +# +# Default: true +pp_indent_brace = true # true/false + +# +# Sort includes options +# + +# The regex for include category with priority 0. +include_category_0 = "" # string + +# The regex for include category with priority 1. +include_category_1 = "" # string + +# The regex for include category with priority 2. +include_category_2 = "" # string + +# +# Use or Do not Use options +# + +# true: indent_func_call_param will be used (default) +# false: indent_func_call_param will NOT be used +# +# Default: true +use_indent_func_call_param = true # true/false + +# The value of the indentation for a continuation line is calculated +# differently if the statement is: +# - a declaration: your case with QString fileName ... +# - an assignment: your case with pSettings = new QSettings( ... +# +# At the second case the indentation value might be used twice: +# - at the assignment +# - at the function call (if present) +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indent_continue will be used only once +# false: indent_continue will be used every time (default) +use_indent_continue_only_once = false # true/false + +# The value might be used twice: +# - at the assignment +# - at the opening brace +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indentation will be used only once +# false: indentation will be used every time (default) +indent_cpp_lambda_only_once = false # true/false + +# Whether sp_after_angle takes precedence over sp_inside_fparen. This was the +# historic behavior, but is probably not the desired behavior, so this is off +# by default. +use_sp_after_angle_always = false # true/false + +# Whether to apply special formatting for Qt SIGNAL/SLOT macros. Essentially, +# this tries to format these so that they match Qt's normalized form (i.e. the +# result of QMetaObject::normalizedSignature), which can slightly improve the +# performance of the QObject::connect call, rather than how they would +# otherwise be formatted. +# +# See options_for_QT.cpp for details. +# +# Default: true +use_options_overriding_for_qt_macros = true # true/false + +# If true: the form feed character is removed from the list +# of whitespace characters. +# See https://en.cppreference.com/w/cpp/string/byte/isspace +use_form_feed_no_more_as_whitespace_character = false # true/false + +# +# Warn levels - 1: error, 2: warning (default), 3: note +# + +# (C#) Warning is given if doing tab-to-\t replacement and we have found one +# in a C# verbatim string literal. +# +# Default: 2 +warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number + +# Limit the number of loops. +# Used by uncrustify.cpp to exit from infinite loop. +# 0: no limit. +debug_max_number_of_loops = 0 # number + +# Set the number of the line to protocol; +# Used in the function prot_the_line if the 2. parameter is zero. +# 0: nothing protocol. +debug_line_number_to_protocol = 0 # number + +# Set the number of second(s) before terminating formatting the current file, +# 0: no timeout. +# only for linux +debug_timeout = 0 # number + +# Meaning of the settings: +# Ignore - do not do any changes +# Add - makes sure there is 1 or more space/brace/newline/etc +# Force - makes sure there is exactly 1 space/brace/newline/etc, +# behaves like Add in some contexts +# Remove - removes space/brace/newline/etc +# +# +# - Token(s) can be treated as specific type(s) with the 'set' option: +# `set tokenType tokenString [tokenString...]` +# +# Example: +# `set BOOL __AND__ __OR__` +# +# tokenTypes are defined in src/token_enum.h, use them without the +# 'CT_' prefix: 'CT_BOOL' => 'BOOL' +# +# +# - Token(s) can be treated as type(s) with the 'type' option. +# `type tokenString [tokenString...]` +# +# Example: +# `type int c_uint_8 Rectangle` +# +# This can also be achieved with `set TYPE int c_uint_8 Rectangle` +# +# +# To embed whitespace in tokenStrings use the '\' escape character, or quote +# the tokenStrings. These quotes are supported: "'` +# +# +# - Support for the auto detection of languages through the file ending can be +# added using the 'file_ext' command. +# `file_ext langType langString [langString..]` +# +# Example: +# `file_ext CPP .ch .cxx .cpp.in` +# +# langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use +# them without the 'LANG_' prefix: 'LANG_CPP' => 'CPP' +# +# +# - Custom macro-based indentation can be set up using 'macro-open', +# 'macro-else' and 'macro-close'. +# `(macro-open | macro-else | macro-close) tokenString` +# +# Example: +# `macro-open BEGIN_TEMPLATE_MESSAGE_MAP` +# `macro-open BEGIN_MESSAGE_MAP` +# `macro-close END_MESSAGE_MAP` +# +# +# option(s) with 'not default' value: 0 +# diff --git a/src/subprojects/packcc/tests/unused_rule_elimination.d/dump.bats b/src/subprojects/packcc/tests/unused_rule_elimination.d/dump.bats new file mode 100644 index 00000000..1ce997d8 --- /dev/null +++ b/src/subprojects/packcc/tests/unused_rule_elimination.d/dump.bats @@ -0,0 +1,8 @@ +#!/usr/bin/env bats + +load "$TESTDIR/utils.sh" + +@test "Testing unused_rule_elimination.d - generation" { + run "$PACKCC" --debug -o "unused_rule_elimination.d/parser" "unused_rule_elimination.d/input.peg" 2>&1 + check_output "unused_rule_elimination.d/expected.txt" +} diff --git a/src/subprojects/packcc/tests/unused_rule_elimination.d/expected.txt b/src/subprojects/packcc/tests/unused_rule_elimination.d/expected.txt new file mode 100644 index 00000000..33ebc733 --- /dev/null +++ b/src/subprojects/packcc/tests/unused_rule_elimination.d/expected.txt @@ -0,0 +1,163 @@ +Rule(name:'statement', ref:0, vars.len:1, capts.len:0, codes.len:2) { + Alternate(max:2, len:2) { + Sequence(max:8, len:5) { + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'e', index:0, name:'expression', rule:'expression') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'(null)', index:void, name:'EOL', rule:'EOL') + Action(index:0, code:{ printf(\"answer=%d\\n\", e); }, vars: + 'e' + ) + } + Sequence(max:4, len:3) { + Quantity(min:0, max:-1) { + Sequence(max:2, len:2) { + Predicate(neg:1) { + Reference(var:'(null)', index:void, name:'EOL', rule:'EOL') + } + Charclass(value:'null') + } + } + Reference(var:'(null)', index:void, name:'EOL', rule:'EOL') + Action(index:1, code:{ printf(\"error\\n\"); }, vars:none) + } + } +} +Rule(name:'expression', ref:2, vars.len:1, capts.len:0, codes.len:1) { + Sequence(max:2, len:2) { + Reference(var:'e', index:0, name:'term', rule:'term') + Action(index:0, code:{ $$ = e; }, vars: + 'e' + ) + } +} +Rule(name:'term', ref:3, vars.len:3, capts.len:0, codes.len:3) { + Alternate(max:4, len:3) { + Sequence(max:8, len:6) { + Reference(var:'l', index:0, name:'term', rule:'term') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:'+') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'r', index:1, name:'factor', rule:'factor') + Action(index:0, code:{ $$ = l + r; }, vars: + 'l' + 'r' + ) + } + Sequence(max:8, len:6) { + Reference(var:'l', index:0, name:'term', rule:'term') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:'-') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'r', index:1, name:'factor', rule:'factor') + Action(index:1, code:{ $$ = l - r; }, vars: + 'l' + 'r' + ) + } + Sequence(max:2, len:2) { + Reference(var:'e', index:2, name:'factor', rule:'factor') + Action(index:2, code:{ $$ = e; }, vars: + 'e' + ) + } + } +} +Rule(name:'factor', ref:5, vars.len:3, capts.len:0, codes.len:3) { + Alternate(max:4, len:3) { + Sequence(max:8, len:6) { + Reference(var:'l', index:0, name:'factor', rule:'factor') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:'*') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'r', index:1, name:'unary', rule:'unary') + Action(index:0, code:{ $$ = l * r; }, vars: + 'l' + 'r' + ) + } + Sequence(max:8, len:6) { + Reference(var:'l', index:0, name:'factor', rule:'factor') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:'/') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'r', index:1, name:'unary', rule:'unary') + Action(index:1, code:{ $$ = l / r; }, vars: + 'l' + 'r' + ) + } + Sequence(max:2, len:2) { + Reference(var:'e', index:2, name:'unary', rule:'unary') + Action(index:2, code:{ $$ = e; }, vars: + 'e' + ) + } + } +} +Rule(name:'unary', ref:5, vars.len:1, capts.len:0, codes.len:3) { + Alternate(max:4, len:3) { + Sequence(max:4, len:4) { + String(value:'+') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'e', index:0, name:'unary', rule:'unary') + Action(index:0, code:{ $$ = +e; }, vars: + 'e' + ) + } + Sequence(max:4, len:4) { + String(value:'-') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'e', index:0, name:'unary', rule:'unary') + Action(index:1, code:{ $$ = -e; }, vars: + 'e' + ) + } + Sequence(max:2, len:2) { + Reference(var:'e', index:0, name:'primary', rule:'primary') + Action(index:2, code:{ $$ = e; }, vars: + 'e' + ) + } + } +} +Rule(name:'primary', ref:1, vars.len:1, capts.len:1, codes.len:2) { + Alternate(max:2, len:2) { + Sequence(max:2, len:2) { + Capture(index:0) { + Quantity(min:1, max:-1) { + Charclass(value:'0-9') + } + } + Action(index:0, code:{ $$ = atoi($1); }, vars: + $1 + ) + } + Sequence(max:8, len:6) { + String(value:'(') + Reference(var:'(null)', index:void, name:'_', rule:'_') + Reference(var:'e', index:0, name:'expression', rule:'expression') + Reference(var:'(null)', index:void, name:'_', rule:'_') + String(value:')') + Action(index:1, code:{ $$ = e; }, vars: + 'e' + ) + } + } +} +Rule(name:'_', ref:14, vars.len:0, capts.len:0, codes.len:0) { + Quantity(min:0, max:-1) { + Charclass(value:' \t') + } +} +Rule(name:'EOL', ref:3, vars.len:0, capts.len:0, codes.len:0) { + Alternate(max:4, len:4) { + String(value:'\n') + String(value:'\r\n') + String(value:'\r') + String(value:';') + } +} +value_type: 'int' +auxil_type: 'void *' +prefix: 'calc' diff --git a/src/subprojects/packcc/tests/unused_rule_elimination.d/input.peg b/src/subprojects/packcc/tests/unused_rule_elimination.d/input.peg new file mode 100644 index 00000000..7d1c13e0 --- /dev/null +++ b/src/subprojects/packcc/tests/unused_rule_elimination.d/input.peg @@ -0,0 +1,35 @@ +%prefix "calc" + +statement <- _ e:expression _ EOL { printf("answer=%d\n", e); } + / ( !EOL . )* EOL { printf("error\n"); } + +expression <- e:term { $$ = e; } + +unused_statement <- _ e:unused_expression _ unused_EOL { printf("answer=%d\n", e); } + / ( !unused_EOL . )* unused_EOL { printf("error\n"); } + +unused_expression <- e:unused_term { $$ = e; } + +unused_term <- l:unused_term _ '+' _ r:factor { $$ = l + r; } + / l:unused_term _ '-' _ r:factor { $$ = l - r; } + / e:factor { $$ = e; } + +unused_EOL <- '\n' / '\r\n' / '\r' / ';' + +term <- l:term _ '+' _ r:factor { $$ = l + r; } + / l:term _ '-' _ r:factor { $$ = l - r; } + / e:factor { $$ = e; } + +factor <- l:factor _ '*' _ r:unary { $$ = l * r; } + / l:factor _ '/' _ r:unary { $$ = l / r; } + / e:unary { $$ = e; } + +unary <- '+' _ e:unary { $$ = +e; } + / '-' _ e:unary { $$ = -e; } + / e:primary { $$ = e; } + +primary <- < [0-9]+ > { $$ = atoi($1); } + / '(' _ e:expression _ ')' { $$ = e; } + +_ <- [ \t]* +EOL <- '\n' / '\r\n' / '\r' / ';' diff --git a/src/subprojects/packcc/tests/utils.sh b/src/subprojects/packcc/tests/utils.sh new file mode 100644 index 00000000..bbdc98b4 --- /dev/null +++ b/src/subprojects/packcc/tests/utils.sh @@ -0,0 +1,28 @@ +test_generate () { + (cd "$BATS_TEST_DIRNAME" && "$PACKCC" -I "$ROOTDIR/import" "${PACKCC_OPTS[@]}" -o "parser" "${1:-input.peg}") +} + +test_compile() { + ${CC:-cc} -I "$BATS_TEST_DIRNAME" "main.c" -o "$BATS_TEST_DIRNAME/parser" "$@" +} + +check_output() { + diff --strip-trailing-cr -uN "${1/input/expected}" --label "${1/input/expected}" <(echo "$output") --label "output" +} + +run_for_input() { + run timeout 5s "$BATS_TEST_DIRNAME/parser" < "$1" + check_output "$1" +} + +in_header() { + grep -Fq "$1" "$BATS_TEST_DIRNAME/parser.h" +} + +in_source() { + grep -Fq "$1" "$BATS_TEST_DIRNAME/parser.c" +} + +get_line() { + sed -n "/$1/=" "$BATS_TEST_DIRNAME/$2" | tail -n1 +} diff --git a/src/subprojects/struct2json.wrap b/src/subprojects/struct2json.wrap new file mode 100644 index 00000000..d272cab2 --- /dev/null +++ b/src/subprojects/struct2json.wrap @@ -0,0 +1,10 @@ +[wrap-git] +directory = struct2json +url = https://github.com/shen390s/struct2json +revision = master +depth = 1 +patch_directory = struct2json +diff_files = struct2json.patch + +[provide] +dependency_names = struct2json diff --git a/src/subprojects/struct2json/.gitattributes b/src/subprojects/struct2json/.gitattributes new file mode 100644 index 00000000..a6ec1ac2 --- /dev/null +++ b/src/subprojects/struct2json/.gitattributes @@ -0,0 +1,40 @@ +* text=auto + +*.S text +*.asm text +*.c text +*.cc text +*.cpp text +*.cxx text +*.h text +*.htm text +*.html text +*.in text +*.ld text +*.m4 text +*.mak text +*.mk text +*.py text +*.rb text +*.s text +*.sct text +*.sh text +*.txt text +*.xml text +Makefile text +AUTHORS text +COPYING text + +*.LZO -text +*.Opt -text +*.Uv2 -text +*.ewp -text +*.eww -text +*.vcproj -text +*.bat -text +*.dos -text +*.icf -text +*.inf -text +*.ini -text +*.sct -text +*.xsd -text diff --git a/src/subprojects/struct2json/LICENSE b/src/subprojects/struct2json/LICENSE new file mode 100644 index 00000000..f631275d --- /dev/null +++ b/src/subprojects/struct2json/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2015 Armink (armink.ztl@gmail.com) +Copyright (c) 2021 YuXuebao (yuxuebao@msn.com) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/src/subprojects/struct2json/README.md b/src/subprojects/struct2json/README.md new file mode 100644 index 00000000..469372cd --- /dev/null +++ b/src/subprojects/struct2json/README.md @@ -0,0 +1,84 @@ +# C结构体与 JSON 快速互转库 + +--- + +## struct2json + +[struct2json](https://github.com/armink/struct2json) 是一个开源的C结构体与 JSON 快速互转库,它可以快速实现 **结构体对象** 与 **JSON 对象** 之间序列化及反序列化要求。快速、简洁的 API 设计,大大降低直接使用 JSON 解析库来实现此类功能的代码复杂度。 + +## 起源 + +把面向对象设计应用到C语言中,是当下很流行的设计思想。由于C语言中没有类,所以一般使用结构体 `struct` 充当类,那么结构体变量就是对象。有了对象之后,很多时候需要考虑对象的序列化及反序列化问题。C语言不像很多高级语言拥有反射等机制,使得对象序列化及反序列化被原生的支持。 + +对于C语言来说,序列化为 JSON 字符串是个不错的选择,所以就得使用 [cJSON](https://github.com/kbranigan/cJSON) 这类 JSON 解析库,但是使用后的代码冗余且逻辑性差,所以萌生对cJSON库进行二次封装,实现一个 struct 与 JSON 之间快速互转的库。 struct2json 就诞生于此。下面是 struct2json 主要使用场景: + +- **持久化** :结构体对象序列化为 JSON 对象后,可直接保存至文件、Flash,实现对结构体对象的掉电存储; +- **通信** :高级语言对JSON支持的很友好,例如: Javascript、Groovy 就对 JSON 具有原生的支持,所以 JSON 也可作为C语言与其他语言软件之间的通信协议格式及对象传递格式; +- **可视化** :序列化为 JSON 后的对象,可以更加直观的展示到控制台或者 UI 上,可用于产品调试、产品二次开发等场景; + +## 如何使用 + +### 声明结构体 + +如下声明了两个结构体,结构体 `Hometown` 是结构体 `Student` 的子结构体 + +```C +/* 籍贯 */ +typedef struct { + char name[16]; +} Hometown; + +/* 学生 */ +typedef struct { + uint8_t id; + uint8_t score[8]; + char name[10]; + double weight; + Hometown hometown; +} Student; +``` + +### 将结构体对象序列化为 JSON 对象 + +|使用前([源文件](https://github.com/armink/struct2json/blob/master/docs/zh/assets/not_use_struct2json.c))|使用后([源文件](https://github.com/armink/struct2json/blob/master/docs/zh/assets/used_struct2json.c))| +|:-----:|:-----:| +|![结构体转JSON-使用前](https://git.oschina.net/Armink/struct2json/raw/master/docs/zh/images/not_use_struct2json.png)| ![结构体转JSON-使用后](https://git.oschina.net/Armink/struct2json/raw/master/docs/zh/images/used_struct2json.png)| + +### 将 JSON 对象反序列化为结构体对象 + +|使用前([源文件](https://github.com/armink/struct2json/blob/master/docs/zh/assets/not_use_struct2json_for_json.c))|使用后([源文件](https://github.com/armink/struct2json/blob/master/docs/zh/assets/used_struct2json_for_json.c))| +|:-----:|:-----:| +|![JSON转结构体-使用前](https://git.oschina.net/Armink/struct2json/raw/master/docs/zh/images/not_use_struct2json_for_json.png)| ![JSON转结构体-使用后](https://git.oschina.net/Armink/struct2json/raw/master/docs/zh/images/used_struct2json_for_json.png)| + +### V2.0版本新增功能【yuxuebao】 +#### 1) 更新cJSON库至1.7.12版本,并扩充实现,支持int64 (long long)类型数据。PS:cJSON原来int64类型以double方式处理,如果超过16位会有精度损失。 +#### 2) 扩展struct2json功能,增加支持结构体内包含结构体成员,支持包含数组成员。 +#### 3) 增加struct2json 结构体与JSON转换代码自动生成的Python脚本,支持从头文件中提取结构体定义,并根据结构体定义自动生成结构体与JSON互转代码,并提供相关示例。 + +### V2.0 使用说明: +#### 1) 提取结构体定义: + 将头文件(eg:mc_usr_def.h)放在demo\inc目录下; + 执行generate_struct_defination.py,生成struct_defination.txt; +#### 2) 生成结构体与JSON互转代码: + 执行generate_s2j_code.py,根据结构体定义自动生成结构体与JSON互转代码:my_struct_2_json.c,my_struct_2_json.h; + 该脚本支持的参数类型有 基本类型 和 结构体类型,enum和指针按int处理,不支持union和位域; + 支持的数组类型:支持基本类型一维数组,结构体一维数组,字符二维数组(字符串数组) +#### 3) 测试结构体与JSON转换: + cd demo + 编译测试代码,gcc ../cJSON/cJSON.c ../struct2json/src/*.c ./*.c -I ../cJSON/ -I ../struct2json/inc/ -lm -DDEBUGS2J -g -o tests2j + 测试 ./tests2j + 查看output输出和生成的JSON样例文件struct_defination.json; + 预期输出:*:strcmp:0 *:strcmp:0 *:json_cmp:1 + +欢迎大家 **fork and pull request**([Github](https://github.com/armink/struct2json)|[OSChina](http://git.oschina.net/armink/struct2json)|[Coding](https://coding.net/u/armink/p/struct2json/git)) 。如果觉得这个开源项目很赞,可以点击[项目主页](https://github.com/armink/struct2json) 右上角的**Star**,同时把它推荐给更多有需要的朋友。 + +## 文档 + +具体内容参考[`\docs\zh\`](https://github.com/armink/struct2json/tree/master/docs/zh)下的文件。务必保证在 **阅读文档** 后再使用。 + +## 许可 +- Armink (original author) +- Yu Xuebao (current maintainer) +- and the other contributors (CONTRIBUTORS.md) + +MIT Copyright (c) armink.ztl@gmail.com diff --git a/src/subprojects/struct2json/cJSON/cJSON.c b/src/subprojects/struct2json/cJSON/cJSON.c new file mode 100644 index 00000000..64e11c61 --- /dev/null +++ b/src/subprojects/struct2json/cJSON/cJSON.c @@ -0,0 +1,3202 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_LOCALES +#include +#endif + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0/0.0 +#endif +#endif + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +{ + if (!cJSON_IsString(item)) + { + return NULL; + } + + return item->valuestring; +} + +CJSON_PUBLIC(long long) cJSON_GetIntValue(const cJSON * const item) +{ + if (!cJSON_IsInt(item)) + { + return 0; + } + + return item->valueint; +} + + +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +{ + if (!cJSON_IsNumber(item)) + { + return (double) NAN; + } + + return item->valuedouble; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(CJSON_CDECL *allocate)(size_t size); + void (CJSON_CDECL *deallocate)(void *pointer); + void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ +static void * CJSON_CDECL internal_malloc(size_t size) +{ + return malloc(size); +} +static void CJSON_CDECL internal_free(void *pointer) +{ + free(pointer); +} +static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char *after_end_int = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + cJSON_bool is_integer = true; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + is_integer = false; + break; + case '.': + number_c_string[i] = decimal_point; + is_integer = false; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + return false; /* parse_error */ + } + + item->valuedouble = number; + item->type = cJSON_Number; + + if (is_integer) + { + item->type = cJSON_Int; + item->valueint = strtoll((const char*)number_c_string, (char**)&after_end_int, 10); + if (number_c_string == after_end_int) + { + return false; /* parse_error */ + } + } + /* use saturation in case of overflow */ + else if (number >= LLONG_MAX) + { + item->valueint = LLONG_MAX; + } + else if (number <= (double)LLONG_MIN) + { + item->valueint = LLONG_MIN; + } + else + { + item->valueint = (long long)number; + } + + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= LLONG_MAX) + { + object->valueint = LLONG_MAX; + } + else if (number <= (double)LLONG_MIN) + { + object->valueint = LLONG_MIN; + } + else + { + object->valueint = (long long)number; + } + + return object->valuedouble = number; +} + +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ + if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) + { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) + { + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); + if (copy == NULL) + { + return NULL; + } + if (object->valuestring != NULL) + { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + + memcpy(newbuffer, p->buffer, p->offset + 1); + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* securely comparison of floating-point variables */ +static cJSON_bool compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test = 0.0; + + if (output_buffer == NULL) + { + return false; + } + + if (item->type == cJSON_Int) + { + length = sprintf((char*)number_buffer, "%lld", item->valueint); + } + else /*item->type == cJSON_Number */ + { + /* This checks for NaN and Infinity */ + if (isnan(d) || isinf(d)) + { + length = sprintf((char*)number_buffer, "null"); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) + { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char*)number_buffer, "%1.17g", d); + } + } + } + + /* sprintf failed or buffer overrun occurred */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + if (cannot_access_at_index(buffer, 0)) + { + return buffer; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) + { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL || 0 == buffer_length) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = buffer_length; + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + buffer->buffer = NULL; + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + } + + if (printed != NULL) + { + hooks->deallocate(printed); + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((length < 0) || (buffer == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buffer; + p.length = (size_t)length; + p.offset = 0; + p.noalloc = true; + p.format = format; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_Bool; + item->valueint = 0; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_Bool; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '+') ||(buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + case cJSON_Bool: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + + if (item->valueint) + { + strcpy((char*)output, "true"); + } + else + { + strcpy((char*)output, "false"); + } + + return true; + + case cJSON_Int: + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { + goto fail; /* failed to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + if ((current_element == NULL) || (current_element->string == NULL)) { + return NULL; + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL) || (array == item)) + { + return false; + } + + child = array->child; + /* + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + item->prev = item; + item->next = NULL; + } + else + { + /* append to the end */ + if (child->prev) + { + suffix_object(child->prev, item); + array->child->prev = item; + } + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + return add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + char *new_key = NULL; + int new_type = cJSON_Invalid; + + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) + { + return false; + } + + if (constant_key) + { + new_key = (char*)cast_away_const(string); + new_type = item->type | cJSON_StringIsConst; + } + else + { + new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (new_key == NULL) + { + return false; + } + + new_type = item->type & ~cJSON_StringIsConst; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + item->string = new_key; + item->type = new_type; + + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return false; + } + + return add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return false; + } + + return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddIntToObject(cJSON * const object, const char * const name, const long long integer) +{ + cJSON *int_item = cJSON_CreateInt(integer); + if (add_item_to_object(object, name, int_item, &global_hooks, false)) + { + return int_item; + } + + cJSON_Delete(int_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +{ + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL)) + { + return NULL; + } + + if (item != parent->child) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + else if (item->next == NULL) + { + /* last element */ + parent->child->prev = item->prev; + } + + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0) + { + return false; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + return add_item_to_array(array, newitem); + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (parent->child == item) + { + if (parent->child->prev == parent->child) + { + replacement->prev = replacement; + } + parent->child = replacement; + } + else + { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the parent's child + */ + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) + { + parent->child->prev = replacement; + } + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return false; + } + + return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + replacement->type &= ~cJSON_StringIsConst; + + return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Bool; + item->valueint = 1; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Bool; + item->valueint = 0; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Bool; + item->valueint = b; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateInt(long long integer) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Int; + item->valuedouble = (double)integer; + item->valueint = integer; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= LLONG_MAX) + { + item->valueint = LLONG_MAX; + } + else if (num <= (double)LLONG_MIN) + { + item->valueint = LLONG_MIN; + } + else + { + item->valueint = (long long)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateInt(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((double)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0;a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + if (newitem && newitem->child) + { + newitem->child->prev = newchild; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +static void skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if (((*input)[0] == '*') && ((*input)[1] == '/')) + { + *input += static_strlen("*/"); + return; + } + } +} + +static void minify_string(char **input, char **output) { + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + char *into = json; + + if (json == NULL) + { + return; + } + + while (json[0] != '\0') + { + switch (json[0]) + { + case ' ': + case '\t': + case '\r': + case '\n': + json++; + break; + + case '/': + if (json[1] == '/') + { + skip_oneline_comment(&json); + } + else if (json[1] == '*') + { + skip_multiline_comment(&json); + } else { + json++; + } + break; + + case '\"': + minify_string(&json, (char**)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return( ((item->type & 0xFF) == cJSON_Bool) && (item->valueint == 0)); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return( ((item->type & 0xFF) == cJSON_Bool) && (item->valueint)); +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Bool ; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInt(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Int; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return ((item->type & 0xFF) == cJSON_Number || (item->type & 0xFF) == cJSON_Int); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + int type; + + if ((a == NULL) || (b == NULL) || cJSON_IsInvalid(a)) + { + return false; + } + + type = a->type & 0xFF; + + if ((a->type & 0xFF) != (b->type & 0xFF)) + { + if (((a->type & 0xFF) == cJSON_Int && (b->type & 0xFF) == cJSON_Number) || + ((b->type & 0xFF) == cJSON_Int && (a->type & 0xFF) == cJSON_Number)) + { + type = cJSON_Number; + } + else + { + return false; + } + } + + /* check if type is valid */ + switch (type) + { + case cJSON_Bool: + case cJSON_Int: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (type) + { + /* in these cases and equal type is enough */ + case cJSON_NULL: + return true; + case cJSON_Bool: + case cJSON_Int: + if (a->valueint == b->valueint) + { + return true; + } + return false; + case cJSON_Number: + if (compare_double(a->valuedouble, b->valuedouble)) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); +} diff --git a/src/subprojects/struct2json/cJSON/cJSON.h b/src/subprojects/struct2json/cJSON/cJSON.h new file mode 100644 index 00000000..a52f2195 --- /dev/null +++ b/src/subprojects/struct2json/cJSON/cJSON.h @@ -0,0 +1,297 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +#define CJSON_CDECL __cdecl +#define CJSON_STDCALL __stdcall + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type CJSON_STDCALL +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#endif +#else /* !__WINDOWS__ */ +#define CJSON_CDECL +#define CJSON_STDCALL + +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 15 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_Bool (1 << 0) +#define cJSON_Int (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* If value is not in [LLONG_MIN, LLONG_MAX], use cJSON_SetNumberValue instead */ + long long valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void (CJSON_CDECL *free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); +CJSON_PUBLIC(long long) cJSON_GetIntValue(const cJSON * const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsInt(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateInt(long long integer); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detach items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will + * need to be released. With recurse!=0, it will duplicate any children connected to the item. + * The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. + * The input pointer json cannot point to a read-only address area, such as a string constant, + * but should point to a readable and writable adress area. */ +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddIntToObject(cJSON * const object, const char * const name, const long long integer); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valuedouble = (object)->valueint = (number): (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/subprojects/struct2json/cJSON/cJSON_Utils.c b/src/subprojects/struct2json/cJSON/cJSON_Utils.c new file mode 100644 index 00000000..d81563c8 --- /dev/null +++ b/src/subprojects/struct2json/cJSON/cJSON_Utils.c @@ -0,0 +1,1498 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUCC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUCC__ +#pragma GCC visibility pop +#endif + +#include "cJSON_Utils.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +static unsigned char* cJSONUtils_strdup(const unsigned char* const string) +{ + size_t length = 0; + unsigned char *copy = NULL; + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*) cJSON_malloc(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +/* string comparison which doesn't consider NULL pointers equal */ +static int compare_strings(const unsigned char *string1, const unsigned char *string2, const cJSON_bool case_sensitive) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + if (case_sensitive) + { + return strcmp((const char*)string1, (const char*)string2); + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +/* securely comparison of floating-point variables */ +static cJSON_bool compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + + +/* Compare the next path element of two JSON pointers, two NULL pointers are considered unequal: */ +static cJSON_bool compare_pointers(const unsigned char *name, const unsigned char *pointer, const cJSON_bool case_sensitive) +{ + if ((name == NULL) || (pointer == NULL)) + { + return false; + } + + for (; (*name != '\0') && (*pointer != '\0') && (*pointer != '/'); (void)name++, pointer++) /* compare until next '/' */ + { + if (*pointer == '~') + { + /* check for escaped '~' (~0) and '/' (~1) */ + if (((pointer[1] != '0') || (*name != '~')) && ((pointer[1] != '1') || (*name != '/'))) + { + /* invalid escape sequence or wrong character in *name */ + return false; + } + else + { + pointer++; + } + } + else if ((!case_sensitive && (tolower(*name) != tolower(*pointer))) || (case_sensitive && (*name != *pointer))) + { + return false; + } + } + if (((*pointer != 0) && (*pointer != '/')) != (*name != 0)) + { + /* one string has ended, the other not */ + return false;; + } + + return true; +} + +/* calculate the length of a string if encoded as JSON pointer with ~0 and ~1 escape sequences */ +static size_t pointer_encoded_length(const unsigned char *string) +{ + size_t length; + for (length = 0; *string != '\0'; (void)string++, length++) + { + /* character needs to be escaped? */ + if ((*string == '~') || (*string == '/')) + { + length++; + } + } + + return length; +} + +/* copy a string while escaping '~' and '/' with ~0 and ~1 JSON pointer escape codes */ +static void encode_string_as_pointer(unsigned char *destination, const unsigned char *source) +{ + for (; source[0] != '\0'; (void)source++, destination++) + { + if (source[0] == '/') + { + destination[0] = '~'; + destination[1] = '1'; + destination++; + } + else if (source[0] == '~') + { + destination[0] = '~'; + destination[1] = '0'; + destination++; + } + else + { + destination[0] = source[0]; + } + } + + destination[0] = '\0'; +} + +CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target) +{ + size_t child_index = 0; + cJSON *current_child = 0; + + if ((object == NULL) || (target == NULL)) + { + return NULL; + } + + if (object == target) + { + /* found */ + return (char*)cJSONUtils_strdup((const unsigned char*)""); + } + + /* recursively search all children of the object or array */ + for (current_child = object->child; current_child != NULL; (void)(current_child = current_child->next), child_index++) + { + unsigned char *target_pointer = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(current_child, target); + /* found the target? */ + if (target_pointer != NULL) + { + if (cJSON_IsArray(object)) + { + /* reserve enough memory for a 64 bit integer + '/' and '\0' */ + unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + 20 + sizeof("/")); + /* check if conversion to unsigned long is valid + * This should be eliminated at compile time by dead code elimination + * if size_t is an alias of unsigned long, or if it is bigger */ + if (child_index > ULONG_MAX) + { + cJSON_free(target_pointer); + cJSON_free(full_pointer); + return NULL; + } + sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* / */ + cJSON_free(target_pointer); + + return (char*)full_pointer; + } + + if (cJSON_IsObject(object)) + { + unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + pointer_encoded_length((unsigned char*)current_child->string) + 2); + full_pointer[0] = '/'; + encode_string_as_pointer(full_pointer + 1, (unsigned char*)current_child->string); + strcat((char*)full_pointer, (char*)target_pointer); + cJSON_free(target_pointer); + + return (char*)full_pointer; + } + + /* reached leaf of the tree, found nothing */ + cJSON_free(target_pointer); + return NULL; + } + } + + /* not found */ + return NULL; +} + +/* non broken version of cJSON_GetArrayItem */ +static cJSON *get_array_item(const cJSON *array, size_t item) +{ + cJSON *child = array ? array->child : NULL; + while ((child != NULL) && (item > 0)) + { + item--; + child = child->next; + } + + return child; +} + +static cJSON_bool decode_array_index_from_pointer(const unsigned char * const pointer, size_t * const index) +{ + size_t parsed_index = 0; + size_t position = 0; + + if ((pointer[0] == '0') && ((pointer[1] != '\0') && (pointer[1] != '/'))) + { + /* leading zeroes are not permitted */ + return 0; + } + + for (position = 0; (pointer[position] >= '0') && (pointer[0] <= '9'); position++) + { + parsed_index = (10 * parsed_index) + (size_t)(pointer[position] - '0'); + + } + + if ((pointer[position] != '\0') && (pointer[position] != '/')) + { + return 0; + } + + *index = parsed_index; + + return 1; +} + +static cJSON *get_item_from_pointer(cJSON * const object, const char * pointer, const cJSON_bool case_sensitive) +{ + cJSON *current_element = object; + + if (pointer == NULL) + { + return NULL; + } + + /* follow path of the pointer */ + while ((pointer[0] == '/') && (current_element != NULL)) + { + pointer++; + if (cJSON_IsArray(current_element)) + { + size_t index = 0; + if (!decode_array_index_from_pointer((const unsigned char*)pointer, &index)) + { + return NULL; + } + + current_element = get_array_item(current_element, index); + } + else if (cJSON_IsObject(current_element)) + { + current_element = current_element->child; + /* GetObjectItem. */ + while ((current_element != NULL) && !compare_pointers((unsigned char*)current_element->string, (const unsigned char*)pointer, case_sensitive)) + { + current_element = current_element->next; + } + } + else + { + return NULL; + } + + /* skip to the next path token or end of string */ + while ((pointer[0] != '\0') && (pointer[0] != '/')) + { + pointer++; + } + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer) +{ + return get_item_from_pointer(object, pointer, false); +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer) +{ + return get_item_from_pointer(object, pointer, true); +} + +/* JSON Patch implementation. */ +static void decode_pointer_inplace(unsigned char *string) +{ + unsigned char *decoded_string = string; + + if (string == NULL) { + return; + } + + for (; *string; (void)decoded_string++, string++) + { + if (string[0] == '~') + { + if (string[1] == '0') + { + decoded_string[0] = '~'; + } + else if (string[1] == '1') + { + decoded_string[1] = '/'; + } + else + { + /* invalid escape sequence */ + return; + } + + string++; + } + } + + decoded_string[0] = '\0'; +} + +/* non-broken cJSON_DetachItemFromArray */ +static cJSON *detach_item_from_array(cJSON *array, size_t which) +{ + cJSON *c = array->child; + while (c && (which > 0)) + { + c = c->next; + which--; + } + if (!c) + { + /* item doesn't exist */ + return NULL; + } + if (c != array->child) + { + /* not the first element */ + c->prev->next = c->next; + } + if (c->next) + { + c->next->prev = c->prev; + } + if (c == array->child) + { + array->child = c->next; + } + else if (c->next == NULL) + { + array->child->prev = c->prev; + } + /* make sure the detached item doesn't point anywhere anymore */ + c->prev = c->next = NULL; + + return c; +} + +/* detach an item at the given path */ +static cJSON *detach_path(cJSON *object, const unsigned char *path, const cJSON_bool case_sensitive) +{ + unsigned char *parent_pointer = NULL; + unsigned char *child_pointer = NULL; + cJSON *parent = NULL; + cJSON *detached_item = NULL; + + /* copy path and split it in parent and child */ + parent_pointer = cJSONUtils_strdup(path); + if (parent_pointer == NULL) { + goto cleanup; + } + + child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); /* last '/' */ + if (child_pointer == NULL) + { + goto cleanup; + } + /* split strings */ + child_pointer[0] = '\0'; + child_pointer++; + + parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive); + decode_pointer_inplace(child_pointer); + + if (cJSON_IsArray(parent)) + { + size_t index = 0; + if (!decode_array_index_from_pointer(child_pointer, &index)) + { + goto cleanup; + } + detached_item = detach_item_from_array(parent, index); + } + else if (cJSON_IsObject(parent)) + { + detached_item = cJSON_DetachItemFromObject(parent, (char*)child_pointer); + } + else + { + /* Couldn't find object to remove child from. */ + goto cleanup; + } + +cleanup: + if (parent_pointer != NULL) + { + cJSON_free(parent_pointer); + } + + return detached_item; +} + +/* sort lists using mergesort */ +static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive) +{ + cJSON *first = list; + cJSON *second = list; + cJSON *current_item = list; + cJSON *result = list; + cJSON *result_tail = NULL; + + if ((list == NULL) || (list->next == NULL)) + { + /* One entry is sorted already. */ + return result; + } + + while ((current_item != NULL) && (current_item->next != NULL) && (compare_strings((unsigned char*)current_item->string, (unsigned char*)current_item->next->string, case_sensitive) < 0)) + { + /* Test for list sorted. */ + current_item = current_item->next; + } + if ((current_item == NULL) || (current_item->next == NULL)) + { + /* Leave sorted lists unmodified. */ + return result; + } + + /* reset pointer to the beginning */ + current_item = list; + while (current_item != NULL) + { + /* Walk two pointers to find the middle. */ + second = second->next; + current_item = current_item->next; + /* advances current_item two steps at a time */ + if (current_item != NULL) + { + current_item = current_item->next; + } + } + if ((second != NULL) && (second->prev != NULL)) + { + /* Split the lists */ + second->prev->next = NULL; + second->prev = NULL; + } + + /* Recursively sort the sub-lists. */ + first = sort_list(first, case_sensitive); + second = sort_list(second, case_sensitive); + result = NULL; + + /* Merge the sub-lists */ + while ((first != NULL) && (second != NULL)) + { + cJSON *smaller = NULL; + if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, case_sensitive) < 0) + { + smaller = first; + } + else + { + smaller = second; + } + + if (result == NULL) + { + /* start merged list with the smaller element */ + result_tail = smaller; + result = smaller; + } + else + { + /* add smaller element to the list */ + result_tail->next = smaller; + smaller->prev = result_tail; + result_tail = smaller; + } + + if (first == smaller) + { + first = first->next; + } + else + { + second = second->next; + } + } + + if (first != NULL) + { + /* Append rest of first list. */ + if (result == NULL) + { + return first; + } + result_tail->next = first; + first->prev = result_tail; + } + if (second != NULL) + { + /* Append rest of second list */ + if (result == NULL) + { + return second; + } + result_tail->next = second; + second->prev = result_tail; + } + + return result; +} + +static void sort_object(cJSON * const object, const cJSON_bool case_sensitive) +{ + if (object == NULL) + { + return; + } + object->child = sort_list(object->child, case_sensitive); +} + +static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) + { + /* mismatched type. */ + return false; + } + switch (a->type & 0xFF) + { + case cJSON_Number: + /* numeric mismatch. */ + if ((a->valueint != b->valueint) || (!compare_double(a->valuedouble, b->valuedouble))) + { + return false; + } + else + { + return true; + } + + case cJSON_Int: + /* numeric mismatch. */ + if (a->valueint != b->valueint) + { + return false; + } + else + { + return true; + } + + case cJSON_String: + /* string mismatch. */ + if (strcmp(a->valuestring, b->valuestring) != 0) + { + return false; + } + else + { + return true; + } + + case cJSON_Array: + for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next) + { + cJSON_bool identical = compare_json(a, b, case_sensitive); + if (!identical) + { + return false; + } + } + + /* array size mismatch? (one of both children is not NULL) */ + if ((a != NULL) || (b != NULL)) + { + return false; + } + else + { + return true; + } + + case cJSON_Object: + sort_object(a, case_sensitive); + sort_object(b, case_sensitive); + for ((void)(a = a->child), b = b->child; (a != NULL) && (b != NULL); (void)(a = a->next), b = b->next) + { + cJSON_bool identical = false; + /* compare object keys */ + if (compare_strings((unsigned char*)a->string, (unsigned char*)b->string, case_sensitive)) + { + /* missing member */ + return false; + } + identical = compare_json(a, b, case_sensitive); + if (!identical) + { + return false; + } + } + + /* object length mismatch (one of both children is not null) */ + if ((a != NULL) || (b != NULL)) + { + return false; + } + else + { + return true; + } + + default: + break; + } + + /* null, true or false */ + return true; +} + +/* non broken version of cJSON_InsertItemInArray */ +static cJSON_bool insert_item_in_array(cJSON *array, size_t which, cJSON *newitem) +{ + cJSON *child = array->child; + while (child && (which > 0)) + { + child = child->next; + which--; + } + if (which > 0) + { + /* item is after the end of the array */ + return 0; + } + if (child == NULL) + { + cJSON_AddItemToArray(array, newitem); + return 1; + } + + /* insert into the linked list */ + newitem->next = child; + newitem->prev = child->prev; + child->prev = newitem; + + /* was it at the beginning */ + if (child == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } + + return 1; +} + +static cJSON *get_object_item(const cJSON * const object, const char* name, const cJSON_bool case_sensitive) +{ + if (case_sensitive) + { + return cJSON_GetObjectItemCaseSensitive(object, name); + } + + return cJSON_GetObjectItem(object, name); +} + +enum patch_operation { INVALID, ADD, REMOVE, REPLACE, MOVE, COPY, TEST }; + +static enum patch_operation decode_patch_operation(const cJSON * const patch, const cJSON_bool case_sensitive) +{ + cJSON *operation = get_object_item(patch, "op", case_sensitive); + if (!cJSON_IsString(operation)) + { + return INVALID; + } + + if (strcmp(operation->valuestring, "add") == 0) + { + return ADD; + } + + if (strcmp(operation->valuestring, "remove") == 0) + { + return REMOVE; + } + + if (strcmp(operation->valuestring, "replace") == 0) + { + return REPLACE; + } + + if (strcmp(operation->valuestring, "move") == 0) + { + return MOVE; + } + + if (strcmp(operation->valuestring, "copy") == 0) + { + return COPY; + } + + if (strcmp(operation->valuestring, "test") == 0) + { + return TEST; + } + + return INVALID; +} + +/* overwrite and existing item with another one and free resources on the way */ +static void overwrite_item(cJSON * const root, const cJSON replacement) +{ + if (root == NULL) + { + return; + } + + if (root->string != NULL) + { + cJSON_free(root->string); + } + if (root->valuestring != NULL) + { + cJSON_free(root->valuestring); + } + if (root->child != NULL) + { + cJSON_Delete(root->child); + } + + memcpy(root, &replacement, sizeof(cJSON)); +} + +static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_sensitive) +{ + cJSON *path = NULL; + cJSON *value = NULL; + cJSON *parent = NULL; + enum patch_operation opcode = INVALID; + unsigned char *parent_pointer = NULL; + unsigned char *child_pointer = NULL; + int status = 0; + + path = get_object_item(patch, "path", case_sensitive); + if (!cJSON_IsString(path)) + { + /* malformed patch. */ + status = 2; + goto cleanup; + } + + opcode = decode_patch_operation(patch, case_sensitive); + if (opcode == INVALID) + { + status = 3; + goto cleanup; + } + else if (opcode == TEST) + { + /* compare value: {...} with the given path */ + status = !compare_json(get_item_from_pointer(object, path->valuestring, case_sensitive), get_object_item(patch, "value", case_sensitive), case_sensitive); + goto cleanup; + } + + /* special case for replacing the root */ + if (path->valuestring[0] == '\0') + { + if (opcode == REMOVE) + { + static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL}; + + overwrite_item(object, invalid); + + status = 0; + goto cleanup; + } + + if ((opcode == REPLACE) || (opcode == ADD)) + { + value = get_object_item(patch, "value", case_sensitive); + if (value == NULL) + { + /* missing "value" for add/replace. */ + status = 7; + goto cleanup; + } + + value = cJSON_Duplicate(value, 1); + if (value == NULL) + { + /* out of memory for add/replace. */ + status = 8; + goto cleanup; + } + + overwrite_item(object, *value); + + /* delete the duplicated value */ + cJSON_free(value); + value = NULL; + + /* the string "value" isn't needed */ + if (object->string != NULL) + { + cJSON_free(object->string); + object->string = NULL; + } + + status = 0; + goto cleanup; + } + } + + if ((opcode == REMOVE) || (opcode == REPLACE)) + { + /* Get rid of old. */ + cJSON *old_item = detach_path(object, (unsigned char*)path->valuestring, case_sensitive); + if (old_item == NULL) + { + status = 13; + goto cleanup; + } + cJSON_Delete(old_item); + if (opcode == REMOVE) + { + /* For Remove, this job is done. */ + status = 0; + goto cleanup; + } + } + + /* Copy/Move uses "from". */ + if ((opcode == MOVE) || (opcode == COPY)) + { + cJSON *from = get_object_item(patch, "from", case_sensitive); + if (from == NULL) + { + /* missing "from" for copy/move. */ + status = 4; + goto cleanup; + } + + if (opcode == MOVE) + { + value = detach_path(object, (unsigned char*)from->valuestring, case_sensitive); + } + if (opcode == COPY) + { + value = get_item_from_pointer(object, from->valuestring, case_sensitive); + } + if (value == NULL) + { + /* missing "from" for copy/move. */ + status = 5; + goto cleanup; + } + if (opcode == COPY) + { + value = cJSON_Duplicate(value, 1); + } + if (value == NULL) + { + /* out of memory for copy/move. */ + status = 6; + goto cleanup; + } + } + else /* Add/Replace uses "value". */ + { + value = get_object_item(patch, "value", case_sensitive); + if (value == NULL) + { + /* missing "value" for add/replace. */ + status = 7; + goto cleanup; + } + value = cJSON_Duplicate(value, 1); + if (value == NULL) + { + /* out of memory for add/replace. */ + status = 8; + goto cleanup; + } + } + + /* Now, just add "value" to "path". */ + + /* split pointer in parent and child */ + parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring); + if (parent_pointer) { + child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); + } + if (child_pointer != NULL) + { + child_pointer[0] = '\0'; + child_pointer++; + } + parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive); + decode_pointer_inplace(child_pointer); + + /* add, remove, replace, move, copy, test. */ + if ((parent == NULL) || (child_pointer == NULL)) + { + /* Couldn't find object to add to. */ + status = 9; + goto cleanup; + } + else if (cJSON_IsArray(parent)) + { + if (strcmp((char*)child_pointer, "-") == 0) + { + cJSON_AddItemToArray(parent, value); + value = NULL; + } + else + { + size_t index = 0; + if (!decode_array_index_from_pointer(child_pointer, &index)) + { + status = 11; + goto cleanup; + } + + if (!insert_item_in_array(parent, index, value)) + { + status = 10; + goto cleanup; + } + value = NULL; + } + } + else if (cJSON_IsObject(parent)) + { + if (case_sensitive) + { + cJSON_DeleteItemFromObjectCaseSensitive(parent, (char*)child_pointer); + } + else + { + cJSON_DeleteItemFromObject(parent, (char*)child_pointer); + } + cJSON_AddItemToObject(parent, (char*)child_pointer, value); + value = NULL; + } + else /* parent is not an object */ + { + /* Couldn't find object to add to. */ + status = 9; + goto cleanup; + } + +cleanup: + if (value != NULL) + { + cJSON_Delete(value); + } + if (parent_pointer != NULL) + { + cJSON_free(parent_pointer); + } + + return status; +} + +CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches) +{ + const cJSON *current_patch = NULL; + int status = 0; + + if (!cJSON_IsArray(patches)) + { + /* malformed patches. */ + return 1; + } + + if (patches != NULL) + { + current_patch = patches->child; + } + + while (current_patch != NULL) + { + status = apply_patch(object, current_patch, false); + if (status != 0) + { + return status; + } + current_patch = current_patch->next; + } + + return 0; +} + +CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches) +{ + const cJSON *current_patch = NULL; + int status = 0; + + if (!cJSON_IsArray(patches)) + { + /* malformed patches. */ + return 1; + } + + if (patches != NULL) + { + current_patch = patches->child; + } + + while (current_patch != NULL) + { + status = apply_patch(object, current_patch, true); + if (status != 0) + { + return status; + } + current_patch = current_patch->next; + } + + return 0; +} + +static void compose_patch(cJSON * const patches, const unsigned char * const operation, const unsigned char * const path, const unsigned char *suffix, const cJSON * const value) +{ + cJSON *patch = NULL; + + if ((patches == NULL) || (operation == NULL) || (path == NULL)) + { + return; + } + + patch = cJSON_CreateObject(); + if (patch == NULL) + { + return; + } + cJSON_AddItemToObject(patch, "op", cJSON_CreateString((const char*)operation)); + + if (suffix == NULL) + { + cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)path)); + } + else + { + size_t suffix_length = pointer_encoded_length(suffix); + size_t path_length = strlen((const char*)path); + unsigned char *full_path = (unsigned char*)cJSON_malloc(path_length + suffix_length + sizeof("/")); + + sprintf((char*)full_path, "%s/", (const char*)path); + encode_string_as_pointer(full_path + path_length + 1, suffix); + + cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)full_path)); + cJSON_free(full_path); + } + + if (value != NULL) + { + cJSON_AddItemToObject(patch, "value", cJSON_Duplicate(value, 1)); + } + cJSON_AddItemToArray(patches, patch); +} + +CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value) +{ + compose_patch(array, (const unsigned char*)operation, (const unsigned char*)path, NULL, value); +} + +static void create_patches(cJSON * const patches, const unsigned char * const path, cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) +{ + if ((from == NULL) || (to == NULL)) + { + return; + } + + if ((from->type & 0xFF) != (to->type & 0xFF)) + { + compose_patch(patches, (const unsigned char*)"replace", path, 0, to); + return; + } + + switch (from->type & 0xFF) + { + case cJSON_Int: + if (from->valueint != to->valueint) + { + compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); + } + return; + + case cJSON_Number: + if ((from->valueint != to->valueint) || !compare_double(from->valuedouble, to->valuedouble)) + { + compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); + } + return; + + case cJSON_String: + if (strcmp(from->valuestring, to->valuestring) != 0) + { + compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); + } + return; + + case cJSON_Array: + { + size_t index = 0; + cJSON *from_child = from->child; + cJSON *to_child = to->child; + unsigned char *new_path = (unsigned char*)cJSON_malloc(strlen((const char*)path) + 20 + sizeof("/")); /* Allow space for 64bit int. log10(2^64) = 20 */ + + /* generate patches for all array elements that exist in both "from" and "to" */ + for (index = 0; (from_child != NULL) && (to_child != NULL); (void)(from_child = from_child->next), (void)(to_child = to_child->next), index++) + { + /* check if conversion to unsigned long is valid + * This should be eliminated at compile time by dead code elimination + * if size_t is an alias of unsigned long, or if it is bigger */ + if (index > ULONG_MAX) + { + cJSON_free(new_path); + return; + } + sprintf((char*)new_path, "%s/%lu", path, (unsigned long)index); /* path of the current array element */ + create_patches(patches, new_path, from_child, to_child, case_sensitive); + } + + /* remove leftover elements from 'from' that are not in 'to' */ + for (; (from_child != NULL); (void)(from_child = from_child->next)) + { + /* check if conversion to unsigned long is valid + * This should be eliminated at compile time by dead code elimination + * if size_t is an alias of unsigned long, or if it is bigger */ + if (index > ULONG_MAX) + { + cJSON_free(new_path); + return; + } + sprintf((char*)new_path, "%lu", (unsigned long)index); + compose_patch(patches, (const unsigned char*)"remove", path, new_path, NULL); + } + /* add new elements in 'to' that were not in 'from' */ + for (; (to_child != NULL); (void)(to_child = to_child->next), index++) + { + compose_patch(patches, (const unsigned char*)"add", path, (const unsigned char*)"-", to_child); + } + cJSON_free(new_path); + return; + } + + case cJSON_Object: + { + cJSON *from_child = NULL; + cJSON *to_child = NULL; + sort_object(from, case_sensitive); + sort_object(to, case_sensitive); + + from_child = from->child; + to_child = to->child; + /* for all object values in the object with more of them */ + while ((from_child != NULL) || (to_child != NULL)) + { + int diff; + if (from_child == NULL) + { + diff = 1; + } + else if (to_child == NULL) + { + diff = -1; + } + else + { + diff = compare_strings((unsigned char*)from_child->string, (unsigned char*)to_child->string, case_sensitive); + } + + if (diff == 0) + { + /* both object keys are the same */ + size_t path_length = strlen((const char*)path); + size_t from_child_name_length = pointer_encoded_length((unsigned char*)from_child->string); + unsigned char *new_path = (unsigned char*)cJSON_malloc(path_length + from_child_name_length + sizeof("/")); + + sprintf((char*)new_path, "%s/", path); + encode_string_as_pointer(new_path + path_length + 1, (unsigned char*)from_child->string); + + /* create a patch for the element */ + create_patches(patches, new_path, from_child, to_child, case_sensitive); + cJSON_free(new_path); + + from_child = from_child->next; + to_child = to_child->next; + } + else if (diff < 0) + { + /* object element doesn't exist in 'to' --> remove it */ + compose_patch(patches, (const unsigned char*)"remove", path, (unsigned char*)from_child->string, NULL); + + from_child = from_child->next; + } + else + { + /* object element doesn't exist in 'from' --> add it */ + compose_patch(patches, (const unsigned char*)"add", path, (unsigned char*)to_child->string, to_child); + + to_child = to_child->next; + } + } + return; + } + + default: + break; + } +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to) +{ + cJSON *patches = NULL; + + if ((from == NULL) || (to == NULL)) + { + return NULL; + } + + patches = cJSON_CreateArray(); + create_patches(patches, (const unsigned char*)"", from, to, false); + + return patches; +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to) +{ + cJSON *patches = NULL; + + if ((from == NULL) || (to == NULL)) + { + return NULL; + } + + patches = cJSON_CreateArray(); + create_patches(patches, (const unsigned char*)"", from, to, true); + + return patches; +} + +CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object) +{ + sort_object(object, false); +} + +CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object) +{ + sort_object(object, true); +} + +static cJSON *merge_patch(cJSON *target, const cJSON * const patch, const cJSON_bool case_sensitive) +{ + cJSON *patch_child = NULL; + + if (!cJSON_IsObject(patch)) + { + /* scalar value, array or NULL, just duplicate */ + cJSON_Delete(target); + return cJSON_Duplicate(patch, 1); + } + + if (!cJSON_IsObject(target)) + { + cJSON_Delete(target); + target = cJSON_CreateObject(); + } + + patch_child = patch->child; + while (patch_child != NULL) + { + if (cJSON_IsNull(patch_child)) + { + /* NULL is the indicator to remove a value, see RFC7396 */ + if (case_sensitive) + { + cJSON_DeleteItemFromObjectCaseSensitive(target, patch_child->string); + } + else + { + cJSON_DeleteItemFromObject(target, patch_child->string); + } + } + else + { + cJSON *replace_me = NULL; + cJSON *replacement = NULL; + + if (case_sensitive) + { + replace_me = cJSON_DetachItemFromObjectCaseSensitive(target, patch_child->string); + } + else + { + replace_me = cJSON_DetachItemFromObject(target, patch_child->string); + } + + replacement = merge_patch(replace_me, patch_child, case_sensitive); + if (replacement == NULL) + { + return NULL; + } + + cJSON_AddItemToObject(target, patch_child->string, replacement); + } + patch_child = patch_child->next; + } + return target; +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch) +{ + return merge_patch(target, patch, false); +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch) +{ + return merge_patch(target, patch, true); +} + +static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) +{ + cJSON *from_child = NULL; + cJSON *to_child = NULL; + cJSON *patch = NULL; + if (to == NULL) + { + /* patch to delete everything */ + return cJSON_CreateNull(); + } + if (!cJSON_IsObject(to) || !cJSON_IsObject(from)) + { + return cJSON_Duplicate(to, 1); + } + + sort_object(from, case_sensitive); + sort_object(to, case_sensitive); + + from_child = from->child; + to_child = to->child; + patch = cJSON_CreateObject(); + if (patch == NULL) + { + return NULL; + } + while (from_child || to_child) + { + int diff; + if (from_child != NULL) + { + if (to_child != NULL) + { + diff = strcmp(from_child->string, to_child->string); + } + else + { + diff = -1; + } + } + else + { + diff = 1; + } + + if (diff < 0) + { + /* from has a value that to doesn't have -> remove */ + cJSON_AddItemToObject(patch, from_child->string, cJSON_CreateNull()); + + from_child = from_child->next; + } + else if (diff > 0) + { + /* to has a value that from doesn't have -> add to patch */ + cJSON_AddItemToObject(patch, to_child->string, cJSON_Duplicate(to_child, 1)); + + to_child = to_child->next; + } + else + { + /* object key exists in both objects */ + if (!compare_json(from_child, to_child, case_sensitive)) + { + /* not identical --> generate a patch */ + cJSON_AddItemToObject(patch, to_child->string, cJSONUtils_GenerateMergePatch(from_child, to_child)); + } + + /* next key in the object */ + from_child = from_child->next; + to_child = to_child->next; + } + } + if (patch->child == NULL) + { + /* no patch generated */ + cJSON_Delete(patch); + return NULL; + } + + return patch; +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to) +{ + return generate_merge_patch(from, to, false); +} + +CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to) +{ + return generate_merge_patch(from, to, true); +} diff --git a/src/subprojects/struct2json/cJSON/cJSON_Utils.h b/src/subprojects/struct2json/cJSON/cJSON_Utils.h new file mode 100644 index 00000000..a970c650 --- /dev/null +++ b/src/subprojects/struct2json/cJSON/cJSON_Utils.h @@ -0,0 +1,88 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON_Utils__h +#define cJSON_Utils__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cJSON.h" + +/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */ +CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer); +CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer); + +/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */ +/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */ +CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to); +CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to); +/* Utility for generating patch array entries. */ +CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value); +/* Returns 0 for success. */ +CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches); +CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches); + +/* +// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use: +//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches) +//{ +// cJSON *modme = cJSON_Duplicate(*object, 1); +// int error = cJSONUtils_ApplyPatches(modme, patches); +// if (!error) +// { +// cJSON_Delete(*object); +// *object = modme; +// } +// else +// { +// cJSON_Delete(modme); +// } +// +// return error; +//} +// Code not added to library since this strategy is a LOT slower. +*/ + +/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */ +/* target will be modified by patch. return value is new ptr for target. */ +CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch); +CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch); +/* generates a patch to move from -> to */ +/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */ +CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to); +CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to); + +/* Given a root object and a target object, construct a pointer from one to the other. */ +CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target); + +/* Sorts the members of the object into alphabetical order. */ +CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object); +CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/subprojects/struct2json/cjson/cJSON.h b/src/subprojects/struct2json/cjson/cJSON.h new file mode 100644 index 00000000..3738b012 --- /dev/null +++ b/src/subprojects/struct2json/cjson/cJSON.h @@ -0,0 +1,13 @@ +/* + * Lowercase-include shim for the meson wrap build of struct2json. + * + * XCE consumers include (the layout the nix packaging + * provided: headers installed under include/cjson/), but the upstream tree + * keeps cJSON.h under cJSON/ (mixed case). This shim forwards to the real + * header so the wrap path needs no build-time header synthesis. The nix + * packaging never enters this path (it installs the real headers). + */ +#ifndef CJSON_SHIM_CJSON_H +#define CJSON_SHIM_CJSON_H +#include "../cJSON/cJSON.h" +#endif /* CJSON_SHIM_CJSON_H */ diff --git a/src/subprojects/struct2json/cjson/s2j.h b/src/subprojects/struct2json/cjson/s2j.h new file mode 100644 index 00000000..7e2288d0 --- /dev/null +++ b/src/subprojects/struct2json/cjson/s2j.h @@ -0,0 +1,9 @@ +/* + * Lowercase-include shim for the meson wrap build of struct2json. + * Forwards to the real header under struct2json/inc/. + * See cjson/cJSON.h shim for rationale. + */ +#ifndef CJSON_SHIM_S2J_H +#define CJSON_SHIM_S2J_H +#include "../struct2json/inc/s2j.h" +#endif /* CJSON_SHIM_S2J_H */ diff --git a/src/subprojects/struct2json/cjson/s2jdef.h b/src/subprojects/struct2json/cjson/s2jdef.h new file mode 100644 index 00000000..3098093d --- /dev/null +++ b/src/subprojects/struct2json/cjson/s2jdef.h @@ -0,0 +1,9 @@ +/* + * Lowercase-include shim for the meson wrap build of struct2json. + * Forwards to the real header under struct2json/inc/. + * See cjson/cJSON.h shim for rationale. + */ +#ifndef CJSON_SHIM_S2JDEF_H +#define CJSON_SHIM_S2JDEF_H +#include "../struct2json/inc/s2jdef.h" +#endif /* CJSON_SHIM_S2JDEF_H */ diff --git a/src/subprojects/struct2json/demo/error_print.txt b/src/subprojects/struct2json/demo/error_print.txt new file mode 100644 index 00000000..d8f0ca4f --- /dev/null +++ b/src/subprojects/struct2json/demo/error_print.txt @@ -0,0 +1,10 @@ +struct_para_json2bin(McUsrInfoT,bin_para,type,value) +struct_para_json2bin(McBaseOrdrT,bin_para,type,value) +struct_para_json2bin(McBaseOrdrArrayT,bin_para,type,value) +struct_para_json2bin(McOcoBaseOrdrT,bin_para,type,value) + +************************************* +struct_para_bin2json(McUsrInfoT,bin_para,type,json_para) +struct_para_bin2json(McBaseOrdrT,bin_para,type,json_para) +struct_para_bin2json(McBaseOrdrArrayT,bin_para,type,json_para) +struct_para_bin2json(McOcoBaseOrdrT,bin_para,type,json_para) \ No newline at end of file diff --git a/src/subprojects/struct2json/demo/generate_s2j_code.py b/src/subprojects/struct2json/demo/generate_s2j_code.py new file mode 100644 index 00000000..d2bcdfeb --- /dev/null +++ b/src/subprojects/struct2json/demo/generate_s2j_code.py @@ -0,0 +1,296 @@ +#!/usr/bin/python3 +import re +struct_txt = "struct_defination.txt" +with open(struct_txt,"r") as f: + lines = f.readlines() +#注意:结构体后面不能加任何注释,仅仅是结构体的一般定义就好,不然会解析出问题 +#将文件中定义的结构体定义由多行转换为一行,方便后续使用字符串进行相关的处理 +struct_str = "" +for line in lines: + struct_str += ' '.join(line.split()) +struct_str = re.sub(r'((?<=\n)|^)[\t]*\/\*.*?\*\/\n?|\/\*.*?\*\/|((?<=\n)|^)[\t]*\/\/[^\n]*\n|\/\/[^\n]*', '',struct_str) + +return_code = "" +#使用typedef进行元素分割,并去除列表中空元素 +struct_str_split_list = [x for x in struct_str.split("typedef") if x!=""] +#print(struct_str_split_list) +struct_name_return = "" +fun_list = [] +error_print_json2bin="" +error_print_bin2json="" +#使用(进行元素分割,先获取结构体参数 +for item in struct_str_split_list: + s2j_code_str_concat_return = "" #定义最后返回的 struct to json 字符串 + j2s_code_str_concat_return = "" #定义最后返回的 json to struct 字符串 + struct_name = item.split("{")[1].split("}")[1].split(",")[0].strip() # 获取结构体名称 + #print(struct_name) + if struct_name.find(";")!=-1: + struct_name=struct_name[:-1] + #print(struct_name) + error_print_json2bin = error_print_json2bin+"struct_para_json2bin("+struct_name+",bin_para,type,value)\n" + error_print_bin2json = error_print_bin2json+"struct_para_bin2json("+struct_name+",bin_para,type,json_para)\n" + + para_list = [ x for x in item.split("{")[1].split("}")[0].split(";") if x !=""]#获取参数列表,并去除列表中空元素 + #print(para_list) + #解析参数列表中的参数类型和参数名称,其中参数类型有 基本类型 和 结构体类型,enum和指针按int处理,不支持union和位域 + #数组类型:支持基本类型一维数组,结构体一维数组,字符二维数组(字符串数组) + #struct to json 的字符串 + #print(struct_name) + s2j_code_fun_str = "cJSON *struct_to_json_" + struct_name + "(void* struct_obj)" + s2j_code_str = s2j_code_fun_str + "\n" + "{\n" + "\ts2j_create_json_obj(json_obj_);\n\t" + struct_name + " *struct_obj_ = (" + struct_name + " *)struct_obj;\n\t" + fun_list.append(s2j_code_fun_str) + # json to struct 的字符串 + j2s_code_fun_str = "void *json_to_struct_" + struct_name + "(cJSON* json_obj)" + fun_list.append(j2s_code_fun_str) + j2s_code_str = j2s_code_fun_str + "\n" + "{\n" + "\ts2j_create_struct_obj(struct_obj_, " + struct_name + ");\n\t" + for para in para_list: + s2j_code_str_concat = "" #定义 struct to json 的初始连接字符串 + j2s_code_str_concat = "" #定义 json to struct 的初始连接字符串 + para_item = para.split(" ") + if len(para_item)==2: + para_type = para_item[0] # 参数类型 + #print(para_type) + para_name = para_item[1] # 参数名称 + #print(para_name) + elif len(para_item) > 2: + para_type = para_item[0] # 包含空格的参数类型 + for index in range(1, len(para_item)-2): + para_type = para_type + " " + para_item[index] + #print(para_type) + para_name = para_item[-1] # 参数名称 + #print(para_name) + + #根据参数类型不同进行处理 + if para.find("*")!=-1: # 指针类型 + last_station = para.rfind("*") + para_name=para[last_station+1:] + #print(para_name) + if "[" in para_name: + left_symbol = para_name.find("[") # 找到[位置 + right_symbol = para_name.find("]") # 找到]位置 + array_para_name_size = para_name[left_symbol+1:right_symbol] + #print(array_para_name_size) + para_name = para_name.split("[")[0] + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_array_element(json_obj_, struct_obj_, int, "+ para_name + ","+ array_para_name_size+");\n\t" + j2s_code_str_concat = j2s_code_str_concat +"s2j_struct_get_array_element(struct_obj_,json_obj, int, "+para_name + ");\n\t" + else: + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_basic_element(json_obj_, struct_obj_, int, "+para_name+");\n\t" + j2s_code_str_concat = j2s_code_str_concat + "s2j_struct_get_basic_element(struct_obj_,json_obj, int, "+para_name+");\n\t" + elif para_type.find("enum")!=-1 or para_type.find("CbT")!=-1: # enum或函数指针(根据实际命名规范识别) + #print(para_type) + if "[" in para_name: + left_symbol = para_name.find("[") # 找到[位置 + right_symbol = para_name.find("]") # 找到]位置 + array_para_name_size = para_name[left_symbol+1:right_symbol] + #print(array_para_name_size) + para_name = para_name.split("[")[0] + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_array_element(json_obj_, struct_obj_, int, "+ para_name + ","+ array_para_name_size+");\n\t" + j2s_code_str_concat = j2s_code_str_concat +"s2j_struct_get_array_element(struct_obj_,json_obj, int, "+para_name + ");\n\t" + else: + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_basic_element(json_obj_, struct_obj_, int, "+para_name+");\n\t" + j2s_code_str_concat = j2s_code_str_concat + "s2j_struct_get_basic_element(struct_obj_,json_obj, int, "+para_name+");\n\t" + else: #基本类型 + if para_type in ("char","unsigned char","signed char","int","unsigned","unsigned int","signed int","short","unsigned short","signed short","long","unsigned long","signed long","long long","unsigned long long","signed long long","BOOL","bool","size_t","uint8_t","uint16_t","uint32_t","uint64_t","int8_t","int16_t","int32_t","int64_t","uint8","uint16","uint32","uint64","int8","int16","int32","int64","uint_fast64_t","__int128_t","__uint128_t","float","double","long double"): + if para_type in ("float","double","long double","__int128_t","__uint128_t"): #浮点型、128位整型 + if "[" in para_name: + #print(para_name) + left_symbol = para_name.find("[") # 找到[位置 + right_symbol = para_name.find("]") # 找到]位置 + array_para_name_size = para_name[left_symbol+1:right_symbol] + para_name = para_name.split("[")[0] + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_array_element(json_obj_, struct_obj_, double, "+ para_name + ","+ array_para_name_size+");\n\t" + j2s_code_str_concat = j2s_code_str_concat +"s2j_struct_get_array_element(struct_obj_,json_obj, double, "+para_name + ");\n\t" + else: + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_basic_element(json_obj_, struct_obj_, double, "+para_name+");\n\t" + j2s_code_str_concat = j2s_code_str_concat +"s2j_struct_get_basic_element(struct_obj_,json_obj, double, "+para_name+");\n\t" + elif para_type =="char" : # 字符串 + if "[" in para_name: + para_name_item = para_name.split("[") + if len(para_name_item)==2: # 处理字符数组的情况,只取名字,舍弃中括号部分 + para_name = para_name_item[0] + s2j_code_str_concat = s2j_code_str_concat+ "s2j_json_set_basic_element(json_obj_, struct_obj_, string, " + para_name + ");\n\t" + j2s_code_str_concat = j2s_code_str_concat + "s2j_struct_get_basic_element(struct_obj_,json_obj, string, " + para_name + ");\n\t" + elif len(para_name_item)==3: # 处理二维字符数组的情况 + para_name = para_name_item[0] + # left_symbol = 0 # 找到[位置 + right_symbol = para_name_item[1].find("]") # 找到]位置 + array_para_name_size = para_name_item[1][0:right_symbol] + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_array_element(json_obj_, struct_obj_, string, "+ para_name + ","+ array_para_name_size+");\n\t" + j2s_code_str_concat = j2s_code_str_concat +"s2j_struct_get_array_element(struct_obj_,json_obj, string, "+para_name + ");\n\t" + else: + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_basic_element(json_obj_, struct_obj_, int, " + para_name + ");\n\t" + j2s_code_str_concat = j2s_code_str_concat + "s2j_struct_get_basic_element(struct_obj_,json_obj, int, " + para_name + ");\n\t" + else: #其它常规整型 + if "[" in para_name: + #print(para_name) + left_symbol = para_name.find("[") # 找到[位置 + right_symbol = para_name.find("]") # 找到]位置 + array_para_name_size = para_name[left_symbol+1:right_symbol] + #print(array_para_name_size) + para_name = para_name.split("[")[0] + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_array_element(json_obj_, struct_obj_, int, "+ para_name + ","+ array_para_name_size+");\n\t" + j2s_code_str_concat = j2s_code_str_concat +"s2j_struct_get_array_element(struct_obj_,json_obj, int, "+para_name + ");\n\t" + else: + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_basic_element(json_obj_, struct_obj_, int, "+para_name+");\n\t" + j2s_code_str_concat = j2s_code_str_concat +"s2j_struct_get_basic_element(struct_obj_,json_obj, int, "+para_name+");\n\t" + else: #结构体类型的参数 + if "[" in para_name: + # usrDefLst[MAX_LIST_MEM_TYPE] + left_sym = para_name.find("[") #找到[位置 + right_sym = para_name.find("]") #找到]位置 + list_size = para_name[left_sym+1:right_sym] + para_name = para_name.split("[")[0] + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_struct_array_element_by_func(json_obj_, struct_obj_, "+ para_type +","+para_name+ ","+list_size+");\n\t" + j2s_code_str_concat = j2s_code_str_concat + "s2j_struct_get_struct_array_element_by_func(struct_obj_, json_obj, "+ para_type +","+para_name+");\n\t" + else: + s2j_code_str_concat = s2j_code_str_concat + "s2j_json_set_struct_element_by_func(json_obj_, struct_obj_, "+ para_type +","+para_name+ ");\n\t" + j2s_code_str_concat = j2s_code_str_concat + "s2j_struct_get_struct_element_by_func(struct_obj_, json_obj, " + para_type + "," + para_name + ");\n\t" + + s2j_code_str_concat_return = s2j_code_str_concat_return + s2j_code_str_concat # #"return json_obj_;\n}" + j2s_code_str_concat_return = j2s_code_str_concat_return + j2s_code_str_concat # #"return json_obj_;\n}" + # 处理每一行的结构体,然后分别进行拼装处理,作为注释打印出来 + #print(item) + struct_item = item.split("{") + struct_item_header = struct_item[0] # 结构体头部 + struct_item_body = struct_item[1].split("}")[0].strip() # 结构体body,包含参数部分,待会要对参数进行处理 + #print(struct_item_body) + struct_item_tail = struct_item[1].split("}")[1] # 结构体尾部 + struct_item_body_list = struct_item_body.split(";") + struct_item_body_str = "" + struct_item_body_list_len = len(struct_item_body_list) + for i in range(struct_item_body_list_len-1): + struct_item_body_str = struct_item_body_str + "\t" + struct_item_body_list[i] + ";\n" + #print(struct_item_body_str) + # 将结构体定义作为注释打印出来 + return_struct_to_json_code = "\n#if 0\n" + "typedef" + struct_item_header + "\n{\n" + struct_item_body_str + "}" + struct_item_tail +"\n#endif\n" + s2j_code_str + s2j_code_str_concat_return + "return json_obj_;\n}" + return_json_to_struct_code = j2s_code_str + j2s_code_str_concat_return + "return struct_obj_;\n}" + #print(item) + + + return_code =return_code + return_struct_to_json_code+"\n\n"+return_json_to_struct_code+"\n" + struct_name_return = (struct_name_return + " " + struct_name).strip() + +#打印生成的函数列表 + +#print(fun_list) + +#将函数列表添加到指定的头文件中 +file = open('my_struct_2_json.h','w') +h_header = r""" +#ifdef __cplusplus +extern "C" { +#endif +""" +h_tail = r""" +#ifdef __cplusplus +} +#endif /* end of __cplusplus */ +""" +content = h_header +for i in range(len(fun_list)): + content = content + "\n" + fun_list[i] +";\n" + +content = content + h_tail +file.write(content.strip()) +file.close() + +head_str = r""" +#include "inc/mc_usr_def.h" +#include "my_struct_2_json.inc" +#include "my_struct_2_json.h" + + +#ifdef __cplusplus +extern "C" { +#endif + """ + +void_main_header = r""" + char file_name[] = "struct_defination.json"; + FILE *fp; + + fp = fopen(file_name, "w"); + if (NULL == fp) return 1; + fprintf(fp,"{\n\t\"struct\": [\n\t\t{\n\t\t\t\"type\": \"void*\",\n\t\t\t\"value\": null\n\t\t}"); + +""" + +str_return = "" +str_s2j_test = "" +for i in range(len(struct_name_return.split())): + str_s2j_test = str_s2j_test + " TEST_S2J_STRUCT(" + struct_name_return.split()[i] + ", 0 , fp);\n" + #print(str_s2j_test) + +str_s2j_test_tail = r""" + fprintf(fp,"\n\t]\n}"); + fclose(fp); + return 0; +} + +""" + +str_s2j_test2_header = r""" + + int s2j_test2(void) + { + + char file_name[] = "struct_defination.json"; + FILE *fp; + + fp = fopen(file_name, "rb"); + if (NULL == fp) return 1; + + fseek(fp,0L,SEEK_END); + int flen=ftell(fp); + char* p=(char *)malloc(flen+1); + if(p==NULL) + { + fclose(fp); + return 0; + } + fseek(fp,0L,SEEK_SET); + fread(p,flen,1,fp); + p[flen]=0; + + printf("\nstruct_defination.json:\n%s\n",p); + + cJSON *json_obj =cJSON_Parse(p); + CHECK_NOT_NULL(json_obj) + cJSON *json_struct = cJSON_GetObjectItem(json_obj, "struct"); + CHECK_NOT_NULL(json_struct) + + int array_size = cJSON_GetArraySize(json_struct); + printf("\nsize:\n%d\n",array_size); + int i = 0; \ + +""" + +str_s2j_test2 = "" +for i in range(len(struct_name_return.split())): + str_s2j_test2 = str_s2j_test2 + " TEST_S2J_JSON(" + struct_name_return.split()[i] + ", array_size);\n" + #print(str_s2j_test2) + + +void_main_tail = r""" + fclose(fp); + free(p); + return 0; +} + + +#endif// DEBUGS2J + +#ifdef __cplusplus +} +#endif /* end of __cplusplus */ +""" +str_return = head_str + return_code + "#ifdef DEBUGS2J \n int s2j_test(void)\n" +" {\n\t" + void_main_header + str_s2j_test + str_s2j_test_tail + str_s2j_test2_header + str_s2j_test2 + void_main_tail +#print(str_return) + +error_return = error_print_json2bin + "\n" + "*************************************" + "\n" + error_print_bin2json +print(error_return) +# 将转换的代码写入文件中 +with open("my_struct_2_json.c","w") as f: + f.write(str_return.strip()) +with open("error_print.txt","w") as f: + f.write(error_return.strip()) diff --git a/src/subprojects/struct2json/demo/generate_struct_defination.py b/src/subprojects/struct2json/demo/generate_struct_defination.py new file mode 100644 index 00000000..00d54e84 --- /dev/null +++ b/src/subprojects/struct2json/demo/generate_struct_defination.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +import os +import re + +root = "./inc" +file_name_list = os.listdir(root) +#print(file_name_list) +h_file_list = [] +for file_item in file_name_list: + if file_item.rfind(".h")!=-1: + h_file_list.append(file_item) +#print(h_file_list) +content = "" + +for h_file in h_file_list: + #print(h_file) + with open(root + "/" + h_file, 'r', encoding='UTF-8') as f: + content_file = f.read() + content_file = re.sub(r'((?<=\n)|^)[\t]*\/\*.*?\*\/\n?|\/\*.*?\*\/|((?<=\n)|^)[\t]*\/\/[^\n]*\n|\/\/[^\n]*','',content_file) + num_struct = content_file.count('typedef struct') + keyword_start = 'typedef struct' + keyword_middle = '}' + keyword_end = ';' + position_start = 0 + position_end=0 + flag=0 + content_struct="" + for i in range(num_struct): + content_temp="" + position_start = content_file.find(keyword_start,position_start) + position_middle = content_file.find(keyword_middle, position_start) + position_end = content_file.find(keyword_end, position_middle) + #print(position_end) + if position_start !=-1: + content_temp = content_file[position_start:position_end+2] + position_start += 1 + content_struct = content_struct + "\n" + content_temp + content=content+content_struct +#print(content) +with open("struct_defination.txt", "w") as f: + f.write(content) diff --git a/src/subprojects/struct2json/demo/inc/mc_usr_def.h b/src/subprojects/struct2json/demo/inc/mc_usr_def.h new file mode 100644 index 00000000..4cb0b339 --- /dev/null +++ b/src/subprojects/struct2json/demo/inc/mc_usr_def.h @@ -0,0 +1,101 @@ +/*** +example +***/ + +#ifndef _MC_USER_DEF_ +#define _MC_USER_DEF_ + +/***************************************************************************** + ** + ** Header File + ** + *****************************************************************************/ +/* Standard C header files */ +#include /* define standard i/o functions */ +#include /* define standard library functions */ +#include /* define string handling functions */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/***************************************************************************** + ** + ** Type Defination + ** + *****************************************************************************/ + + +/***************************************************************************** + ** + ** Macro + ** + *****************************************************************************/ + +/****************************************************************************** + ** + ** Structure + ** + ******************************************************************************/ + +typedef int int32; +typedef long long int64; + +typedef int (*fun_ptr_CbT)(int,int); + +typedef enum WEEK_DAY +{ + MON=1, TUE, WED, THU, FRI, SAT, SUN +}enumWEEK_DAY_T; + + +typedef struct McUsrInfoS +{ + int *pInt; + int *pIntArray[2]; + fun_ptr_CbT fun; + fun_ptr_CbT funArray[2]; + enum WEEK_DAY day1; + enumWEEK_DAY_T day2; + enumWEEK_DAY_T day2Array[2]; + unsigned char id; + unsigned char idArray[2]; + char usrType; + char usrName[8]; + char usrNameArray[2][8]; + int32 usrSqno; + int32 ussSqnoArray[2]; + int64 jobSqno; + int64 jobSqnoArray[2]; + float rate; + float rateArray[2]; + double price; + double priceArray[2]; +} McUsrInfoT, *pMcUsrInfoT; + +typedef struct McBaseOrdrS +{ + short taskSqno; + short taskSqnoArray[2]; + double price; + double priceArray[2]; +} McBaseOrdrT, *pMcBaseOrdrT; + +typedef struct McBaseOrdrArray +{ + McBaseOrdrT mcBaseOrdrArray[2]; +} McBaseOrdrArrayT; + +typedef struct McOcoBaseOrdrS +{ + McBaseOrdrArrayT mcBaseOrdrAry; + void * pUsrDef; +} McOcoBaseOrdrT, *pMcOcoBaseOrdrT; + + +#ifdef __cplusplus +} +#endif + +#endif /* _MC_USER_DEF_ */ diff --git a/src/subprojects/struct2json/demo/main.c b/src/subprojects/struct2json/demo/main.c new file mode 100644 index 00000000..048941b2 --- /dev/null +++ b/src/subprojects/struct2json/demo/main.c @@ -0,0 +1,138 @@ +/* + * This file is part of the struct2json Library. + * + * Copyright (c) 2015, Armink, + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Function: demo for this library. + * Created on: 2015-10-14 + */ + +#include "s2j.h" +#include +#include + +#ifdef DEBUGS2J +extern int s2j_test(void); +extern int s2j_test2(void); +#endif// DEBUGS2J + +typedef struct { + char name[16]; +} Hometown; + +typedef struct { + uint8_t id; + double weight; + uint8_t score[8]; + char name[10]; + Hometown hometown; +} Student; + +/** + * Student JSON object to structure object + * + * @param json_obj JSON object + * + * @return structure object + */ +static void *json_to_struct(cJSON* json_obj) { + /* create Student structure object */ + s2j_create_struct_obj(struct_student, Student); + + /* deserialize data to Student structure object. */ + s2j_struct_get_basic_element(struct_student, json_obj, int, id); +#if 1 + s2j_struct_get_array_element(struct_student, json_obj, int, score); + s2j_struct_get_basic_element(struct_student, json_obj, string, name); + s2j_struct_get_basic_element(struct_student, json_obj, double, weight); +#else // another xxx_ex api, add default value and more secure + s2j_struct_get_array_element_ex(struct_student, json_obj, int, score, 8, 0); + s2j_struct_get_basic_element_ex(struct_student, json_obj, string, name, "John"); + s2j_struct_get_basic_element_ex(struct_student, json_obj, double, weight, 0); +#endif + + /* deserialize data to Student.Hometown structure object. */ + s2j_struct_get_struct_element(struct_hometown, struct_student, json_hometown, json_obj, Hometown, hometown); + s2j_struct_get_basic_element(struct_hometown, json_hometown, string, name); + + /* return Student structure object pointer */ + return struct_student; +} + +/** + * Student structure object to JSON object + * + * @param struct_obj structure object + * + * @param JSON object + */ +static cJSON *struct_to_json(void* struct_obj) { + Student *struct_student = (Student *)struct_obj; + + /* create Student JSON object */ + s2j_create_json_obj(json_student); + + /* serialize data to Student JSON object. */ + s2j_json_set_basic_element(json_student, struct_student, int, id); + s2j_json_set_basic_element(json_student, struct_student, double, weight); + s2j_json_set_array_element(json_student, struct_student, int, score, 8); + s2j_json_set_basic_element(json_student, struct_student, string, name); + + /* serialize data to Student.Hometown JSON object. */ + s2j_json_set_struct_element(json_hometown, json_student, struct_hometown, struct_student, Hometown, hometown); + s2j_json_set_basic_element(json_hometown, struct_hometown, string, name); + + /* return Student JSON object pointer */ + return json_student; +} + +int main(void) { + static Student orignal_student_obj = { + .id = 24, + .weight = 71.2, + .score = {1, 2, 3, 4, 5, 6, 7, 8}, + .name = "armink", + .hometown.name = "China", + }; + + /* serialize Student structure object */ + cJSON *json_student = struct_to_json(&orignal_student_obj); + /* deserialize Student structure object */ + Student *converted_student_obj = json_to_struct(json_student); + + /* compare Student structure object */ + if(memcmp(&orignal_student_obj, converted_student_obj, sizeof(Student))) { + printf("Converted failed!\n"); + } else { + printf("Converted OK!\n"); + } + + s2j_delete_json_obj(json_student); + s2j_delete_struct_obj(converted_student_obj); + +#ifdef DEBUGS2J + s2j_test(); + s2j_test2(); +#endif// DEBUGS2J + + return 0; +} diff --git a/src/subprojects/struct2json/demo/my_struct_2_json.c b/src/subprojects/struct2json/demo/my_struct_2_json.c new file mode 100644 index 00000000..0398a3eb --- /dev/null +++ b/src/subprojects/struct2json/demo/my_struct_2_json.c @@ -0,0 +1,232 @@ +#include "inc/mc_usr_def.h" +#include "my_struct_2_json.inc" +#include "my_struct_2_json.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#if 0 +typedef struct McUsrInfoS +{ + int *pInt; + int *pIntArray[2]; + fun_ptr_CbT fun; + fun_ptr_CbT funArray[2]; + enum WEEK_DAY day1; + enumWEEK_DAY_T day2; + enumWEEK_DAY_T day2Array[2]; + unsigned char id; + unsigned char idArray[2]; + char usrType; + char usrName[8]; + char usrNameArray[2][8]; + int32 usrSqno; + int32 ussSqnoArray[2]; + int64 jobSqno; + int64 jobSqnoArray[2]; + float rate; + float rateArray[2]; + double price; + double priceArray[2]; +} McUsrInfoT, *pMcUsrInfoT; +#endif +cJSON *struct_to_json_McUsrInfoT(void* struct_obj) +{ + s2j_create_json_obj(json_obj_); + McUsrInfoT *struct_obj_ = (McUsrInfoT *)struct_obj; + s2j_json_set_basic_element(json_obj_, struct_obj_, int, pInt); + s2j_json_set_array_element(json_obj_, struct_obj_, int, pIntArray,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, int, fun); + s2j_json_set_array_element(json_obj_, struct_obj_, int, funArray,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, int, day1); + s2j_json_set_basic_element(json_obj_, struct_obj_, int, day2); + s2j_json_set_array_element(json_obj_, struct_obj_, int, day2Array,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, int, id); + s2j_json_set_array_element(json_obj_, struct_obj_, int, idArray,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, int, usrType); + s2j_json_set_basic_element(json_obj_, struct_obj_, string, usrName); + s2j_json_set_array_element(json_obj_, struct_obj_, string, usrNameArray,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, int, usrSqno); + s2j_json_set_array_element(json_obj_, struct_obj_, int, ussSqnoArray,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, int, jobSqno); + s2j_json_set_array_element(json_obj_, struct_obj_, int, jobSqnoArray,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, double, rate); + s2j_json_set_array_element(json_obj_, struct_obj_, double, rateArray,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, double, price); + s2j_json_set_array_element(json_obj_, struct_obj_, double, priceArray,2); + return json_obj_; +} + +void *json_to_struct_McUsrInfoT(cJSON* json_obj) +{ + s2j_create_struct_obj(struct_obj_, McUsrInfoT); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, pInt); + s2j_struct_get_array_element(struct_obj_,json_obj, int, pIntArray); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, fun); + s2j_struct_get_array_element(struct_obj_,json_obj, int, funArray); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, day1); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, day2); + s2j_struct_get_array_element(struct_obj_,json_obj, int, day2Array); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, id); + s2j_struct_get_array_element(struct_obj_,json_obj, int, idArray); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, usrType); + s2j_struct_get_basic_element(struct_obj_,json_obj, string, usrName); + s2j_struct_get_array_element(struct_obj_,json_obj, string, usrNameArray); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, usrSqno); + s2j_struct_get_array_element(struct_obj_,json_obj, int, ussSqnoArray); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, jobSqno); + s2j_struct_get_array_element(struct_obj_,json_obj, int, jobSqnoArray); + s2j_struct_get_basic_element(struct_obj_,json_obj, double, rate); + s2j_struct_get_array_element(struct_obj_,json_obj, double, rateArray); + s2j_struct_get_basic_element(struct_obj_,json_obj, double, price); + s2j_struct_get_array_element(struct_obj_,json_obj, double, priceArray); + return struct_obj_; +} + +#if 0 +typedef struct McBaseOrdrS +{ + short taskSqno; + short taskSqnoArray[2]; + double price; + double priceArray[2]; +} McBaseOrdrT, *pMcBaseOrdrT; +#endif +cJSON *struct_to_json_McBaseOrdrT(void* struct_obj) +{ + s2j_create_json_obj(json_obj_); + McBaseOrdrT *struct_obj_ = (McBaseOrdrT *)struct_obj; + s2j_json_set_basic_element(json_obj_, struct_obj_, int, taskSqno); + s2j_json_set_array_element(json_obj_, struct_obj_, int, taskSqnoArray,2); + s2j_json_set_basic_element(json_obj_, struct_obj_, double, price); + s2j_json_set_array_element(json_obj_, struct_obj_, double, priceArray,2); + return json_obj_; +} + +void *json_to_struct_McBaseOrdrT(cJSON* json_obj) +{ + s2j_create_struct_obj(struct_obj_, McBaseOrdrT); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, taskSqno); + s2j_struct_get_array_element(struct_obj_,json_obj, int, taskSqnoArray); + s2j_struct_get_basic_element(struct_obj_,json_obj, double, price); + s2j_struct_get_array_element(struct_obj_,json_obj, double, priceArray); + return struct_obj_; +} + +#if 0 +typedef struct McBaseOrdrArray +{ + McBaseOrdrT mcBaseOrdrArray[2]; +} McBaseOrdrArrayT; +#endif +cJSON *struct_to_json_McBaseOrdrArrayT(void* struct_obj) +{ + s2j_create_json_obj(json_obj_); + McBaseOrdrArrayT *struct_obj_ = (McBaseOrdrArrayT *)struct_obj; + s2j_json_set_struct_array_element_by_func(json_obj_, struct_obj_, McBaseOrdrT,mcBaseOrdrArray,2); + return json_obj_; +} + +void *json_to_struct_McBaseOrdrArrayT(cJSON* json_obj) +{ + s2j_create_struct_obj(struct_obj_, McBaseOrdrArrayT); + s2j_struct_get_struct_array_element_by_func(struct_obj_, json_obj, McBaseOrdrT,mcBaseOrdrArray); + return struct_obj_; +} + +#if 0 +typedef struct McOcoBaseOrdrS +{ + McBaseOrdrArrayT mcBaseOrdrAry; + void * pUsrDef; +} McOcoBaseOrdrT, *pMcOcoBaseOrdrT; +#endif +cJSON *struct_to_json_McOcoBaseOrdrT(void* struct_obj) +{ + s2j_create_json_obj(json_obj_); + McOcoBaseOrdrT *struct_obj_ = (McOcoBaseOrdrT *)struct_obj; + s2j_json_set_struct_element_by_func(json_obj_, struct_obj_, McBaseOrdrArrayT,mcBaseOrdrAry); + s2j_json_set_basic_element(json_obj_, struct_obj_, int, pUsrDef); + return json_obj_; +} + +void *json_to_struct_McOcoBaseOrdrT(cJSON* json_obj) +{ + s2j_create_struct_obj(struct_obj_, McOcoBaseOrdrT); + s2j_struct_get_struct_element_by_func(struct_obj_, json_obj, McBaseOrdrArrayT,mcBaseOrdrAry); + s2j_struct_get_basic_element(struct_obj_,json_obj, int, pUsrDef); + return struct_obj_; +} +#ifdef DEBUGS2J + int s2j_test(void) + { + + char file_name[] = "struct_defination.json"; + FILE *fp; + + fp = fopen(file_name, "w"); + if (NULL == fp) return 1; + fprintf(fp,"{\n\t\"struct\": [\n\t\t{\n\t\t\t\"type\": \"void*\",\n\t\t\t\"value\": null\n\t\t}"); + + TEST_S2J_STRUCT(McUsrInfoT, 0 , fp); + TEST_S2J_STRUCT(McBaseOrdrT, 0 , fp); + TEST_S2J_STRUCT(McBaseOrdrArrayT, 0 , fp); + TEST_S2J_STRUCT(McOcoBaseOrdrT, 0 , fp); + + fprintf(fp,"\n\t]\n}"); + fclose(fp); + return 0; +} + + + + int s2j_test2(void) + { + + char file_name[] = "struct_defination.json"; + FILE *fp; + + fp = fopen(file_name, "rb"); + if (NULL == fp) return 1; + + fseek(fp,0L,SEEK_END); + int flen=ftell(fp); + char* p=(char *)malloc(flen+1); + if(p==NULL) + { + fclose(fp); + return 0; + } + fseek(fp,0L,SEEK_SET); + fread(p,flen,1,fp); + p[flen]=0; + + printf("\nstruct_defination.json:\n%s\n",p); + + cJSON *json_obj =cJSON_Parse(p); + CHECK_NOT_NULL(json_obj) + cJSON *json_struct = cJSON_GetObjectItem(json_obj, "struct"); + CHECK_NOT_NULL(json_struct) + + int array_size = cJSON_GetArraySize(json_struct); + printf("\nsize:\n%d\n",array_size); + int i = 0; \ + + TEST_S2J_JSON(McUsrInfoT, array_size); + TEST_S2J_JSON(McBaseOrdrT, array_size); + TEST_S2J_JSON(McBaseOrdrArrayT, array_size); + TEST_S2J_JSON(McOcoBaseOrdrT, array_size); + + fclose(fp); + free(p); + return 0; +} + + +#endif// DEBUGS2J + +#ifdef __cplusplus +} +#endif /* end of __cplusplus */ \ No newline at end of file diff --git a/src/subprojects/struct2json/demo/my_struct_2_json.h b/src/subprojects/struct2json/demo/my_struct_2_json.h new file mode 100644 index 00000000..5547764d --- /dev/null +++ b/src/subprojects/struct2json/demo/my_struct_2_json.h @@ -0,0 +1,23 @@ +#ifdef __cplusplus +extern "C" { +#endif + +cJSON *struct_to_json_McUsrInfoT(void* struct_obj); + +void *json_to_struct_McUsrInfoT(cJSON* json_obj); + +cJSON *struct_to_json_McBaseOrdrT(void* struct_obj); + +void *json_to_struct_McBaseOrdrT(cJSON* json_obj); + +cJSON *struct_to_json_McBaseOrdrArrayT(void* struct_obj); + +void *json_to_struct_McBaseOrdrArrayT(cJSON* json_obj); + +cJSON *struct_to_json_McOcoBaseOrdrT(void* struct_obj); + +void *json_to_struct_McOcoBaseOrdrT(cJSON* json_obj); + +#ifdef __cplusplus +} +#endif /* end of __cplusplus */ \ No newline at end of file diff --git a/src/subprojects/struct2json/demo/my_struct_2_json.inc b/src/subprojects/struct2json/demo/my_struct_2_json.inc new file mode 100644 index 00000000..f9931b10 --- /dev/null +++ b/src/subprojects/struct2json/demo/my_struct_2_json.inc @@ -0,0 +1,131 @@ +/* + * This file is the demo part of the struct2json Library. + * + * Copyright (c) 2021, YuXuebao, + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Function: It is an head file for this library. You can see all be called functions. + * Created on: 2021-02-20 + */ + +/* +gcc ../cJSON/cJSON.c ../struct2json/src/*.c ./*.c -I ../cJSON/ -I ../struct2json/inc/ -lm -DDEBUGS2J -g -o tests2j + +*/ + +#include +#include +#include +#include "../cJSON/cJSON.h" +#include "../struct2json/inc/s2j.h" + + +#ifndef CHECK_NOT_NULL +#define CHECK_NOT_NULL(p) \ +do\ +{\ + if (NULL == (p)) \ + {\ + fprintf (stdout, "\nWARNING: Null pointer accured(%s). [FUNCTION:%s, FILE:%s, LINE:%d]\n", #p,__FUNCTION__, __FILE__, __LINE__); \ + return -1; \ + }\ +} while (0); +#endif + + +#define struct_para_json2bin(para_type,bin_para, type, value) \ + else if (0 == strcmp( #para_type, type)){ \ + para_type* p_##para_type = (para_type*)json_to_struct_##para_type(value); \ + *bin_para = p_##para_type; \ + } \ + + +#define struct_para_bin2json(para_type,bin_para, type,json_para) \ + else if (0 == strcmp( #para_type, type)) { \ + cJSON* value_new = struct_to_json_##para_type(bin_para); \ + cJSON_ReplaceItemInObject(*json_para,"value",value_new); \ + } \ + + +#ifdef DEBUGS2J + +#define TEST_S2J_STRUCT(type, value, file) \ + type struct_obj##type; \ + memset(&struct_obj##type, value, sizeof(type)); \ + cJSON *json_obj##type = struct_to_json_##type(&struct_obj##type); \ + char* str_json##type = cJSON_Print(json_obj##type); \ + printf("s2j:\n%s: %s\n",#type, str_json##type); \ + fprintf(file,",\n\t\t{\n\t\t\t\"type\": \"%s\",\n\t\t\t\"value\": %s\n\t\t}", #type, str_json##type); \ + cJSON *json_obj1##type =cJSON_Parse(str_json##type); \ + cJSON_bool json_cmp1##type = cJSON_Compare(json_obj ##type, json_obj1##type, 1); \ + printf("%s:json_cmp1:%d\n\n\n",#type, json_cmp1##type); \ + type *p_struct_obj##type =(type *)json_to_struct_##type(json_obj1##type); \ + int cmp##type = memcmp(p_struct_obj##type, &struct_obj##type, sizeof(type)); \ + printf("\n"); \ + cJSON *json_obj2##type = struct_to_json_##type(p_struct_obj##type); \ + char* str_json2##type = cJSON_Print(json_obj2##type); \ + printf("s2j2s2j:\n%s: %s\n",#type, str_json2##type); \ + int str_cmp##type = strcmp(str_json##type, str_json2##type); \ + printf("\n%s:strcmp:%d\n",#type, str_cmp##type); \ + cJSON_bool json_cmp2##type = cJSON_Compare(json_obj##type, json_obj2##type, 1); \ + printf("%s:json_cmp2:%d\n\n\n",#type, json_cmp2##type); \ + free(str_json##type); \ + free(str_json2##type); \ + s2j_delete_struct_obj(p_struct_obj##type); \ + s2j_delete_json_obj(json_obj##type); \ + s2j_delete_json_obj(json_obj1##type); \ + s2j_delete_json_obj(json_obj2##type); \ + + +#define TEST_S2J_JSON(type, size) \ + cJSON *json_struct_##type = NULL; \ + i = 0; \ + for (; i < size;i++) { \ + cJSON *json_struct_item = cJSON_GetArrayItem(json_struct, i); \ + cJSON *json_struct_item_type = cJSON_GetObjectItem(json_struct_item, "type"); \ + char* str_type = json_struct_item_type->valuestring; \ + if (0 == strcmp(#type, str_type)) { \ + json_struct_##type = cJSON_GetObjectItem(json_struct_item, "value"); \ + printf("\ntype:%s:\n",#type); \ + break; \ + } \ + } \ + if (json_struct_##type != NULL) { \ + cJSON * json_obj1##type = json_struct_##type; \ + char* str_json1##type = cJSON_Print(json_obj1##type); \ + printf("\nj2str:\n%s: %s\n",#type, str_json1##type); \ + type *p_struct_obj##type =(type *)json_to_struct_##type(json_obj1##type); \ + cJSON *json_obj2##type = struct_to_json_##type(p_struct_obj##type); \ + char* str_json2##type = cJSON_Print(json_obj2##type); \ + printf("\nj2s2j:\n%s: %s\n",#type, str_json2##type); \ + int str_cmp##type = strcmp(str_json1##type, str_json2##type); \ + printf("\n%s:strcmp:%d\n",#type, str_cmp##type); \ + cJSON_bool json_cmp##type = cJSON_Compare(json_obj1##type, json_obj2##type, 1); \ + printf("%s:json_cmp:%d\n\n\n",#type, json_cmp##type); \ + free(str_json1##type); \ + free(str_json2##type); \ + s2j_delete_struct_obj(p_struct_obj##type); \ + s2j_delete_json_obj(json_obj1##type); \ + s2j_delete_json_obj(json_obj2##type); \ + } + +#endif// DEBUGS2J + diff --git a/src/subprojects/struct2json/demo/struct_defination.json b/src/subprojects/struct2json/demo/struct_defination.json new file mode 100644 index 00000000..7f345f3d --- /dev/null +++ b/src/subprojects/struct2json/demo/struct_defination.json @@ -0,0 +1,140 @@ +{ + "struct": [ + { + "type": "void*", + "value": null + }, + { + "type": "McUsrInfoT", + "value": { + "pInt": 0, + "pIntArray": [ + 0, + 0 + ], + "fun": 0, + "funArray": [ + 0, + 0 + ], + "day1": 0, + "day2": 0, + "day2Array": [ + 0, + 0 + ], + "id": 0, + "idArray": [ + 0, + 0 + ], + "usrType": 0, + "usrName": "", + "usrNameArray": [ + "", + "" + ], + "usrSqno": 0, + "ussSqnoArray": [ + 0, + 0 + ], + "jobSqno": 0, + "jobSqnoArray": [ + 0, + 0 + ], + "rate": 0, + "rateArray": [ + 0, + 0 + ], + "price": 0, + "priceArray": [ + 0, + 0 + ] + } + }, + { + "type": "McBaseOrdrT", + "value": { + "taskSqno": 0, + "taskSqnoArray": [ + 0, + 0 + ], + "price": 0, + "priceArray": [ + 0, + 0 + ] + } + }, + { + "type": "McBaseOrdrArrayT", + "value": { + "mcBaseOrdrArray": [ + { + "taskSqno": 0, + "taskSqnoArray": [ + 0, + 0 + ], + "price": 0, + "priceArray": [ + 0, + 0 + ] + }, + { + "taskSqno": 0, + "taskSqnoArray": [ + 0, + 0 + ], + "price": 0, + "priceArray": [ + 0, + 0 + ] + } + ] + } + }, + { + "type": "McOcoBaseOrdrT", + "value": { + "mcBaseOrdrAry": { + "mcBaseOrdrArray": [ + { + "taskSqno": 0, + "taskSqnoArray": [ + 0, + 0 + ], + "price": 0, + "priceArray": [ + 0, + 0 + ] + }, + { + "taskSqno": 0, + "taskSqnoArray": [ + 0, + 0 + ], + "price": 0, + "priceArray": [ + 0, + 0 + ] + } + ] + }, + "pUsrDef": 0 + } + } + ] +} \ No newline at end of file diff --git a/src/subprojects/struct2json/demo/struct_defination.txt b/src/subprojects/struct2json/demo/struct_defination.txt new file mode 100644 index 00000000..ac080e74 --- /dev/null +++ b/src/subprojects/struct2json/demo/struct_defination.txt @@ -0,0 +1,43 @@ + +typedef struct McUsrInfoS +{ + int *pInt; + int *pIntArray[2]; + fun_ptr_CbT fun; + fun_ptr_CbT funArray[2]; + enum WEEK_DAY day1; + enumWEEK_DAY_T day2; + enumWEEK_DAY_T day2Array[2]; + unsigned char id; + unsigned char idArray[2]; + char usrType; + char usrName[8]; + char usrNameArray[2][8]; + int32 usrSqno; + int32 ussSqnoArray[2]; + int64 jobSqno; + int64 jobSqnoArray[2]; + float rate; + float rateArray[2]; + double price; + double priceArray[2]; +} McUsrInfoT, *pMcUsrInfoT; + +typedef struct McBaseOrdrS +{ + short taskSqno; + short taskSqnoArray[2]; + double price; + double priceArray[2]; +} McBaseOrdrT, *pMcBaseOrdrT; + +typedef struct McBaseOrdrArray +{ + McBaseOrdrT mcBaseOrdrArray[2]; +} McBaseOrdrArrayT; + +typedef struct McOcoBaseOrdrS +{ + McBaseOrdrArrayT mcBaseOrdrAry; + void * pUsrDef; +} McOcoBaseOrdrT, *pMcOcoBaseOrdrT; diff --git a/src/subprojects/struct2json/demo/tests2j b/src/subprojects/struct2json/demo/tests2j new file mode 100644 index 0000000000000000000000000000000000000000..ba710c60f80ec0c4d67be4b2379097dbfe886f56 GIT binary patch literal 89040 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 literal 0 HcmV?d00001 diff --git a/src/subprojects/struct2json/docs/README.md b/src/subprojects/struct2json/docs/README.md new file mode 100644 index 00000000..da9229a0 --- /dev/null +++ b/src/subprojects/struct2json/docs/README.md @@ -0,0 +1,4 @@ +|File or folder name |Description| +|:----- |:----| +|en |English documents| +|zh |中文文档(简体)| \ No newline at end of file diff --git a/src/subprojects/struct2json/docs/readme.md b/src/subprojects/struct2json/docs/readme.md new file mode 100644 index 00000000..da9229a0 --- /dev/null +++ b/src/subprojects/struct2json/docs/readme.md @@ -0,0 +1,4 @@ +|File or folder name |Description| +|:----- |:----| +|en |English documents| +|zh |中文文档(简体)| \ No newline at end of file diff --git a/src/subprojects/struct2json/docs/zh/api.md b/src/subprojects/struct2json/docs/zh/api.md new file mode 100644 index 00000000..4d1bee4a --- /dev/null +++ b/src/subprojects/struct2json/docs/zh/api.md @@ -0,0 +1,194 @@ +# struct2json API Îĵµ + +--- + +ËùÓÐ֧³ֵÄAPI½ӿڶ¼ÔÚ `\struct2json\inc\s2j.h` ÖÐÉùÃ÷¡£ÒÔÏÂÄÚÈݽ϶࣬½¨ÒéʹÓà CTRL+F ËÑË÷¡£ + +## 1¡¢Óû§ʹÓýӿÚ + +### 1.1 ³õʼ»¯ + +³õʼ»¯µÄstruct2json¿⡣ + +> ע£ºĿǰÖ÷Ҫ³õʼ»¯¸ÿ⼰cJSON¿âËùÐèµÄÄڴæ¹ÜÀí·½·¨¡£ĬÈÏʹÓõÄ `malloc` ¼° `free` ×÷ΪÄڴæ¹ÜÀí·½·¨£¬Èç¹ûʹÓÃĬÈÏÄڴæ¹ÜÀí·½ʽ£¬ÔòÎÞÐè³õʼ»¯¡£ + +```C +void s2j_init(S2jHook *hook) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|hook |ָ¶¨µÄÄڴæ¹ÜÀí·½·¨| + +### 1.2 ½«½ṹÌå¶ÔÏóת»»£¨ÐòÁл¯£©ΪJSON¶ÔÏó + +עÒ⣺ÒÔÏÂAPI¾ù²ÉÓú궨Ò巽ʽ£¬ÔÚʹÓÃʱÓ볣ÓÃAPI·½·¨ÐÎʽÂÔÓв»ͬ£¬ÇëעÒâ²鿴Demo¡£ + +#### 1.2.1 ´´½¨JSON¶ÔÏó + +```C +s2j_create_json_obj(json_obj) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|json_obj |JSON¶ÔÏó| + +#### 1.2.2 ת»»»ù±¾ÀàÐÍԪËØ + +עÒ⣺ÕâÀïµĽṹÌåԪËػù±¾ÀàÐÍֻ֧³Ö `int` ¡¢ `string` ¼° `double` £¬ÆäËûÀàÐÍת»»ʱӦ¿¼ÂÇѡȡÈýÕßÖеÄÆäÖÐһÖÖ×÷Ŀ±êÀàÐͣ¬ѡÔñ±ê׼ΪÁ½ÕßÀàÐͼä¿ɱ»ÎÞËðÏ໥ת»»¡£ÀýÈ磺½ṹÌåԪËØÀàÐÍΪ `uint8_t` ¡¢`uint16_t` ¡¢`int16_t` ¡¢ `size_t` ¡¢`ijָÕëµØַ` µÈÀàÐͿÉÒÔѡÔñ `int` ×÷ΪÈë²Ρ£ + +```C +s2j_json_set_basic_element(to_json, from_struct, type, element) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|to_json |Ŀ±êJSON¶ÔÏó| +|from_struct |Դ½ṹÌå¶ÔÏó| +|type |Դ½ṹÌå¶ÔÏóԪËØÀàÐͣ¬ÕâÀïֻ֧³Öint¡¢string¡¢double| +|element |Դ½ṹÌå¶ÔÏóԪËØ| + +#### 1.2.3 ת»»Êý×éÀàÐÍԪËØ + +```C +s2j_json_set_array_element(to_json, from_struct, type, element, size) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|to_json |Ŀ±êJSON¶ÔÏó| +|from_struct |Դ½ṹÌå¶ÔÏó| +|type |Դ½ṹÌå¶ÔÏóԪËصĻù±¾ÀàÐ͡£²ο¼1.2.2ÖжԻù±¾ÀàÐ͵ÄҪÇó| +|element |Դ½ṹÌå¶ÔÏóԪËØ| +|size |Դ½ṹÌå¶ÔÏóÊý×éԪËصij¤¶È| + +#### 1.2.4 ת»»½ṹÌåÀàÐÍԪËأ¨¼´×ӽṹÌ壩 + +```C +s2j_json_set_struct_element(child_json, to_json, child_struct, from_struct, type, element) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|child_json |Ŀ±êJSON¶ÔÏóµÄ×ÓJSON¶ÔÏó| +|to_json |Ŀ±êJSON¶ÔÏó| +|child_struct |Դ½ṹÌå¶ÔÏóµÄ×ӽṹÌå¶ÔÏó| +|from_struct |Դ½ṹÌå¶ÔÏó| +|type |Դ½ṹÌå¶ÔÏóԪËأ¨×ӽṹÌ壩ÀàÐÍ| +|element |Դ½ṹÌå¶ÔÏóԪËØ| + +Àý×ӣº +```C +typedef struct { + char name[16]; +} Hometown; + +typedef struct { + uint8_t id; + char name[10]; + Hometown hometown; +} Student; + +Student orignal_struct_student = { + .id = 24, + .name = "armink", + .hometown.name = "China", +} +Student *struct_student = &orignal_struct_student; +/* ´´½¨¿ÕStudent JSON¶ÔÏó */ +s2j_create_json_obj(json_student); +/* ÐòÁл¯£¨ת»»£©Student½ṹÌåµÄidԪËØ */ +s2j_json_set_basic_element(json_student, struct_student, int, id); +/* ÐòÁл¯Student½ṹÌåµÄnameԪËØ */ +s2j_json_set_basic_element(json_student, struct_student, string, name); +/* ÐòÁл¯Student½ṹÌåµÄ×ӽṹÌåhometownԪËØ */ +s2j_json_set_struct_element(json_hometown, json_student, struct_hometown, struct_student, Hometown, hometown); +/* ÐòÁл¯Hometown½ṹÌåµÄnameԪËØ */ +s2j_json_set_basic_element(json_hometown, struct_hometown, string, name); +``` + +### 1.3 ½«JSON¶ÔÏóת»»£¨·´ÐòÁл¯£©Ϊ½ṹÌå¶ÔÏó + +#### 1.3.1 ´´½¨½ṹÌå¶ÔÏó + +```C +s2j_create_struct_obj(struct_obj, type) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|struct_obj |½ṹÌå¶ÔÏó| +|type |½ṹÌåÀàÐÍ| + +#### 1.3.2 ת»»»ù±¾ÀàÐÍԪËØ + +```C +s2j_struct_get_basic_element(to_struct, from_json, type, element) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|to_struct |Ŀ±ê½ṹÌå¶ÔÏó| +|from_json |ԴJSON¶ÔÏó| +|type |Ŀ±ê½ṹÌå¶ÔÏóԪËØÀàÐ͡£²ο¼1.2.2ÖжԻù±¾ÀàÐ͵ÄҪÇó| +|element |Ŀ±ê½ṹÌå¶ÔÏóԪËØ| + +#### 1.3.3 ת»»Êý×éÀàÐÍԪËØ + +```C +s2j_struct_get_array_element(to_struct, from_json, type, element) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|to_struct |Ŀ±ê½ṹÌå¶ÔÏó| +|from_json |ԴJSON¶ÔÏó| +|type |Ŀ±ê½ṹÌå¶ÔÏóԪËØÀàÐ͡£²ο¼1.2.2ÖжԻù±¾ÀàÐ͵ÄҪÇó| +|element |Ŀ±ê½ṹÌå¶ÔÏóԪËØ| + +#### 1.3.4 ת»»½ṹÌåÀàÐÍԪËأ¨¼´×ÓJSON£© + +```C +s2j_struct_get_struct_element(child_struct, to_struct, child_json, from_json, type, element) +``` + +|²ÎÊý |ÃèÊö| +|:----- |:----| +|child_struct |Ŀ±ê½ṹÌå¶ÔÏóµÄ×ӽṹÌå¶ÔÏó| +|to_struct |Ŀ±ê½ṹÌå¶ÔÏó| +|child_json |ԴJSON¶ÔÏóµÄ×ÓJSON¶ÔÏó| +|from_json |ԴJSON¶ÔÏó| +|type |ԴJSON¶ÔÏóԪËأ¨×ÓJSON£©ÀàÐÍ| +|element |ԴJSON¶ÔÏóԪËØ| + +Àý×ӣº +```C +typedef struct { + char name[16]; +} Hometown; + +typedef struct { + uint8_t id; + char name[10]; + Hometown hometown; +} Student; + +char orignal_json_string_student[] = "{\"id\":24, \"name\":\"armink\", \"hometown\":{\"name\":\"China\"}}"; +/* ´´½¨Student JSON¶ÔÏó */ +cJSON *json_student = cJSON_Parse(orignal_json_string_student); +/* ´´½¨¿ÕStudent½ṹÌå¶ÔÏó */ +s2j_create_struct_obj(struct_student, Student); +/* ·´ÐòÁл¯Student½ṹÌåµÄidԪËØ */ +s2j_struct_get_basic_element(struct_student, json_student, int, id); +/* ·´ÐòÁл¯Student½ṹÌåµÄnameԪËØ */ +s2j_struct_get_basic_element(struct_student, json_student, string, name); +/* ·´ÐòÁл¯Student½ṹÌåµÄ×ӽṹÌåhometownԪËØ */ +s2j_struct_get_struct_element(struct_hometown, struct_student, json_hometown, json_student, Hometown, hometown); +/* ·´ÐòÁл¯Hometown½ṹÌåµÄnameԪËØ */ +s2j_struct_get_basic_element(struct_hometown, json_hometown, string, name); +``` + +## 2¡¢עÒâ + +- ¸ÿâֻÊÊÓÃÓÚC99¼°ÆäÒÔÉϱê׼±àÒëÆ÷ \ No newline at end of file diff --git a/src/subprojects/struct2json/docs/zh/assets/not_use_struct2json.c b/src/subprojects/struct2json/docs/zh/assets/not_use_struct2json.c new file mode 100644 index 00000000..ade8a086 --- /dev/null +++ b/src/subprojects/struct2json/docs/zh/assets/not_use_struct2json.c @@ -0,0 +1,30 @@ +cJSON *struct_to_json(void* struct_obj) { + Student *struct_student = (Student *) struct_obj; + cJSON *score, *score_element; + size_t index = 0; + + /* 创建Student JSON对象 */ + cJSON *json_student = cJSON_CreateObject(); + + /* 序列化数据到Student JSON对象 */ + cJSON_AddNumberToObject(json_student, "id", struct_student->id); + cJSON_AddNumberToObject(json_student, "weight", struct_student->weight); + score = cJSON_CreateArray(); + if (score) { + while (index < 8) { + score_element = cJSON_CreateNumber(struct_student->score[index++]); + cJSON_AddItemToArray(score, score_element); + } + cJSON_AddItemToObject(json_student, "score", score); + } + cJSON_AddStringToObject(json_student, "name", struct_student->name); + + /* 序列化数据到Student.Hometown JSON对象 */ + Hometown *hometown_struct = &(struct_student->hometown); + cJSON *hometown_json = cJSON_CreateObject(); + cJSON_AddItemToObject(json_student, "hometown", hometown_json); + cJSON_AddStringToObject(hometown_json, "name", hometown_struct->name); + + /* 返回Student JSON对象指针 */ + return json_student; +} diff --git a/src/subprojects/struct2json/docs/zh/assets/not_use_struct2json_for_json.c b/src/subprojects/struct2json/docs/zh/assets/not_use_struct2json_for_json.c new file mode 100644 index 00000000..18649c32 --- /dev/null +++ b/src/subprojects/struct2json/docs/zh/assets/not_use_struct2json_for_json.c @@ -0,0 +1,46 @@ +void *json_to_struct(cJSON* json_obj) { + cJSON *json_temp, *score, *score_element; + Student *struct_student; + size_t index = 0, score_size = 0; + + /* 创建Student结构体对象 */ + struct_student = s2j_malloc(sizeof(Student)); + if (struct_student) { + memset(struct_student, 0, sizeof(Student)); + } + + /* 反序列化数据到Student结构体对象 */ + json_temp = cJSON_GetObjectItem(json_obj, "id"); + if (json_temp) { + struct_student->id = json_temp->valueint; + } + score = cJSON_GetObjectItem(json_obj, "score") + if (score) { + score_size = cJSON_GetArraySize(score); + while (index < score_size) { + score_element = cJSON_GetArrayItem(score, index); + if (score_element) { + struct_student->score[index++] = score_element->valueint; + } + } + } + json_temp = cJSON_GetObjectItem(json_obj, "name"); + if (json_temp) { + strcpy(struct_student->name, json_temp->valuestring); + } + json_temp = cJSON_GetObjectItem(json_obj, "weight"); + if (json_temp) { + struct_student->weight = json_temp->valuedouble; + } + + /* 反序列化数据到Student.Hometown结构体对象 */ + Hometown *struct_hometown = &(struct_student->hometown); + cJSON *json_hometown = cJSON_GetObjectItem(json_obj, "hometown"); + json_temp = cJSON_GetObjectItem(json_hometown, "name"); + if (json_temp) { + strcpy(struct_hometown->name, json_temp->valuestring); + } + + /* 返回Student结构体对象指针 */ + return struct_student; +} diff --git a/src/subprojects/struct2json/docs/zh/assets/used_struct2json.c b/src/subprojects/struct2json/docs/zh/assets/used_struct2json.c new file mode 100644 index 00000000..6c234fff --- /dev/null +++ b/src/subprojects/struct2json/docs/zh/assets/used_struct2json.c @@ -0,0 +1,19 @@ +cJSON *struct_to_json(void* struct_obj) { + Student *struct_student = (Student *)struct_obj; + + /* 创建Student JSON对象 */ + s2j_create_json_obj(json_student); + + /* 序列化数据到Student JSON对象 */ + s2j_json_set_basic_element(json_student, struct_student, int, id); + s2j_json_set_basic_element(json_student, struct_student, double, weight); + s2j_json_set_array_element(json_student, struct_student, int, score, 8); + s2j_json_set_basic_element(json_student, struct_student, string, name); + + /* 序列化数据到Student.Hometown JSON对象 */ + s2j_json_set_struct_element(json_hometown, json_student, struct_hometown, struct_student, Hometown, hometown); + s2j_json_set_basic_element(json_hometown, struct_hometown, string, name); + + /* 返回Student JSON对象指针 */ + return json_student; +} diff --git a/src/subprojects/struct2json/docs/zh/assets/used_struct2json_for_json.c b/src/subprojects/struct2json/docs/zh/assets/used_struct2json_for_json.c new file mode 100644 index 00000000..70728571 --- /dev/null +++ b/src/subprojects/struct2json/docs/zh/assets/used_struct2json_for_json.c @@ -0,0 +1,17 @@ +void *json_to_struct(cJSON* json_obj) { + /* 创建Student结构体对象 */ + s2j_create_struct_obj(struct_student, Student); + + /* 反序列化数据到Student结构体对象 */ + s2j_struct_get_basic_element(struct_student, json_obj, int, id); + s2j_struct_get_array_element(struct_student, json_obj, int, score); + s2j_struct_get_basic_element(struct_student, json_obj, string, name); + s2j_struct_get_basic_element(struct_student, json_obj, double, weight); + + /* 反序列化数据到Student.Hometown结构体对象 */ + s2j_struct_get_struct_element(struct_hometown, struct_student, json_hometown, json_obj, Hometown, hometown); + s2j_struct_get_basic_element(struct_hometown, json_hometown, string, name); + + /* 返回Student结构体对象指针 */ + return struct_student; +} diff --git a/src/subprojects/struct2json/docs/zh/images/not_use_struct2json.png b/src/subprojects/struct2json/docs/zh/images/not_use_struct2json.png new file mode 100644 index 0000000000000000000000000000000000000000..a686280adb3a8cf8394dab0a20c47a96b89f0e49 GIT binary patch literal 85919 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 literal 0 HcmV?d00001 diff --git a/src/subprojects/struct2json/docs/zh/images/not_use_struct2json_for_json.png b/src/subprojects/struct2json/docs/zh/images/not_use_struct2json_for_json.png new file mode 100644 index 0000000000000000000000000000000000000000..3eecd20cdcba2ed9a7a62d1ee148be986c6ab135 GIT binary patch literal 71583 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 literal 0 HcmV?d00001 diff --git a/src/subprojects/struct2json/docs/zh/images/used_struct2json.png b/src/subprojects/struct2json/docs/zh/images/used_struct2json.png new file mode 100644 index 0000000000000000000000000000000000000000..681dbd4b4f24169c5e898d662ec894ba36df5515 GIT binary patch literal 59204 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≀wS1L*26uP-dHXqE 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 WwO}jrwK)t73=E#GelF{r5}E*L&?jyH literal 0 HcmV?d00001 diff --git a/src/subprojects/struct2json/docs/zh/readme.md b/src/subprojects/struct2json/docs/zh/readme.md new file mode 100644 index 00000000..d01eeaf8 --- /dev/null +++ b/src/subprojects/struct2json/docs/zh/readme.md @@ -0,0 +1,3 @@ +|文件名 |描述| +|:----- |:----| +|api.md |API 说明| \ No newline at end of file diff --git a/src/subprojects/struct2json/meson.build b/src/subprojects/struct2json/meson.build new file mode 100644 index 00000000..28df97cf --- /dev/null +++ b/src/subprojects/struct2json/meson.build @@ -0,0 +1,57 @@ +project('struct2json', + ['c'], + version:'1.0.0') + +pkg = import('pkgconfig') + +if get_option('buildtype') == 'debug' + add_project_arguments(['-ggdb', + '-g3', + '-Og', + ], language: ['c']) +else + add_project_arguments(['-Os'], language: ['c']) +endif + +struct2json_srcs = [ + './cJSON/cJSON.c', + './cJSON/cJSON_Utils.c', + './struct2json/src/s2j.c', +] + +struct2json_headers = [ + './cJSON/cJSON_Utils.h', + './cJSON/cJSON.h', + './struct2json/inc/s2j.h', + './struct2json/inc/s2jdef.h', +] + +struct2json_deps = [] + +incdir = include_directories('cJSON', 'struct2json/inc') + +libstruct2json = static_library('struct2json', + struct2json_srcs, + include_directories: [incdir], + dependencies: struct2json_deps, + install: true) + +install_headers(struct2json_headers, install_dir: 'include/cjson') + +pkg.generate(libstruct2json, + name:'struct2json', + description: 'struct to json', + version:'1.0.0') + +# Register the fallback the parent resolves through this wrap's [provide] +# section: dependency('struct2json'). Includes: '.' exposes the cjson/ +# forwarding shims ( etc.); 'cJSON' and 'struct2json/inc' +# keep the library headers' own quoted includes resolving, exactly like the +# upstream incdir. +struct2json_sdep = declare_dependency( + link_with: libstruct2json, + include_directories: [include_directories('.'), + include_directories('cJSON'), + include_directories('struct2json/inc')], + version: '1.0.0') +meson.override_dependency('struct2json', struct2json_sdep) diff --git a/src/subprojects/struct2json/struct2json/inc/s2j.h b/src/subprojects/struct2json/struct2json/inc/s2j.h new file mode 100644 index 00000000..d1b1f9f9 --- /dev/null +++ b/src/subprojects/struct2json/struct2json/inc/s2j.h @@ -0,0 +1,113 @@ +/* + * This file is part of the struct2json Library. + * + * Copyright (c) 2015, Armink, + * Copyright (c) 2018, YuXuebao, + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Function: It is an head file for this library. You can see all be called functions. + * Created on: 2015-10-14 + */ + +#ifndef __S2J_H__ +#define __S2J_H__ + +#include "cJSON.h" +#include +#include "s2jdef.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* struct2json software version number */ +#define S2J_SW_VERSION "2.0.0" + + +/* Create JSON object */ +#define s2j_create_json_obj(json_obj) \ + S2J_CREATE_JSON_OBJECT(json_obj) + +/* Delete JSON object */ +#define s2j_delete_json_obj(json_obj) \ + S2J_DELETE_JSON_OBJECT(json_obj) + +/* Set basic type element for JSON object */ +#define s2j_json_set_basic_element(to_json, from_struct, type, element) \ + S2J_JSON_SET_BASIC_ELEMENT(to_json, from_struct, type, element) + +/* Set array type element for JSON object */ +#define s2j_json_set_array_element(to_json, from_struct, type, element, size) \ + S2J_JSON_SET_ARRAY_ELEMENT(to_json, from_struct, type, element, size) + +/* Set child structure type element for JSON object */ +#define s2j_json_set_struct_element(child_json, to_json, child_struct, from_struct, type, element) \ + S2J_JSON_SET_STRUCT_ELEMENT(child_json, to_json, child_struct, from_struct, type, element) + +/* Create structure object */ +#define s2j_create_struct_obj(struct_obj, type) \ + S2J_CREATE_STRUCT_OBJECT(struct_obj, type) + +/* Delete structure object */ +#define s2j_delete_struct_obj(struct_obj) \ + S2J_DELETE_STRUCT_OBJECT(struct_obj) + +/* Get basic type element for structure object */ +#define s2j_struct_get_basic_element(to_struct, from_json, type, element) \ + S2J_STRUCT_GET_BASIC_ELEMENT(to_struct, from_json, type, element) + +#define s2j_struct_get_basic_element_ex(to_struct, from_json, type, element, _defval) \ + S2J_STRUCT_GET_BASIC_ELEMENT_EX(to_struct, from_json, type, element, _defval) + +/* Get array type element for structure object */ +#define s2j_struct_get_array_element(to_struct, from_json, type, element) \ + S2J_STRUCT_GET_ARRAY_ELEMENT(to_struct, from_json, type, element) + +#define s2j_struct_get_array_element_ex(to_struct, from_json, type, element, size, _defval) \ + S2J_STRUCT_GET_ARRAY_ELEMENT_EX(to_struct, from_json, type, element, size, _defval) + +/* Get child structure type element for structure object */ +#define s2j_struct_get_struct_element(child_struct, to_struct, child_json, from_json, type, element) \ + S2J_STRUCT_GET_STRUCT_ELEMENT(child_struct, to_struct, child_json, from_json, type, element) + +/* Set child structure type element for JSON object by function [cJSON * struct_to_json_##type(void*)] */ +#define s2j_json_set_struct_element_by_func(to_json, from_struct, type, element) \ + S2J_JSON_SET_STRUCT_ELEMENT_BY_FUNC(to_json, from_struct, type, element) + +/* Set child structure array type element for JSON object by function [cJSON * struct_to_json_##type(void*)] */ +#define s2j_json_set_struct_array_element_by_func(to_json, from_struct, type, element, array_size) \ + S2J_JSON_SET_STRUCT_ARRAY_ELEMENT_BY_FUNC(to_json, from_struct, type, element, array_size) + +/* Get child structure type element for structure object by function [void *json_to_struct_#type(cJSON*)]*/ +#define s2j_struct_get_struct_element_by_func(to_struct, from_json, type, element) \ + S2J_STRUCT_GET_STRUCT_ELEMENT_BY_FUNC(to_struct, from_json, type, element) + +/* Get struct array type element for structure object by function [void *json_to_struct_#type(cJSON*)] */ +#define s2j_struct_get_struct_array_element_by_func(to_struct, from_json, type, element) \ + S2J_STRUCT_GET_STRUCT_ARRAY_ELEMENT_BY_FUNC(to_struct, from_json, type, element) + +extern S2jHook s2jHook; +void s2j_init(S2jHook *hook); + +#ifdef __cplusplus +} +#endif + +#endif /* __S2J_H__ */ diff --git a/src/subprojects/struct2json/struct2json/inc/s2jdef.h b/src/subprojects/struct2json/struct2json/inc/s2jdef.h new file mode 100644 index 00000000..63b6e936 --- /dev/null +++ b/src/subprojects/struct2json/struct2json/inc/s2jdef.h @@ -0,0 +1,286 @@ +/* + * This file is part of the struct2json Library. + * + * Copyright (c) 2015, Armink, + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Function: It is an head file for this library. + * Created on: 2015-10-14 + */ + +#ifndef __S2JDEF_H__ +#define __S2JDEF_H__ + +#include "cJSON.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define S2J_ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0])) + + +typedef struct { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} S2jHook, *S2jHook_t; + +#define S2J_STRUCT_GET_int_ELEMENT(to_struct, from_json, _element) \ + json_temp = cJSON_GetObjectItem(from_json, #_element); \ + if (json_temp) (to_struct)->_element = json_temp->valueint; + +#define S2J_STRUCT_GET_int_ELEMENT_EX(to_struct, from_json, _element, _defval) \ + { \ + if (from_json) { \ + json_temp = cJSON_GetObjectItem(from_json, #_element); \ + if (json_temp) (to_struct)->_element = json_temp->valueint; \ + else (to_struct)->_element = _defval; \ + } else { \ + (to_struct)->_element = _defval; \ + } \ + } + +#define S2J_STRUCT_GET_string_ELEMENT(to_struct, from_json, _element) \ + json_temp = cJSON_GetObjectItem(from_json, #_element); \ + if (json_temp) strncpy((to_struct)->_element, json_temp->valuestring,sizeof((to_struct)->_element)-1); + +#define S2J_STRUCT_GET_string_ELEMENT_EX(to_struct, from_json, _element, _defval) \ + { \ + if (from_json) { \ + json_temp = cJSON_GetObjectItem(from_json, #_element); \ + if (json_temp) strncpy((to_struct)->_element, json_temp->valuestring,sizeof((to_struct)->_element)-1); \ + else strncpy((to_struct)->_element, _defval,sizeof((to_struct)->_element)-1); \ + } else { \ + strncpy((to_struct)->_element, _defval,sizeof((to_struct)->_element)-1); \ + } \ + } + +#define S2J_STRUCT_GET_double_ELEMENT(to_struct, from_json, _element) \ + json_temp = cJSON_GetObjectItem(from_json, #_element); \ + if (json_temp) (to_struct)->_element = json_temp->valuedouble; + +#define S2J_STRUCT_GET_double_ELEMENT_EX(to_struct, from_json, _element, _defval) \ + { \ + if (from_json) { \ + json_temp = cJSON_GetObjectItem(from_json, #_element); \ + if (json_temp) (to_struct)->_element = json_temp->valuedouble; \ + else (to_struct)->_element = _defval; \ + } else { \ + (to_struct)->_element = _defval; \ + } \ + } + +#define S2J_STRUCT_ARRAY_GET_int_ELEMENT(to_struct, from_json, _element, index) \ + (to_struct)->_element[index] = from_json->valueint; + +#define S2J_STRUCT_ARRAY_GET_string_ELEMENT(to_struct, from_json, _element, index) \ + strncpy((to_struct)->_element[index], from_json->valuestring,sizeof((to_struct)->_element[0])-1); + +#define S2J_STRUCT_ARRAY_GET_double_ELEMENT(to_struct, from_json, _element, index) \ + (to_struct)->_element[index] = from_json->valuedouble; + +#define S2J_STRUCT_ARRAY_GET_ELEMENT(to_struct, from_json, type, _element, index) \ + S2J_STRUCT_ARRAY_GET_##type##_ELEMENT(to_struct, from_json, _element, index) + +#define S2J_STRUCT_ARRAY_GET_int_ELEMENT_EX(to_struct, from_json, _element, index, _defval) \ + if (from_json) (to_struct)->_element[index] = from_json->valueint; \ + else (to_struct)->_element[index] = _defval; + +#define S2J_STRUCT_ARRAY_GET_string_ELEMENT_EX(to_struct, from_json, _element, index, _defval) \ + if (from_json) strncpy((to_struct)->_element[index], from_json->valuestring,sizeof((to_struct)->_element[0])-1); \ + else strncpy((to_struct)->_element[index], _defval,sizeof((to_struct)->_element[0])-1); + +#define S2J_STRUCT_ARRAY_GET_double_ELEMENT_EX(to_struct, from_json, _element, index, _defval) \ + if (from_json) (to_struct)->_element[index] = from_json->valuedouble; \ + else (to_struct)->_element[index] = _defval; + +#define S2J_STRUCT_ARRAY_GET_ELEMENT_EX(to_struct, from_json, type, _element, index, _defval) \ + S2J_STRUCT_ARRAY_GET_##type##_ELEMENT_EX(to_struct, from_json, _element, index, _defval) + +#define S2J_JSON_SET_int_ELEMENT(to_json, from_struct, _element) \ + cJSON_AddIntToObject(to_json, #_element,(long long)(from_struct)->_element); + +#define S2J_JSON_SET_double_ELEMENT(to_json, from_struct, _element) \ + cJSON_AddNumberToObject(to_json, #_element, (double)(from_struct)->_element); + +#define S2J_JSON_SET_string_ELEMENT(to_json, from_struct, _element) \ + (from_struct)->_element[sizeof((from_struct)->_element)-1] = '\0'; \ + cJSON_AddStringToObject(to_json, #_element, (from_struct)->_element); + +#define S2J_JSON_ARRAY_SET_int_ELEMENT(to_json, from_struct, _element, index) \ + cJSON_AddItemToArray(to_json, cJSON_CreateInt((from_struct)->_element[index])); + +#define S2J_JSON_ARRAY_SET_double_ELEMENT(to_json, from_struct, _element, index) \ + cJSON_AddItemToArray(to_json, cJSON_CreateNumber((from_struct)->_element[index])); + +#define S2J_JSON_ARRAY_SET_string_ELEMENT(to_json, from_struct, _element, index) \ + (from_struct)->_element[index][sizeof((from_struct)->_element[0])-1] = '\0'; \ + cJSON_AddItemToArray(to_json, cJSON_CreateString((from_struct)->_element[index])); + +#define S2J_JSON_ARRAY_SET_ELEMENT(to_json, from_struct, type, _element, index) \ + S2J_JSON_ARRAY_SET_##type##_ELEMENT(to_json, from_struct, _element, index) + + +#define S2J_CREATE_JSON_OBJECT(json_obj) \ + cJSON *json_obj = cJSON_CreateObject(); + +#define S2J_DELETE_JSON_OBJECT(json_obj) \ + cJSON_Delete(json_obj); + +#define S2J_JSON_SET_BASIC_ELEMENT(to_json, from_struct, type, _element) \ + S2J_JSON_SET_##type##_ELEMENT(to_json, from_struct, _element) + +#define S2J_JSON_SET_ARRAY_ELEMENT(to_json, from_struct, type, _element, size) \ + { \ + cJSON *array_##_element; \ + size_t index_##_element = 0; \ + array_##_element = cJSON_CreateArray(); \ + if (array_##_element) { \ + for (;index_##_element < size;index_##_element++) { \ + S2J_JSON_ARRAY_SET_ELEMENT(array_##_element, from_struct, type, _element, index_##_element); \ + } \ + cJSON_AddItemToObject(to_json, #_element, array_##_element); \ + } \ + } + +#define S2J_JSON_SET_STRUCT_ELEMENT(child_json, to_json, child_struct, from_struct, type, _element) \ + type *child_struct = &((from_struct)->_element); \ + cJSON *child_json = cJSON_CreateObject(); \ + if (child_json) cJSON_AddItemToObject(to_json, #_element, child_json); + +#define S2J_CREATE_STRUCT_OBJECT(struct_obj, type) \ + cJSON *json_temp; \ + type *struct_obj = (type *)s2jHook.malloc_fn(sizeof(type)); \ + if (struct_obj) memset(struct_obj, 0, sizeof(type)); + +#define S2J_DELETE_STRUCT_OBJECT(struct_obj) \ + s2jHook.free_fn(struct_obj); + +#define S2J_STRUCT_GET_BASIC_ELEMENT(to_struct, from_json, type, _element) \ + S2J_STRUCT_GET_##type##_ELEMENT(to_struct, from_json, _element) + +#define S2J_STRUCT_GET_BASIC_ELEMENT_EX(to_struct, from_json, type, _element, _defval) \ + S2J_STRUCT_GET_##type##_ELEMENT_EX(to_struct, from_json, _element, _defval) + +#define S2J_STRUCT_GET_ARRAY_ELEMENT(to_struct, from_json, type, _element) \ + { \ + cJSON *array_##_element, *array_item_##_element; \ + size_t index_##_element = 0, size_##_element = 0, realsize_##_element = 0; \ + size_##_element = S2J_ARRAY_SIZE((to_struct)->_element); \ + array_##_element = cJSON_GetObjectItem(from_json, #_element); \ + if (array_##_element) { \ + realsize_##_element = cJSON_GetArraySize(array_##_element); \ + for (;index_##_element < realsize_##_element && index_##_element < size_##_element ;index_##_element++) { \ + array_item_##_element = cJSON_GetArrayItem(array_##_element, index_##_element); \ + if (array_item_##_element) { \ + S2J_STRUCT_ARRAY_GET_ELEMENT(to_struct, array_item_##_element, type, _element, index_##_element); \ + } \ + } \ + } \ + } + +#define S2J_STRUCT_GET_ARRAY_ELEMENT_EX(to_struct, from_json, type, _element, size, _defval) \ + { \ + size_t index_##_element = 0, size_##_element = 0, realsize_##_element = 0; \ + if (from_json) { \ + cJSON *array_##_element = NULL, *array_item_##_element = NULL; \ + array_##_element = cJSON_GetObjectItem(from_json, #_element); \ + if (array_##_element) { \ + realsize_##_element = cJSON_GetArraySize(array_##_element); \ + for (;index_##_element < realsize_##_element && index_##_element < size; index_##_element++) { \ + array_item_##_element = cJSON_GetArrayItem(array_##_element, index_##_element); \ + if (array_item_##_element) { \ + S2J_STRUCT_ARRAY_GET_ELEMENT_EX(to_struct, array_item_##_element, type, _element, index_##_element, _defval); \ + }\ + } \ + } else { \ + for (;index_##_element < realsize_##_element && index_##_element < size; index_##_element++) { \ + S2J_STRUCT_ARRAY_GET_ELEMENT_EX(to_struct, array_##_element, type, _element, index_##_element, _defval); \ + } \ + } \ + } else { \ + for (;index_##_element < realsize_##_element && index_##_element < size; index_##_element++) { \ + S2J_STRUCT_ARRAY_GET_ELEMENT_EX(to_struct, from_json, type, _element, index_##_element, _defval); \ + } \ + } \ + } + +#define S2J_STRUCT_GET_STRUCT_ELEMENT(child_struct, to_struct, child_json, from_json, type, _element) \ + type *child_struct = &((to_struct)->_element); \ + cJSON *child_json = cJSON_GetObjectItem(from_json, #_element); + +#define S2J_JSON_SET_STRUCT_ELEMENT_BY_FUNC(to_json, from_struct, type, element) \ + cJSON_AddItemToObject(to_json, #element, struct_to_json_##type(&((from_struct)->element))) + +#define S2J_JSON_SET_STRUCT_ARRAY_ELEMENT_BY_FUNC(to_json, from_struct, type, element, array_size) \ + { \ + cJSON * j_array_##element = cJSON_CreateArray(); \ + cJSON_AddItemToObject(to_json, #element, j_array_##element); \ + int j_index_##element = 0; \ + for (; j_index_##element < array_size; j_index_##element++) { \ + cJSON_AddItemToArray(j_array_##element, struct_to_json_##type(&((from_struct)->element[j_index_##element]))); \ + } \ + } + +#define S2J_STRUCT_GET_STRUCT_ELEMENT_BY_FUNC(to_struct, from_json, type, element) \ + { \ + S2J_STRUCT_GET_STRUCT_ELEMENT(struct_##element, to_struct, json_##element, from_json, type, element) \ + if (json_##element){ \ + type * p_##element = (type *)json_to_struct_##type(json_##element); \ + *(struct_##element) = *(p_##element); \ + s2j_delete_struct_obj(p_##element); \ + } \ + else { \ + fprintf (stdout, "\nWARNING: Invalid json element(%s). [FUNCTION:%s, FILE:%s, LINE:%d]\n", #element,__FUNCTION__, __FILE__, __LINE__); \ + } \ + } + +#define S2J_STRUCT_GET_STRUCT_ARRAY_ELEMENT_BY_FUNC(to_struct, from_json, type, element) \ + { \ + cJSON *array_##element, *array_item_##element; \ + size_t index_##element = 0, size_##element = 0, realsize_##element = 0; \ + size_##element = S2J_ARRAY_SIZE((to_struct)->element); \ + array_##element = cJSON_GetObjectItem(from_json, #element); \ + if (array_##element) { \ + realsize_##element = cJSON_GetArraySize(array_##element); \ + for (;index_##element < realsize_##element && index_##element < size_##element; index_##element++) { \ + array_item_##element = cJSON_GetArrayItem(array_##element, index_##element); \ + if (array_item_##element) { \ + type *struct_##element = &((to_struct)->element[index_##element]); \ + type * p##element = (type *)json_to_struct_##type(array_item_##element); \ + *(struct_##element) = *(p##element); \ + s2j_delete_struct_obj(p##element); \ + } \ + } \ + } \ + else { \ + fprintf (stdout, "\nWARNING: Invalid json element(%s). [FUNCTION:%s, FILE:%s, LINE:%d]\n", #element,__FUNCTION__, __FILE__, __LINE__); \ + } \ + } + + + +#ifdef __cplusplus +} +#endif + +#endif /* __S2JDEF_H__ */ diff --git a/src/subprojects/struct2json/struct2json/src/s2j.c b/src/subprojects/struct2json/struct2json/src/s2j.c new file mode 100644 index 00000000..d4d914e4 --- /dev/null +++ b/src/subprojects/struct2json/struct2json/src/s2j.c @@ -0,0 +1,52 @@ +/* + * This file is part of the struct2json Library. + * + * Copyright (c) 2015, Armink, + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Function: Initialize interface for this library. + * Created on: 2015-10-14 + */ + +#include "../inc/s2j.h" +#include + +S2jHook s2jHook = { + .malloc_fn = malloc, + .free_fn = free, +}; + +/** + * struct2json library initialize + * @note It will initialize cJSON library hooks. + */ +void s2j_init(S2jHook *hook) { + /* initialize cJSON library */ + cJSON_InitHooks((cJSON_Hooks *)hook); + /* initialize hooks */ + if (hook) { + s2jHook.malloc_fn = (hook->malloc_fn) ? hook->malloc_fn : malloc; + s2jHook.free_fn = (hook->free_fn) ? hook->free_fn : free; + } else { + s2jHook.malloc_fn = malloc; + s2jHook.free_fn = free; + } +} diff --git a/src/subprojects/tinylog.wrap b/src/subprojects/tinylog.wrap new file mode 100644 index 00000000..6b7c2e95 --- /dev/null +++ b/src/subprojects/tinylog.wrap @@ -0,0 +1,9 @@ +[wrap-git] +directory = tinylog +url = https://github.com/shen390s/tinylog +revision = master +depth = 1 +patch_directory = tinylog + +[provide] +dependency_names = tinylog, tinylog-raw diff --git a/src/subprojects/tinylog/.clang-format b/src/subprojects/tinylog/.clang-format new file mode 100644 index 00000000..a4495a54 --- /dev/null +++ b/src/subprojects/tinylog/.clang-format @@ -0,0 +1,2 @@ +BasedOnStyle: WebKit +PointerAlignment: Right \ No newline at end of file diff --git a/src/subprojects/tinylog/.gitignore b/src/subprojects/tinylog/.gitignore new file mode 100644 index 00000000..99f6ab32 --- /dev/null +++ b/src/subprojects/tinylog/.gitignore @@ -0,0 +1,5 @@ +.vscode +.o +build +*.so +*.o \ No newline at end of file diff --git a/src/subprojects/tinylog/CMakeLists.txt b/src/subprojects/tinylog/CMakeLists.txt new file mode 100644 index 00000000..23f68ab1 --- /dev/null +++ b/src/subprojects/tinylog/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.5) +project(tlog) + +include(GNUInstallDirs) + +add_library(tlog SHARED) +target_sources(tlog PRIVATE tlog.c) + +install(TARGETS tlog + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +install(FILES tlog.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/src/subprojects/tinylog/LICENSE b/src/subprojects/tinylog/LICENSE new file mode 100644 index 00000000..f3b08b07 --- /dev/null +++ b/src/subprojects/tinylog/LICENSE @@ -0,0 +1,22 @@ +MIT License + +tinylog +Copyright (c) 2018 Nick Peng + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/subprojects/tinylog/README.md b/src/subprojects/tinylog/README.md new file mode 100644 index 00000000..ac9c6e91 --- /dev/null +++ b/src/subprojects/tinylog/README.md @@ -0,0 +1,266 @@ +# TinyLog + +[中文REAMDME请看这里](README_zh-CN.md) + +Tinylog is a lightweight C-language high performance log component for UNIX environment, It is high performance, asynchronized, thread-safe and process-safe log library for C/C++. + +It support log archiving, asynchronized, multithreading writing, multiprocessing writing, non-blocking mode. + +output example: + +```C +[2018-04-03 21:52:13,485][INFO][ example.c:7 ] This is a log message. +``` + +archive example: + +```C +root@raspberrypi:/home/pi/code/tiny-log/test # ls log/ -l +total 11564 +-rw-r----- 1 root root 8754060 Apr 20 21:48 test.log +-rw-r----- 1 root root 1543852 Apr 20 21:48 test.log-20180420-214824.gz +-rw-r----- 1 root root 1539119 Apr 20 21:48 test.log-20180420-214830.gz +``` + +## Features + +1. Log to compressed archive file. +2. Log level output. +3. log format customization. +4. asynchronized log output. +5. Multiple log file support. +6. printf, vprintf similar interface, easy to expand. +7. non-blocking log mode. +8. Multithreading concurrent write. +9. Multiprcessing concurrent write. +10. c++ std::cout sytle log function. +11. Output log with color. + +## Usage + +1. Include the log header file `tlog.h` in the C code. +2. Call `tlog_init` to initialize the log module. +3. Call `tlog` or `tlog_[debug|info|notice|warn|error|fatal]` function output log. +4. Call `tlog_[debug|info|notice|warn|error|fatal]<<` output c++ log. +5. Call `tlog_exit` to exit the shutdown log component. + +## Example + +1. Output log + + ```C + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_init("example.log", 1024 * 1024, 8, 0, 0); + tlog(TLOG_INFO, "This is a log message.\n"); + tlog_exit(); + return 0; + } + ``` + +1. Output log with color. + + ```c + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_init("example.log", 1024 * 1024, 8, 0, TLOG_SCREEN_COLOR); + tlog_debug("This is a debug message."); + tlog_info("This is a log message."); + tlog_notice("This is a notice message."); + tlog_warn("This is a warn message."); + tlog_error("This is a error message."); + tlog_fatal("This is a fatal message."); + tlog_exit(); + return 0; + } + ``` + +1. Output log for c++ cout style + + ```cpp + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_init("example.log", 1024 * 1024, 8, 0, 0); + tlog_info << "This is a c++ cout style log message.\n"; + tlog_exit(); + return 0; + } + ``` + +1. Independent log stream + + c printf style + + ```C + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_log *log = NULL; + tlog_init("example.log", 1024 * 1024, 8, 0, 0); + log = tlog_open("another.log", 1024 * 1024, 8, 0, TLOG_SEGMENT); + tlog_printf(log, "This is a separate log stream\n"); + tlog_close(log); + tlog_exit(); + return 0; + } + ``` + + cpp std::out like style + + ```Cpp + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_log *log = NULL; + tlog_init("example.log", 1024 * 1024, 8, 0, 0); + log = tlog_open("another.log", 1024 * 1024, 8, 0, TLOG_SEGMENT); + tlog_out(log) << "This is a separate log stream\n"; + tlog_close(log); + tlog_exit(); + return 0; + } + ``` + +## API description + +1. int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag); + `Function`:Initialize log module + `logfile`: log file + `maxlogsize`: The maximum size of a single log file. + `maxlogcount`: Number of archived logs. + `buffsize`: Buffer size + `flag`: log output flag: List of flags are as follows + * `TLOG_MULTI_WRITE`: Enable multi-process write single log mode. (Note: When using this mode, the maxlogsize parameter of all processes must be the same) + * `TLOG_NOCOMPRESS`: The archive log is not compressed. + * `TLOG_SEGMENT`: Log segmentation, used to register the callback function, returns a complete log for subsequent processing. + * `TLOG_NONBLOCK`: Do not block when buffer is insufficient. + * `TLOG_SCREEN`: Output logs to the screen. + * `TLOG_SUPPORT_FORK`: Support fork process. + * `TLOG_SCREEN_COLOR`: Output logs to the screen with color. + +1. tlog(level, format, ...) + + `Function`:Print log + `level`: Current log Levels + `format`: Log formats + +1. tlog_debug, tlog_info, tlog_notice, tlog_warn, tlog_error, tlog_fatal + + `Function`:Print log, for c++ use `<<` output log. + `format`: Log formats. + +1. tlog_exit() + + `Function`:Log component exits + +1. tlog_reg_format_func(tlog_format_func func) + + `Function`:Registers a custom Format function, and the callback function is defined as:tlog_format_func + +1. tlog_reg_log_output_func(tlog_log_output_func output, void *private) + `Function`: Register the custom log output function. The callback function is defined as: tlog_log_output_func. The TLOG_SEGMENT flag can be set during log initialization to return the callback to an independent full log. + +1. tlog_setlevel(tlog_level level) + + `Function`:Set log level,valid level are :TLOG_DEBUG, TLOG_INFO, TLOG_NOTICE, TLOG_WARN, TLOG_ERROR, TLOG_FATAL, TLOG_OFF + +1. tlog_getlevel() + + `Function`:Get log level. + +1. tlog_set_logfile(const char *logfile) + + `Function`:Update log file. + `logfile`: log file + +1. tlog_setlogscreen(int enable) + + `Function`:set whether the log is output to screen. + +1. tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag) + + `Function`: Initializes a new log stream. When finished, it is closed with tlog_cloese. + `logfile`: log file. + `maxlogsize`: The maximum size of a single log file. + `maxlogcount`: The number of archived logs. + `buffsize`: The size of the buffer. + `flag`: log output flag: List of flags are as follows + * `TLOG_MULTI_WRITE`: Enable multi-process write single log mode. (Note: When using this mode, the maxlogsize parameter of all processes must be the same) + * `TLOG_NOCOMPRESS`: The archive log is not compressed. + * `TLOG_SEGMENT`: Log segmentation, used to register the callback function, returns a complete log for subsequent processing. + * `TLOG_NONBLOCK`: Do not block when buffer is insufficient. + * `TLOG_SCREEN`: Output logs to the screen. + `return value`: log stream handle. + +1. tlog_close(tlog_log *log) + + `Function`: Turn off the log stream + `log`: The log stream handle. + +1. tlog_printf(tlog_log *log, const char *format, ...) + + `Function`: Print the log to the specified log stream + `log`: The log stream handle. + `format`: The log format. + +1. tlog_out(tlog_log *log) + + `Function`: Print the log to the specified log stream, use `<<` output log like std::out + `log`: The log stream handle. + +1. tlog_vprintf(tlog_log *log, const char *format, va_list ap) + + `Function`: Print the log to the specified log stream + `log`: The log stream handle. + `format`: The log format. + `ap`: List of parameters. + +1. tlog_logscreen(tlog_log *log, int enable) + + `Function`: Set whether the log stream is output to the screen + `log`: The log stream handle. + `enable`: Whether to enable. + +1. tlog_localtime(struct tlog_time *tm) + + `Function`: Get local time. + `tm`: Local time output. + +1. tlog_reg_output_func(tlog_log *log, tlog_output_func output) + + `Function`: Register the log stream output callback function. After the specified, the built-in write local file interface will be invalid. The TLOG_SEGMENT flag can be set when the log stream is initialized to return the callback to an independent complete log. + +1. tlog_set_private(tlog_log *log, void *private) + + `Function`: Set private parameters for retrieval in the callback function. + `log`: The log stream handle. + `private`: private parameter. + +1. tlog_get_private(tlog_log *log) + + `Function`: Get the private parameter, which is obtained from the callback function. + `log`: The log stream handle. + `return value`: private parameter. + +1. tlog_rename_logfile(tlog_log *log, const char *logfile) + + `Function`: Rename log file. + `log`: The log stream handle. + `logfile`: log file. + +## License + +MIT License diff --git a/src/subprojects/tinylog/README_zh-CN.md b/src/subprojects/tinylog/README_zh-CN.md new file mode 100644 index 00000000..0ac910f6 --- /dev/null +++ b/src/subprojects/tinylog/README_zh-CN.md @@ -0,0 +1,268 @@ + +# Tinylog + +Tinylog是一个UNIX环境下轻量级的C/C++高性能异步日志组件,其提供了高性能,异步,线程安全,进程安全的日志功能。 + +支持日志归档,支持多线程并发写日志,多进程并发写日志,支持非阻塞日志。 + +日志输出例子 + +```c +[2018-04-03 21:52:13,485][ INFO][ example.c:7 ] This is a log message. +``` + +归档目录例子 + +```c +root@raspberrypi:/home/pi/code/tiny-log/test # ls log/ -l +total 11564 +-rw-r----- 1 root root 8754060 Apr 20 21:48 test.log +-rw-r----- 1 root root 1543852 Apr 20 21:48 test.log-20180420-214824.gz +-rw-r----- 1 root root 1539119 Apr 20 21:48 test.log-20180420-214830.gz +``` + +## 特性 + +1. 日志压缩归档。 +2. 日志级别输出。 +3. 日志格式定制。 +4. 异步日志输出。 +5. 多日志文件支持。 +6. printf,vprintf类似接口,易于扩展。 +7. 非阻塞日志。 +8. 多线程并发写。 +9. 多进程并发写。 +10. c++流风格日志输出。 +11. 按颜色输出日志。 + +## 使用 + +1. 将日志头文件`tlog.h`包含到C代码的中。 +2. 调用`tlog_init`初始化日志模块。 +3. 调用`tlog`或`tlog_[debug|info|notice|warn|error|fatal]`日志输出函数输出日志。 +4. c++使用cout风格输出日志到`tlog_info`。 +5. 调用`tlog_exit`退出关闭日志组件。 + +## 例子 + +1. 输出日志 + + ```c + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_init("example.log", 1024 * 1024, 8, 0, 0); + tlog(TLOG_INFO, "This is a log message.\n"); + tlog_info("This is another log message.\n"); + tlog_exit(); + return 0; + } + ``` + +1. 按颜色输出日志 + + ```c + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_init("example.log", 1024 * 1024, 8, 0, TLOG_SCREEN_COLOR); + tlog_debug("This is a debug message."); + tlog_info("This is a log message."); + tlog_notice("This is a notice message."); + tlog_warn("This is a warn message."); + tlog_error("This is a error message."); + tlog_fatal("This is a fatal message."); + tlog_exit(); + return 0; + } + ``` + +1. c++流日志 + + ```cpp + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_init("example.log", 1024 * 1024, 8, 0, 0); + tlog_info << "This is a c++ cout style log message.\n"; + tlog_exit(); + return 0; + } + ``` + +1. 独立日志流 + + c printf风格 + + ```c + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_log *log = NULL; + tlog_init("example.log", 1024 * 1024, 8, 0, 0); + log = tlog_open("another.log", 1024 * 1024, 8, 0, TLOG_SEGMENT); + tlog_printf(log, "This is a separate log stream.\n"); + tlog_close(log); + tlog_exit(); + return 0; + } + ``` + + c++ std::out 风格 + + ```cpp + #include + #include "tlog.h" + + int main(int argc, char *argv[]) + { + tlog_log *log = NULL; + tlog_init("example.log", 1024 * 1024, 8, 0, 0); + log = tlog_open("another.log", 1024 * 1024, 8, 0, TLOG_SEGMENT); + tlog_out(log) << "This is a separate log stream.\n"; + tlog_close(log); + tlog_exit(); + return 0; + } + ``` + +## API说明 + +1. int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag); + + `功能`: 初始化日志模块 + `logfile`: 日志文件。 + `maxlogsize`: 单个日志文件最大大小。 + `maxlogcount`: 归档日志个数。 + `buffsize`: 缓冲区大小。 + `flag`:日志输出模式:可设置: + * `TLOG_MULTI_WRITE`: 启用多进程写单个日志模式. (注意: 当使用此模式时,所有进程的maxlogsize参数必须一样) + * `TLOG_NOCOMPRESS`: 归档日志不进行压缩。 + * `TLOG_SEGMENT`: 日志分段,用于注册回调函数后,返回一条完整的日志用于后续处理。 + * `TLOG_NONBLOCK`: 缓冲区不足时,不阻塞。 + * `TLOG_SCREEN`: 输出日志到屏幕。 + * `TLOG_SUPPORT_FORK`: 支持fork运行的进程。 + * `TLOG_SCREEN_COLOR`: 按颜色输出日志到屏幕。 + +1. tlog(level, format, ...) + + `功能`: 打印日志 + `level`: 当前日志级别 + `format`: 日志格式。 + +1. tlog_debug, tlog_info, tlog_notice, tlog_warn, tlog_error, tlog_fatal + + `功能`: 打印日志, c++使用`<<`输出日志。 + `format`: 日志格式。 + +1. tlog_exit() + + `功能`: 日志组件退出。 + +1. tlog_reg_format_func(tlog_format_func func) + + `功能`: 注册自定义格式函数,回调函数定义为: tlog_format_func + +1. int tlog_reg_log_output_func(tlog_log_output_func output, void *private) + `功能`: 注册自定义日志输出函数,回调函数定义为:tlog_log_output_func, 可在日志初始化时设置TLOG_SEGMENT标志使回调返回一条独立完整日志。 + +1. tlog_setlevel(tlog_level level) + + `功能`: 设置日志级别,有效参数为TLOG_DEBUG, TLOG_INFO, TLOG_NOTICE, TLOG_WARN, TLOG_ERROR, TLOG_FATAL, TLOG_OFF + +1. tlog_getlevel(tlog_level level) + + `功能`: 获取设置的日志级别。 + +1. tlog_set_logfile(const char *logfile) + + `功能`: 设置日志文件。 + `logfile`: 日志文件。 + +1. tlog_setlogscreen(int enable) + + `功能`: 设置日志是否输出到屏幕。 + `enable`: 是否启用。 + +1. tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag); + + `功能`:  初始化一个新的日志流,完成后,使用tlog_cloese关闭。 + `logfile`: 日志文件。 + `maxlogsize`: 单个日志文件最大大小。 + `maxlogcount`: 归档日志个数。 + `buffsize`: 缓冲区大小。 + `flag`:日志输出模式:可设置: + * `TLOG_MULTI_WRITE`: 启用多进程写单个日志模式. (注意: 当使用此模式时,所有进程的maxlogsize参数必须一样) + * `TLOG_NOCOMPRESS`: 归档日志不进行压缩。 + * `TLOG_SEGMENT`: 日志分段,用于注册回调函数后,返回一条完整的日志用于后续处理。 + * `TLOG_NOBLOCK`: 缓冲区不足时,不阻塞。 + * `TLOG_SCREEN`: 输出日志到屏幕。 + `返回值`: 日志流句柄。 + +1. tlog_close(tlog_log *log) + + `功能`: 关闭日志流。 + `log`: 日志流句柄。 + +1. tlog_printf(tlog_log *log, const char *format, ...) + + `功能`: 打印日志到指定日志流 + `log`: 日志流句柄。 + `format`: 日志格式。 + +1. tlog_out(tlog_log *log) + + `功能`: c++风格打印日志到指定日志流,使用`<<`输出日志 + `log`: 日志流句柄。 + +1. tlog_vprintf(tlog_log *log, const char *format, va_list ap) + + `功能`: 打印日志到指定日志流 + `log`: 日志流句柄。 + `format`: 日志格式。 + `ap`: 参数列表。 + +1. tlog_logscreen(tlog_log *log, int enable) + + `功能`: 设置日志流是否输出到屏幕 + `log`: 日志流句柄。 + `enable`: 是否启用。 + +1. tlog_localtime(struct tlog_time *tm) + + `功能`: 获取本地时间。 + `tm`: 本地时间输出。 + +1. int tlog_reg_output_func(tlog_log *log, tlog_output_func output) + + `功能`: 注册日志流输出回调函数,指定后,内置的写本地文件接口将失效; 可在日志流初始化时设置TLOG_SEGMENT标志使回调返回一条独立完整日志。 + +1. void tlog_set_private(tlog_log *log, void *private) + + `功能`: 设置私有参数,供回调函数中获取。 + `log`: 日志流句柄。 + `private`: 私有参数。 + +1. void tlog_get_private(tlog_log *log) + + `功能`: 获取私有参数,供回调函数中获取。 + `log`: 日志流句柄。 + `返回值`: 私有参数。 + +1. tlog_rename_logfile(tlog_log *log, const char *logfile) + + `功能`: 重命名日志文件。 + `log`: 日志流句柄。 + `logfile`: 日志文件。 + +## License + +MIT License diff --git a/src/subprojects/tinylog/example/CMakeLists.txt b/src/subprojects/tinylog/example/CMakeLists.txt new file mode 100644 index 00000000..3d1d3ef8 --- /dev/null +++ b/src/subprojects/tinylog/example/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8) +project(example) + +include_directories(../) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASE_FILE_NAME='\"$(notdir $<)\"'") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DBASE_FILE_NAME='\"$(notdir $<)\"'") + +add_executable(example example.cpp ../tlog.c) +target_link_libraries(example pthread) diff --git a/src/subprojects/tinylog/example/Makefile b/src/subprojects/tinylog/example/Makefile new file mode 100644 index 00000000..1a5dafa4 --- /dev/null +++ b/src/subprojects/tinylog/example/Makefile @@ -0,0 +1,18 @@ +OBJS = example.o tlog.o +BIN = example +CFLAGS = -Wall -g -O0 +CXXFLAGS = -Wall -g -O0 +LIBS = -lpthread +ROOT_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +CFLAGS += -I$(ROOT_PATH)../ +CXXFLAGS += -I$(ROOT_PATH)../ +VPATH = $(ROOT_PATH) $(ROOT_PATH)../ +.PHONY : all + +all: $(BIN) + +$(BIN):$(OBJS) + $(CXX) $^ -o $@ $(LIBS) + +clean: + $(RM) $(BIN) $(OBJS) *.o *.log \ No newline at end of file diff --git a/src/subprojects/tinylog/example/example.cpp b/src/subprojects/tinylog/example/example.cpp new file mode 100644 index 00000000..44c9b4db --- /dev/null +++ b/src/subprojects/tinylog/example/example.cpp @@ -0,0 +1,33 @@ +#include "tlog.h" +#include + +int main(int argc, char *argv[]) +{ + tlog_log *log = NULL; + + /* init and output log message */ + tlog_init("example.log", 1024 * 1024, 8, 0, TLOG_SCREEN_COLOR); + tlog_setlevel(TLOG_DEBUG); + tlog(TLOG_DEBUG, "This is a debug message.\n"); + tlog(TLOG_INFO, "This is a log message.\n"); + tlog(TLOG_NOTICE, "This is a notice message.\n"); + tlog(TLOG_WARN, "This is a warn message.\n"); + tlog(TLOG_ERROR, "This is a error message.\n"); + tlog(TLOG_FATAL, "This is a fatal message.\n"); + + /* c++ cout style log */ + tlog_info << "This is a c++ style log.\n"; + + /* open another log file, and output message*/ + log = tlog_open("another.log", 1024 * 1024, 8, 0, TLOG_SEGMENT); + tlog_printf(log, "This is a separate log stream\n"); + /* c++ style log */ + tlog_out(log) << "This is a separate c++ log stream\n"; + + /* close log stream */ + tlog_close(log); + + /* flush pending message, and exit tlog */ + tlog_exit(); + return 0; +} diff --git a/src/subprojects/tinylog/makefile b/src/subprojects/tinylog/makefile new file mode 100644 index 00000000..c96ffc58 --- /dev/null +++ b/src/subprojects/tinylog/makefile @@ -0,0 +1,13 @@ +BIN=libtlog.so + +CFLAGS +=-O2 -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing -funwind-tables -Wmissing-prototypes -Wshadow -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough + +$(BIN): tlog.o + $(CC) -shared -o $@ $^ + +install: + cp $(BIN) /usr/lib64/ + cp tlog.h /usr/include/ + +clean: + $(RM) *.o $(BIN) \ No newline at end of file diff --git a/src/subprojects/tinylog/meson.build b/src/subprojects/tinylog/meson.build new file mode 100644 index 00000000..13172a5f --- /dev/null +++ b/src/subprojects/tinylog/meson.build @@ -0,0 +1,43 @@ +project('tinylog', + ['c'], + version: '1.0.0', + meson_version: '>=1.0', + default_options: ['c_std=gnu99', 'warning_level=2']) + +pkg = import('pkgconfig') + +incdir = include_directories('.') + +libtlog = shared_library('tlog', + ['tlog.c'], + include_directories: incdir, + install: not meson.is_subproject()) + +if not meson.is_subproject() + install_headers(['tlog.h']) + + pkg.generate(libtlog, + name: 'tinylog', + description: 'Tinylog is a lightweight C-language high performance log component for UNIX environment', + version: meson.project_version()) +endif + +# Register the fallback the parent resolves through this wrap's [provide] +# section: dependency('tinylog'). +tinylog_sdep = declare_dependency( + link_with: libtlog, + include_directories: incdir, + version: meson.project_version()) +meson.override_dependency('tinylog', tinylog_sdep) + +# Raw flags for non-meson consumers (frontend/apiserver reads them via +# dep.get_variable() to fill CGO_CFLAGS/CGO_LDFLAGS -- Go's cgo cannot +# consume meson dependency objects). Mirrors the nix tinylog.pc +# (Libs: -L${libdir} -ltlog, Cflags: -I${includedir}); the shared object +# lands in this subproject's build-dir root. +tinylog_raw = declare_dependency( + variables: { + 'cflags': '-I' + meson.current_source_dir(), + 'ldflags': '-L' + meson.current_build_dir() + ' -ltlog', + }) +meson.override_dependency('tinylog-raw', tinylog_raw) diff --git a/src/subprojects/tinylog/test/Makefile b/src/subprojects/tinylog/test/Makefile new file mode 100644 index 00000000..64866250 --- /dev/null +++ b/src/subprojects/tinylog/test/Makefile @@ -0,0 +1,20 @@ +OBJS = test.o tlog.o +BIN = test +CFLAGS = -Wall -g -O0 -I../ +LIBS = -lpthread +ROOT_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +CFLAGS += -I$(ROOT_PATH)../ +CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\" +VPATH = $(ROOT_PATH) $(ROOT_PATH)../ + +.PHONY : all + +all: $(BIN) + +all: $(BIN) + +$(BIN):$(OBJS) + $(CC) $^ -o $@ $(LIBS) + +clean: + $(RM) $(BIN) $(OBJS) \ No newline at end of file diff --git a/src/subprojects/tinylog/test/test.c b/src/subprojects/tinylog/test/test.c new file mode 100644 index 00000000..3ebb859f --- /dev/null +++ b/src/subprojects/tinylog/test/test.c @@ -0,0 +1,70 @@ +#include "tlog.h" +#include +#include + +pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + +struct tlog_log *logs = NULL; + +void *test(void *arg) +{ + int id = (intptr_t)arg; + int i = 0; + + for (i = 0; i < 100000; i++) { + tlog_error("%d i = %d\n", id, i); + } + return NULL; +} + +void *test1(void *arg) +{ + int id = (intptr_t)arg; + int i = 0; + + for (i = 0; i < 100000; i++) { + tlog_printf(logs, " %d i = %d\n", id, i); + } + return NULL; +} + +int main(int argc, char *argv[]) +{ + tlog_init("log/test.log", 1024 * 1024 * 32, 10, 0, 0); + logs = tlog_open("log/test1.log", 1024 * 1024 * 32, 10, 0, TLOG_NOCOMPRESS); + pthread_attr_t attr; + pthread_t threads[10]; + pthread_t threads1[10]; + int i; + int ret; + + pthread_attr_init(&attr); + for (i = 0; i < 10; i++) { + ret = pthread_create(&threads[i], &attr, test, (void *)(intptr_t)i); + if (ret != 0) { + return 1; + } + } + + for (i = 0; i < 10; i++) { + ret = pthread_create(&threads1[i], &attr, test1, (void *)(intptr_t)i); + if (ret != 0) { + return 1; + } + } + + for (i = 0; i < 10; i++) { + void *retval = NULL; + pthread_join(threads1[i], &retval); + } + + for (i = 0; i < 10; i++) { + void *retval = NULL; + pthread_join(threads[i], &retval); + } + + tlog_close(logs); + tlog_exit(); + return 0; +} \ No newline at end of file diff --git a/src/subprojects/tinylog/tlog.c b/src/subprojects/tinylog/tlog.c new file mode 100644 index 00000000..83c98fba --- /dev/null +++ b/src/subprojects/tinylog/tlog.c @@ -0,0 +1,2224 @@ +/* + * tinylog + * Copyright (C) 2018-2025 Nick Peng + * https://github.com/pymumu/tinylog + */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include "tlog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif + +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif + +#define TLOG_BUFF_SIZE (1024 * 128) +#define TLOG_TMP_LEN 128 +#define TLOG_LOG_SIZE (1024 * 1024 * 50) +#define TLOG_LOG_COUNT 32 +#define TLOG_LOG_NAME_LEN 256 +#define TLOG_BUFF_LEN (PATH_MAX + TLOG_LOG_NAME_LEN * 3) +#define TLOG_SUFFIX_GZ ".gz" +#define TLOG_SUFFIX_LOG "" +#define TLOG_MAX_LINE_SIZE_SET (1024 * 8) +#define TLOG_MIN_LINE_SIZE_SET (128) + +#define TLOG_SEGMENT_MAGIC 0xFF446154 + +struct linux_dirent64 { + unsigned long long d_ino; + long long d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +struct tlog_log { + char *buff; + int buffsize; + int start; + int end; + int ext_end; + + int fd; + int fd_lock; + + off_t filesize; + char logdir[PATH_MAX]; + char logname[TLOG_LOG_NAME_LEN]; + char suffix[TLOG_LOG_NAME_LEN]; + char pending_logfile[PATH_MAX]; + char logfile[PATH_MAX * 2]; + int rename_pending; + int fail; + int logsize; + int logcount; + int block; + int dropped; + int nocompress; + int zip_pid; + int multi_log; + int logscreen; + int logscreen_color; + int segment_log; + int max_line_size; + int print_errmsg; + + tlog_output_func output_func; + void *private_data; + int set_custom_output_func; + + time_t last_try; + time_t last_waitpid; + mode_t file_perm; + mode_t archive_perm; + int mode_changed; + + int waiters; + int is_exit; + struct tlog_log *next; + pthread_mutex_t lock; + pthread_cond_t client_cond; +}; + +struct tlog { + struct tlog_log *root; + struct tlog_log *log; + struct tlog_log *notify_log; + int run; + pthread_t tid; + pthread_mutex_t lock; + pthread_cond_t cond; + tlog_log_output_func output_func; + struct tlog_log *wait_on_log; + int is_wait; + int output_no_prefix; + char gzip_cmd[PATH_MAX]; + + tlog_format_func root_format; + + tlog_early_print_func tlog_early_print; + tlog_log_output_func early_print_output; + int early_print_disable; + int early_print_with_screen; + int early_print_no_prefix; + int early_print_color; + void *early_print_userptr; +}; + +struct tlog_segment_log_head { + struct tlog_loginfo info; + unsigned short len; + char data[0]; +} __attribute__((packed)); + +struct tlog_segment_head { + unsigned int magic; + unsigned short len; + char data[0]; +} __attribute__((packed)); + +struct oldest_log { + char name[TLOG_LOG_NAME_LEN]; + time_t mtime; + struct tlog_log *log; +}; + +struct count_log { + int lognum; + struct tlog_log *log; +}; + +struct tlog_info_inter { + struct tlog_loginfo info; + void *userptr; +}; + +typedef int (*list_callback)(const char *name, struct dirent *entry, void *user); +typedef int (*vprint_callback)(char *buff, int maxlen, void *userptr, const char *format, va_list ap); + +static struct tlog tlog; +static tlog_level tlog_set_level = TLOG_INFO; +unsigned int tlog_localtime_lock; + +static const char *tlog_level_str[] = { + "DEBUG3", + "DEBUG2", + "DEBUG", + "INFO", + "NOTICE", + "WARN", + "ERROR", + "FATAL", +}; + +static inline void _tlog_spin_lock(unsigned int *lock) +{ + while (1) { + int i; + for (i = 0; i < 10000; i++) { + if (__sync_bool_compare_and_swap(lock, 0, 1)) { + return; + } + } + sched_yield(); + } +} + +static inline void _tlog_spin_unlock(unsigned int *lock) +{ + __sync_bool_compare_and_swap(lock, 1, 0); +} + +static int _tlog_mkdir(const char *path) +{ + char path_c[PATH_MAX + 1]; + char *path_end; + char str; + int len; + if (access(path, F_OK) == 0) { + return 0; + } + + while (*path == ' ') { + path++; + } + + strncpy(path_c, path, sizeof(path_c) - 1); + path_c[sizeof(path_c) - 1] = '\0'; + len = strnlen(path_c, sizeof(path_c) - 1); + path_c[len] = '/'; + path_c[len + 1] = '\0'; + path_end = path_c; + + /* create directory recursively */ + while (*path_end != 0) { + if (*path_end != '/') { + path_end++; + continue; + } + + if (path_end == path_c) { + path_end++; + continue; + } + + str = *path_end; + *path_end = '\0'; + if (access(path_c, F_OK) == 0) { + *path_end = str; + path_end++; + continue; + } + + if (mkdir(path_c, 0750) != 0) { + return -1; + } + + *path_end = str; + path_end++; + } + + return 0; +} + +static struct tm *_tlog_localtime(time_t *timep, struct tm *tm) +{ + static time_t last_time; + static struct tm last_tm; + + /* localtime_r has a global timezone lock, it's about 8 times slower than gmtime + * this code is used to speed up localtime_r call. + */ + _tlog_spin_lock(&tlog_localtime_lock); + if (*timep == last_time) { + *tm = last_tm; + } else { + _tlog_spin_unlock(&tlog_localtime_lock); + tm = localtime_r(timep, tm); + _tlog_spin_lock(&tlog_localtime_lock); + if (tm) { + last_time = *timep; + last_tm = *tm; + } + } + _tlog_spin_unlock(&tlog_localtime_lock); + + return tm; +} + +static int _tlog_getmtime(struct tlog_time *log_mtime, const char *file) +{ + struct tm tm; + struct stat sb; + + if (stat(file, &sb) != 0) { + return -1; + } + + if (_tlog_localtime(&sb.st_mtime, &tm) == NULL) { + return -1; + } + + log_mtime->year = tm.tm_year + 1900; + log_mtime->mon = tm.tm_mon + 1; + log_mtime->mday = tm.tm_mday; + log_mtime->hour = tm.tm_hour; + log_mtime->min = tm.tm_min; + log_mtime->sec = tm.tm_sec; + log_mtime->usec = 0; + + return 0; +} + +static int _tlog_gettime(struct tlog_time *cur_time) +{ + struct tm tm; + struct timeval tmval; + + if (gettimeofday(&tmval, NULL) != 0) { + return -1; + } + + if (_tlog_localtime(&tmval.tv_sec, &tm) == NULL) { + return -1; + } + + cur_time->year = tm.tm_year + 1900; + cur_time->mon = tm.tm_mon + 1; + cur_time->mday = tm.tm_mday; + cur_time->hour = tm.tm_hour; + cur_time->min = tm.tm_min; + cur_time->sec = tm.tm_sec; + cur_time->usec = tmval.tv_usec; + + return 0; +} + +void tlog_set_maxline_size(struct tlog_log *log, int size) +{ + if (log == NULL) { + return; + } + + if (size < TLOG_MIN_LINE_SIZE_SET) { + size = TLOG_MIN_LINE_SIZE_SET; + } else if (size > TLOG_MAX_LINE_SIZE_SET) { + size = TLOG_MAX_LINE_SIZE_SET; + } + + log->max_line_size = size; +} + +void tlog_logcount(struct tlog_log *log, int count) +{ + if (log == NULL) { + return; + } + + if (count < 0) { + count = 0; + } + + log->logcount = count; +} + +void tlog_set_permission(struct tlog_log *log, mode_t file, mode_t archive) +{ + log->file_perm = file; + log->archive_perm = archive; + log->mode_changed = 1; +} + +int tlog_localtime(struct tlog_time *tm) +{ + return _tlog_gettime(tm); +} + +tlog_log *tlog_get_root(void) +{ + return tlog.root; +} + +void tlog_set_private(tlog_log *log, void *private_data) +{ + if (log == NULL) { + return; + } + + log->private_data = private_data; +} + +void *tlog_get_private(tlog_log *log) +{ + if (log == NULL) { + return NULL; + } + + return log->private_data; +} + +static int _tlog_root_default_format(char *buff, int maxlen, struct tlog_loginfo *info, void *userptr, const char *format, va_list ap) +{ + int len = 0; + int total_len = 0; + struct tlog_time *tm = &info->time; + void *unused __attribute__((unused)); + + unused = userptr; + + if (tlog.output_no_prefix == 0) { + if (tlog.root->multi_log) { + /* format prefix */ + len = snprintf(buff, maxlen, "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d,%.3d][%5d][%4s][%17s:%-4d] ", + tm->year, tm->mon, tm->mday, tm->hour, tm->min, tm->sec, tm->usec / 1000, getpid(), + tlog_get_level_string(info->level), info->file, info->line); + } else { + /* format prefix */ + len = snprintf(buff, maxlen, "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d,%.3d][%5s][%17s:%-4d] ", + tm->year, tm->mon, tm->mday, tm->hour, tm->min, tm->sec, tm->usec / 1000, + tlog_get_level_string(info->level), info->file, info->line); + } + } + + if (len < 0 || len >= maxlen) { + return -1; + } + buff += len; + total_len += len; + maxlen -= len; + + /* format log message */ + len = vsnprintf(buff, maxlen, format, ap); + if (len < 0 || len == maxlen) { + return -1; + } + buff += len; + total_len += len; + + /* return total length */ + return total_len; +} + +static int _tlog_root_log_buffer(char *buff, int maxlen, void *userptr, const char *format, va_list ap) +{ + int len = 0; + int log_len = 0; + struct tlog_info_inter *info_inter = (struct tlog_info_inter *)userptr; + struct tlog_segment_log_head *log_head = NULL; + int max_format_len = 0; + + if (tlog.root_format == NULL) { + return -1; + } + + if (tlog.root->segment_log) { + log_head = (struct tlog_segment_log_head *)buff; + len += sizeof(*log_head); + memcpy(&log_head->info, &info_inter->info, sizeof(log_head->info)); + } + + max_format_len = maxlen - len - 2; + buff[maxlen - 1] = 0; + log_len = tlog.root_format(buff + len, max_format_len, &info_inter->info, info_inter->userptr, format, ap); + if (log_len < 0) { + return -1; + } else if (log_len >= max_format_len) { + buff[len + max_format_len - 2] = '.'; + buff[len + max_format_len - 3] = '.'; + buff[len + max_format_len - 4] = '.'; + log_len = max_format_len - 1; + } + len += log_len; + + /* add new line character*/ + if (*(buff + len - 1) != '\n' && len + 1 < maxlen - 1) { + *(buff + len) = '\n'; + len++; + log_len++; + } + + if (tlog.root->segment_log && log_head != NULL) { + if (len + 1 < maxlen - 1) { + *(buff + len) = '\0'; + len++; + } + log_head->len = log_len; + } + + return len; +} + +static int _tlog_print_buffer(char *buff, int maxlen, void *userptr, const char *format, va_list ap) +{ + int len; + int total_len = 0; + void *unused __attribute__((unused)); + + unused = userptr; + + /* format log message */ + len = vsnprintf(buff, maxlen, format, ap); + if (len < 0 || len == maxlen) { + return -1; + } + buff += len; + total_len += len; + + /* return total length */ + return total_len; +} + +static int _tlog_need_drop(struct tlog_log *log) +{ + int maxlen = 0; + int ret = -1; + if (log->block) { + return -1; + } + + pthread_mutex_lock(&tlog.lock); + if (log->end == log->start) { + if (log->ext_end == 0) { + /* if buffer is empty */ + maxlen = log->buffsize - log->end; + } + } else if (log->end > log->start) { + maxlen = log->buffsize - log->end; + } else { + /* if reverse */ + maxlen = log->start - log->end; + } + + /* if free buffer length is less than min line length */ + if (maxlen < log->max_line_size) { + log->dropped++; + ret = 0; + } + pthread_mutex_unlock(&tlog.lock); + return ret; +} + +static int _tlog_write_screen(struct tlog_log *log, struct tlog_loginfo *info, const char *buff, int bufflen) +{ + if (bufflen <= 0) { + return 0; + } + + if (log->logscreen == 0) { + return 0; + } + + if (info == NULL) { + return write(STDOUT_FILENO, buff, bufflen);; + } + + return tlog_stdout_with_color(info->level, buff, bufflen); +} + +static int _tlog_write_output_func(struct tlog_log *log, char *buff, int bufflen) +{ + if (log->logscreen && log != tlog.root) { + _tlog_write_screen(log, NULL, buff, bufflen); + } + + if (log->output_func == NULL) { + return -1; + } + + return log->output_func(log, buff, bufflen); +} + +static void _tlog_output_warning(void) +{ + static int printed = 0; + int unused __attribute__((unused)); + + if (printed) { + return; + } + printed = 1; + tlog_log *root = tlog.root; + + const char warning_msg[] = "" + "TLOG ERROR: \n" + " Do not call the tlog output function from within a registered tlog log output callback function.\n" + " Recursively calling the log output function will cause tlog to fail to output logs and deadlock.\n"; + + if (root->logcount > 0 && root->logsize > 0 && root->logfile[0] != 0) { + int fd = open(root->logfile, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, root->file_perm); + if (fd >= 0) { + unused = write(fd, warning_msg, sizeof(warning_msg) - 1); + close(fd); + } + } + + /* if open log file failed, print to stderr */ + fprintf(stderr, "\033[31;1m%s\033[0m\n", warning_msg); + + return; +} + +static int _tlog_vprintf(struct tlog_log *log, vprint_callback print_callback, void *userptr, const char *format, va_list ap) +{ + int len; + int maxlen = 0; + struct tlog_segment_head *segment_head = NULL; + + if (log == NULL || format == NULL) { + return -1; + } + + char buff[log->max_line_size]; + + if (log->buff == NULL) { + return -1; + } + + if (unlikely(log->logcount <= 0 && log->logscreen == 0 && log->set_custom_output_func == 0)) { + return 0; + } + + if (_tlog_need_drop(log) == 0) { + return -1; + } + + len = print_callback(buff, sizeof(buff), userptr, format, ap); + if (len <= 0) { + return -1; + } else if (len >= log->max_line_size) { + len = log->max_line_size; + buff[len - 1] = '\0'; + buff[len - 2] = '\n'; + buff[len - 3] = '.'; + buff[len - 4] = '.'; + buff[len - 5] = '.'; + } + + /* + Output log from tlog_worker thread context? this may crash from upper-level function. + Try call printf output log. + */ + if (tlog.tid == pthread_self()) { + _tlog_output_warning(); + vprintf(format, ap); + printf("\n"); + return -1; + } + + pthread_mutex_lock(&tlog.lock); + do { + if (log->end == log->start) { + if (log->ext_end == 0) { + /* if buffer is empty */ + maxlen = log->buffsize - log->end; + } + } else if (log->end > log->start) { + maxlen = log->buffsize - log->end; + } else { + /* if reverse */ + maxlen = log->start - log->end; + } + + /* if free buffer length is less than min line length */ + if (maxlen < log->max_line_size) { + if (log->end != log->start) { + tlog.notify_log = log; + pthread_cond_signal(&tlog.cond); + } + + /* if drop message, increase statistics and return */ + if (log->block == 0) { + log->dropped++; + pthread_mutex_unlock(&tlog.lock); + return -1; + } + + pthread_mutex_unlock(&tlog.lock); + pthread_mutex_lock(&log->lock); + log->waiters++; + /* block wait for free buffer */ + int ret = pthread_cond_wait(&log->client_cond, &log->lock); + log->waiters--; + pthread_mutex_unlock(&log->lock); + if (ret < 0) { + return -1; + } + + pthread_mutex_lock(&tlog.lock); + } + } while (maxlen < log->max_line_size); + + if (log->segment_log) { + segment_head = (struct tlog_segment_head *)(log->buff + log->end); + memcpy(segment_head->data, buff, len); + log->end += len + sizeof(*segment_head) + 1; + segment_head->len = len + 1; + segment_head->data[len] = '\0'; + segment_head->magic = TLOG_SEGMENT_MAGIC; + } else { + /* write log to buffer */ + memcpy(log->buff + log->end, buff, len); + log->end += len; + } + + /* if remain buffer is not enough for a line, move end to start of buffer. */ + if (log->end > log->buffsize - log->max_line_size) { + log->ext_end = log->end; + log->end = 0; + } + if (tlog.is_wait) { + tlog.notify_log = log; + pthread_cond_signal(&tlog.cond); + } + pthread_mutex_unlock(&tlog.lock); + + return len; +} + +int tlog_vprintf(struct tlog_log *log, const char *format, va_list ap) +{ + return _tlog_vprintf(log, _tlog_print_buffer, NULL, format, ap); +} + +int tlog_printf(struct tlog_log *log, const char *format, ...) +{ + int len; + va_list ap; + + va_start(ap, format); + len = tlog_vprintf(log, format, ap); + va_end(ap); + + return len; +} + +int tlog_stdout_with_color(tlog_level level, const char *buff, int bufflen) +{ + int unused __attribute__((unused)); + const char *color = NULL; + + switch (level) { + case TLOG_DEBUG2: + case TLOG_DEBUG3: + color = ANSI_GREEN; + break; + case TLOG_DEBUG: + color = "\033[0;94m"; + break; + case TLOG_NOTICE: + color = "\033[0;97m"; + break; + case TLOG_WARN: + color = "\033[0;33m"; + break; + case TLOG_ERROR: + color = "\033[0;31m"; + break; + case TLOG_FATAL: + color = "\033[31;1m"; + break; + default: + unused = write(STDOUT_FILENO, buff, bufflen); + return bufflen; + } + + if (color != NULL) { + fprintf(stdout, "%s%.*s\033[0m\n", color, bufflen - 1, buff); + } else { + fprintf(stdout, "%s", buff); + } + + return bufflen; +} + +static int _tlog_early_print(struct tlog_info_inter *info_inter, const char *format, va_list ap) +{ + char log_buf[TLOG_MAX_LINE_LEN]; + size_t len = 0; + size_t out_len = 0; + struct tlog_time cur_time; + int unused __attribute__((unused)); + + if (tlog.early_print_disable) { + return 0; + } + + if (_tlog_gettime(&cur_time) != 0) { + return -1; + } + + if (tlog.tlog_early_print != NULL) { + tlog.tlog_early_print(&info_inter->info, format, ap); + return out_len; + } + + if (tlog.early_print_no_prefix == 0) { + len = snprintf(log_buf, sizeof(log_buf), "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d,%.3d][%5s][%17s:%-4d] ", + cur_time.year, cur_time.mon, cur_time.mday, cur_time.hour, cur_time.min, cur_time.sec, cur_time.usec / 1000, + tlog_get_level_string(info_inter->info.level), info_inter->info.file, info_inter->info.line); + } + + out_len = len; + len = vsnprintf(log_buf + out_len, sizeof(log_buf) - out_len - 1, format, ap); + out_len += len; + if (len <= 0) { + return -1; + } else if (len >= sizeof(log_buf) - 1) { + out_len = sizeof(log_buf) - 1; + } + + if (log_buf[out_len - 1] != '\n') { + log_buf[out_len] = '\n'; + out_len++; + } + + if (out_len + 1 < sizeof(log_buf) - out_len - 1) { + log_buf[out_len] = '\0'; + } + + if (tlog.early_print_output != NULL) { + len = tlog.early_print_output(&info_inter->info, log_buf, out_len, tlog.early_print_userptr); + if (tlog.early_print_with_screen == 0) { + return len; + } + } + + if (tlog.early_print_color) { + unused = tlog_stdout_with_color(info_inter->info.level, log_buf, out_len); + } else { + unused = write(STDOUT_FILENO, log_buf, out_len); + } + + return out_len; +} + +int tlog_vext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, va_list ap) +{ + struct tlog_info_inter info_inter; + + if (level < tlog_set_level) { + return 0; + } + + if (level >= TLOG_END) { + return -1; + } + + info_inter.info.file = file; + info_inter.info.line = line; + info_inter.info.func = func; + info_inter.info.level = level; + info_inter.userptr = userptr; + if (_tlog_gettime(&info_inter.info.time) != 0) { + return -1; + } + + if (tlog.root == NULL) { + return _tlog_early_print(&info_inter, format, ap); + } + + if (unlikely(tlog.root->logsize <= 0 && tlog.root->logscreen == 0 && tlog.root->set_custom_output_func == 0)) { + return 0; + } + + return _tlog_vprintf(tlog.root, _tlog_root_log_buffer, &info_inter, format, ap); +} + +int tlog_ext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, ...) +{ + int len; + va_list ap; + + va_start(ap, format); + len = tlog_vext(level, file, line, func, userptr, format, ap); + va_end(ap); + + return len; +} + +static int _tlog_rename_logfile(struct tlog_log *log, const char *log_file) +{ + char archive_file[TLOG_BUFF_LEN]; + struct tlog_time logtime; + int i = 0; + + if (_tlog_getmtime(&logtime, log_file) != 0) { + return -1; + } + + snprintf(archive_file, sizeof(archive_file), "%s/%s-%.4d%.2d%.2d-%.2d%.2d%.2d%s", + log->logdir, log->logname, logtime.year, logtime.mon, logtime.mday, + logtime.hour, logtime.min, logtime.sec, log->suffix); + + while (access(archive_file, F_OK) == 0) { + i++; + snprintf(archive_file, sizeof(archive_file), "%s/%s-%.4d%.2d%.2d-%.2d%.2d%.2d-%d%s", + log->logdir, log->logname, logtime.year, logtime.mon, + logtime.mday, logtime.hour, logtime.min, logtime.sec, i, log->suffix); + } + + if (rename(log_file, archive_file) != 0) { + return -1; + } + + chmod(archive_file, log->archive_perm); + + return 0; +} + +static int _tlog_list_dir(const char *path, list_callback callback, void *userptr) +{ + DIR *dir = NULL; + struct dirent *ent; + int ret = 0; + const char *unused __attribute__((unused)) = path; + + dir = opendir(path); + if (dir == NULL) { + fprintf(stderr, "tlog: open directory failed, %s\n", strerror(errno)); + goto errout; + } + + while ((ent = readdir(dir)) != NULL) { + if (strncmp(".", ent->d_name, 2) == 0 || strncmp("..", ent->d_name, 3) == 0) { + continue; + } + ret = callback(path, ent, userptr); + if (ret != 0) { + goto errout; + } + } + + closedir(dir); + return 0; +errout: + if (dir) { + closedir(dir); + dir = NULL; + } + return -1; +} + +static int _tlog_count_log_callback(const char *path, struct dirent *entry, void *userptr) +{ + struct count_log *count_log = (struct count_log *)userptr; + struct tlog_log *log = count_log->log; + char logname[TLOG_LOG_NAME_LEN * 2]; + const char *unused __attribute__((unused)) = path; + + if (strstr(entry->d_name, log->suffix) == NULL) { + return 0; + } + + snprintf(logname, sizeof(logname), "%s-", log->logname); + int len = strnlen(logname, sizeof(logname)); + if (strncmp(logname, entry->d_name, len) != 0) { + return 0; + } + + count_log->lognum++; + return 0; +} + +static int _tlog_get_oldest_callback(const char *path, struct dirent *entry, void *userptr) +{ + struct stat sb; + char filename[TLOG_BUFF_LEN]; + struct oldest_log *oldestlog = (struct oldest_log *)userptr; + struct tlog_log *log = oldestlog->log; + char logname[TLOG_LOG_NAME_LEN * 2]; + + /* if not a log file, skip */ + if (strstr(entry->d_name, log->suffix) == NULL) { + return 0; + } + + /* if not tlog log file, skip */ + snprintf(logname, sizeof(logname), "%s-", log->logname); + int len = strnlen(logname, sizeof(logname)); + if (strncmp(logname, entry->d_name, len) != 0) { + return 0; + } + + /* get log file mtime */ + snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name); + if (stat(filename, &sb) != 0) { + return -1; + } + + if (oldestlog->mtime == 0 || oldestlog->mtime > sb.st_mtime) { + oldestlog->mtime = sb.st_mtime; + strncpy(oldestlog->name, entry->d_name, sizeof(oldestlog->name) - 1); + oldestlog->name[sizeof(oldestlog->name) - 1] = '\0'; + return 0; + } + + return 0; +} + +static int _tlog_remove_oldestlog(struct tlog_log *log) +{ + struct oldest_log oldestlog; + oldestlog.name[0] = 0; + oldestlog.mtime = 0; + oldestlog.log = log; + + /* get oldest log file name */ + if (_tlog_list_dir(log->logdir, _tlog_get_oldest_callback, &oldestlog) != 0) { + return -1; + } + + char filename[PATH_MAX * 2]; + snprintf(filename, sizeof(filename), "%s/%s", log->logdir, oldestlog.name); + + /* delete */ + unlink(filename); + + return 0; +} + +static int _tlog_remove_oldlog(struct tlog_log *log) +{ + struct count_log count_log; + int i = 0; + count_log.lognum = 0; + count_log.log = log; + + /* get total log file number */ + if (_tlog_list_dir(log->logdir, _tlog_count_log_callback, &count_log) != 0) { + fprintf(stderr, "tlog: get log file count failed.\n"); + return -1; + } + + /* remove last N log files */ + for (i = 0; i < count_log.lognum - log->logcount; i++) { + _tlog_remove_oldestlog(log); + } + + return 0; +} + +static void _tlog_log_unlock(struct tlog_log *log) +{ + char lock_file[PATH_MAX * 2]; + if (log->fd_lock <= 0) { + return; + } + + snprintf(lock_file, sizeof(lock_file), "%s/%s.lock", log->logdir, log->logname); + unlink(lock_file); + close(log->fd_lock); + log->fd_lock = -1; +} + +static int _tlog_log_lock(struct tlog_log *log) +{ + char lock_file[PATH_MAX * 2]; + int fd; + + if (log->multi_log == 0) { + return 0; + } + + snprintf(lock_file, sizeof(lock_file), "%s/%s.lock", log->logdir, log->logname); + fd = open(lock_file, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); + if (fd == -1) { + fprintf(stderr, "tlog: create lock file failed, %s", strerror(errno)); + return -1; + } + + if (lockf(fd, F_TLOCK, 0) < 0) { + goto errout; + } + + log->fd_lock = fd; + return 0; + +errout: + if (fd > 0) { + close(fd); + } + return -1; +} + +static void _tlog_wait_pid(struct tlog_log *log, int wait_hang) +{ + int status; + if (log->zip_pid <= 0) { + return; + } + + int option = (wait_hang == 0) ? WNOHANG : 0; + /* check and obtain gzip process status*/ + if (waitpid(log->zip_pid, &status, option) <= 0) { + if (errno != ECHILD || errno == EINTR) { + return; + } + } + + /* gzip process exited */ + log->zip_pid = -1; + char gzip_file[PATH_MAX * 2]; + + /* rename zipped file */ + snprintf(gzip_file, sizeof(gzip_file), "%s/%s.pending.gz", log->logdir, log->logname); + if (_tlog_rename_logfile(log, gzip_file) != 0) { + _tlog_log_unlock(log); + return; + } + + /* remove oldest file */ + _tlog_remove_oldlog(log); + _tlog_log_unlock(log); +} + +static void _tlog_close_all_fd_by_res(void) +{ + struct rlimit lim; + int maxfd = 0; + int i = 0; + + getrlimit(RLIMIT_NOFILE, &lim); + + maxfd = lim.rlim_cur; + if (maxfd > 4096) { + maxfd = 4096; + } + + for (i = 3; i < maxfd; i++) { + close(i); + } +} + +static int _tlog_str_to_int(const char *str) +{ + int num = 0; + + while (*str >= '0' && *str <= '9') { + num = num * 10 + (*str - '0'); + ++str; + } + + if (*str) { + return -1; + } + + return num; +} + +static void _tlog_close_all_fd(void) +{ +#if defined(__linux__) + int dir_fd = -1; + + dir_fd = open("/proc/self/fd/", O_RDONLY | O_DIRECTORY); + if (dir_fd < 0) { + goto errout; + } + + char buffer[sizeof(struct linux_dirent64)]; + int bytes; + while ((bytes = syscall(SYS_getdents64, dir_fd, + (struct linux_dirent64 *)buffer, + sizeof(buffer))) + > 0) { + struct linux_dirent64 *entry; + int offset; + + for (offset = 0; offset < bytes; offset += entry->d_reclen) { + int fd; + entry = (struct linux_dirent64 *)(buffer + offset); + if ((fd = _tlog_str_to_int(entry->d_name)) < 0) { + continue; + } + + if (fd == dir_fd || fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) { + continue; + } + close(fd); + } + } + + + if (bytes < 0) { + goto errout; + } + + close(dir_fd); + return; +errout: + if (dir_fd > 0) { + close(dir_fd); + dir_fd = -1; + } +#endif + _tlog_close_all_fd_by_res(); + return; +} + +static int _tlog_archive_log_compressed(struct tlog_log *log) +{ + char gzip_file[TLOG_BUFF_LEN]; + char log_file[TLOG_BUFF_LEN]; + char pending_file[TLOG_BUFF_LEN]; + + snprintf(gzip_file, sizeof(gzip_file), "%s/%s.pending.gz", log->logdir, log->logname); + snprintf(pending_file, sizeof(pending_file), "%s/%s.pending", log->logdir, log->logname); + + if (_tlog_log_lock(log) != 0) { + return -1; + } + + /* if pending.zip exists */ + if (access(gzip_file, F_OK) == 0) { + /* rename it to standard name */ + if (_tlog_rename_logfile(log, gzip_file) != 0) { + goto errout; + } + } + + if (access(pending_file, F_OK) != 0) { + /* rename current log file to pending */ + snprintf(log_file, sizeof(log_file), "%s/%s", log->logdir, log->logname); + if (rename(log_file, pending_file) != 0) { + goto errout; + } + } + + /* start gzip process to compress log file */ + if (log->zip_pid <= 0) { + int pid = vfork(); + if (pid == 0) { + _tlog_close_all_fd(); + execl(tlog.gzip_cmd, tlog.gzip_cmd, "-1", pending_file, NULL); + fprintf(stderr, "tlog: execl gzip failed, no compress\n"); + log->nocompress = 1; + _exit(1); + } else if (pid < 0) { + if (errno == EPERM || errno == EACCES) { + fprintf(stderr, "tlog: vfork failed, errno: %d, no compress\n", errno); + log->nocompress = 1; + } + goto errout; + } + log->zip_pid = pid; + } + + return 0; + +errout: + _tlog_log_unlock(log); + return -1; +} + +static int _tlog_archive_log_nocompress(struct tlog_log *log) +{ + char log_file[TLOG_BUFF_LEN]; + char pending_file[TLOG_BUFF_LEN]; + + snprintf(pending_file, sizeof(pending_file), "%s/%s.pending", log->logdir, log->logname); + + if (_tlog_log_lock(log) != 0) { + return -1; + } + + if (access(pending_file, F_OK) != 0) { + /* rename current log file to pending */ + snprintf(log_file, sizeof(log_file), "%s/%s", log->logdir, log->logname); + if (rename(log_file, pending_file) != 0) { + goto errout; + } + } + + /* rename pending file */ + if (_tlog_rename_logfile(log, pending_file) != 0) { + goto errout; + } + + /* remove oldest file */ + _tlog_remove_oldlog(log); + _tlog_log_unlock(log); + + return 0; + +errout: + _tlog_log_unlock(log); + return -1; +} + +static int _tlog_archive_log(struct tlog_log *log) +{ + if (log->nocompress) { + return _tlog_archive_log_nocompress(log); + } else { + return _tlog_archive_log_compressed(log); + } +} + +static void _tlog_get_log_name_dir(struct tlog_log *log) +{ + char log_file[PATH_MAX + 1]; + if (log->fd > 0) { + close(log->fd); + log->fd = -1; + } + + pthread_mutex_lock(&tlog.lock); + strncpy(log_file, log->pending_logfile, sizeof(log_file) - 1); + log_file[sizeof(log_file) - 1] = '\0'; + strncpy(log->logdir, dirname(log_file), sizeof(log->logdir) - 1); + log->logdir[sizeof(log->logdir) - 1] = '\0'; + strncpy(log_file, log->pending_logfile, PATH_MAX); + log_file[sizeof(log_file) - 1] = '\0'; + strncpy(log->logname, basename(log_file), sizeof(log->logname) - 1); + log->logname[sizeof(log->logname) - 1] = '\0'; + snprintf(log->logfile, sizeof(log->logfile), "%s/%s", log->logdir, log->logname); + pthread_mutex_unlock(&tlog.lock); +} + +static int _tlog_write(struct tlog_log *log, const char *buff, int bufflen) +{ + int len; + int unused __attribute__((unused)); + struct stat sb = { 0 }; + + if (bufflen <= 0 || log->fail) { + return 0; + } + + if (log->rename_pending) { + _tlog_get_log_name_dir(log); + log->rename_pending = 0; + } + + if (log->logcount <= 0 || log->logsize <= 0) { + return 0; + } + + /* if log file size exceeds threshold, start to compress */ + if (log->multi_log && log->fd > 0) { + log->filesize = lseek(log->fd, 0, SEEK_END); + } + + if (log->filesize > log->logsize && log->zip_pid <= 0) { + if (log->filesize < lseek(log->fd, 0, SEEK_END) && log->multi_log == 0) { + const char *msg = "[Auto enable multi-process write mode, log may be lost, please enable multi-process write mode manually]\n"; + log->multi_log = 1; + unused = write(log->fd, msg, strlen(msg)); + } + close(log->fd); + log->fd = -1; + log->filesize = 0; + _tlog_archive_log(log); + } + + + if ((log->fd <= 0 && log->logsize > 0) + || ((0 == fstat(log->fd, &sb)) + && (0 == sb.st_nlink)) // log file was deleted + ) { + /* open a new log file to write */ + time_t now; + + if (log->fd > 0) { + close(log->fd); + log->fd = -1; + } + + time(&now); + if (now == log->last_try) { + return -1; + } + log->last_try = now; + + if (_tlog_mkdir(log->logdir) != 0) { + if (log->print_errmsg == 0) { + return -1; + } + log->print_errmsg = 0; + fprintf(stderr, "tlog: create log dir %s failed, %s\n", log->logdir, strerror(errno)); + if (errno == EACCES && log->logscreen == 0) { + fprintf(stderr, "tlog: no permission to write log file, output log to console\n"); + tlog_logscreen(log, 1); + tlog_logcount(log, 0); + } + return -1; + } + + log->filesize = 0; + log->fd = open(log->logfile, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, log->file_perm); + if (log->fd < 0) { + if (log->print_errmsg == 0) { + return -1; + } + + fprintf(stderr, "tlog: open log file %s failed, %s\n", log->logfile, strerror(errno)); + log->print_errmsg = 0; + return -1; + } + + if (log->mode_changed != 0) { + fchmod(log->fd, log->file_perm); + } + + log->last_try = 0; + log->print_errmsg = 1; + /* get log file size */ + log->filesize = lseek(log->fd, 0, SEEK_END); + } + + /* write log to file */ + len = write(log->fd, buff, bufflen); + if (len > 0) { + log->filesize += len; + } else { + if (log->fd > 0 && errno == ENOSPC) { + close(log->fd); + log->fd = -1; + } + } + return len; +} + +int tlog_write(struct tlog_log *log, const char *buff, int bufflen) +{ + return _tlog_write(log, buff, bufflen); +} + +static int _tlog_has_data(struct tlog_log *log) +{ + if (log->end != log->start || log->ext_end > 0) { + return 1; + } + + return 0; +} + +static int _tlog_any_has_data_locked(void) +{ + struct tlog_log *next = NULL; + + next = tlog.log; + while (next) { + if (_tlog_has_data(next) == 1) { + return 1; + } + next = next->next; + } + + return 0; +} + +static int _tlog_any_has_data(void) +{ + int ret = 0; + pthread_mutex_lock(&tlog.lock); + ret = _tlog_any_has_data_locked(); + pthread_mutex_unlock(&tlog.lock); + + return ret; +} + +static int _tlog_wait_pids(void) +{ + time_t now = time(NULL); + struct tlog_log *next = NULL; + static struct tlog_log *last_log = NULL; + + pthread_mutex_lock(&tlog.lock); + for (next = tlog.log; next != NULL; next = next->next) { + if (next->zip_pid <= 0) { + continue; + } + + if (next == last_log) { + continue; + } + + if (next->last_waitpid == now) { + continue; + } + + last_log = next; + next->last_waitpid = now; + pthread_mutex_unlock(&tlog.lock); + _tlog_wait_pid(next, 0); + return 0; + } + last_log = NULL; + pthread_mutex_unlock(&tlog.lock); + + return 0; +} + +static int _tlog_close(struct tlog_log *log, int wait_hang) +{ + struct tlog_log *next = tlog.log; + + if (log == NULL) { + return -1; + } + + if (log->zip_pid > 0) { + _tlog_wait_pid(log, wait_hang); + if (log->zip_pid > 0) { + return -1; + } + } + + if (log->fd > 0) { + close(log->fd); + log->fd = -1; + } + + _tlog_log_unlock(log); + + if (log->buff != NULL) { + free(log->buff); + log->buff = NULL; + } + + if (next == log) { + tlog.log = next->next; + free(log); + return 0; + } + + while (next) { + if (next->next == log) { + next->next = log->next; + free(log); + return -1; + } + next = next->next; + } + + pthread_cond_destroy(&log->client_cond); + pthread_mutex_destroy(&log->lock); + + return 0; +} + +static struct tlog_log *_tlog_next_log(struct tlog_log *last_log) +{ + if (last_log == NULL) { + return tlog.log; + } + + return last_log->next; +} + +static struct tlog_log *_tlog_wait_log_locked(struct tlog_log *last_log) +{ + int ret = 0; + struct timespec tm; + struct tlog_log *log = NULL; + struct tlog_log *next = NULL; + int need_wait_pid = 0; + + for (next = tlog.log; next != NULL; next = next->next) { + if (next->zip_pid > 0) { + need_wait_pid = 1; + break; + } + } + + clock_gettime(CLOCK_REALTIME, &tm); + tm.tv_sec += 2; + tlog.is_wait = 1; + tlog.wait_on_log = last_log; + if (need_wait_pid != 0) { + ret = pthread_cond_timedwait(&tlog.cond, &tlog.lock, &tm); + } else { + ret = pthread_cond_wait(&tlog.cond, &tlog.lock); + } + + tlog.is_wait = 0; + tlog.wait_on_log = NULL; + errno = ret; + if (ret == 0 || ret == ETIMEDOUT) { + log = tlog.notify_log; + tlog.notify_log = NULL; + } + + return log; +} + +static void _tlog_wakeup_waiters(struct tlog_log *log) +{ + pthread_mutex_lock(&log->lock); + if (log->waiters > 0) { + /* if there are waiters, wakeup */ + pthread_cond_broadcast(&log->client_cond); + } + pthread_mutex_unlock(&log->lock); +} + +static void _tlog_write_one_segment_log(struct tlog_log *log, char *buff, int bufflen) +{ + struct tlog_segment_head *segment_head = NULL; + int write_len = 0; + + segment_head = (struct tlog_segment_head *)buff; + for (write_len = 0; write_len < bufflen;) { + if (segment_head->magic != TLOG_SEGMENT_MAGIC) { + return; + } + + _tlog_write_output_func(log, segment_head->data, segment_head->len - 1); + write_len += segment_head->len + sizeof(*segment_head); + segment_head = (struct tlog_segment_head *)(buff + write_len); + } +} + +static void _tlog_write_segments_log(struct tlog_log *log, int log_len, int log_extlen) +{ + _tlog_write_one_segment_log(log, log->buff + log->start, log_len); + if (log_extlen > 0) { + /* write extend buffer log */ + _tlog_write_one_segment_log(log, log->buff, log_extlen); + } +} + +static void _tlog_write_buff_log(struct tlog_log *log, int log_len, int log_extlen) +{ + _tlog_write_output_func(log, log->buff + log->start, log_len); + if (log_extlen > 0) { + /* write extend buffer log */ + _tlog_write_output_func(log, log->buff, log_extlen); + } +} + +static void _tlog_work_write(struct tlog_log *log, int log_len, int log_extlen, int log_dropped) +{ + /* write log */ + if (log->segment_log) { + _tlog_write_segments_log(log, log_len, log_extlen); + } else { + _tlog_write_buff_log(log, log_len, log_extlen); + } + + if (log_dropped > 0) { + /* if there is dropped log, record dropped log number */ + char dropmsg[TLOG_TMP_LEN]; + char *msg = dropmsg; + struct tlog_segment_log_head *log_head = NULL; + if (log->segment_log) { + memset(dropmsg, 0, sizeof(struct tlog_segment_log_head)); + log_head = (struct tlog_segment_log_head *)dropmsg; + msg += sizeof(struct tlog_segment_log_head); + log_head->info.level = TLOG_WARN; + } + + int len = snprintf(msg, msg - dropmsg, "[Total Dropped %d Messages]\n", log_dropped); + if (log_head) { + log_head->len = len; + } + _tlog_write_output_func(log, dropmsg, strnlen(dropmsg, sizeof(dropmsg))); + } +} + +static int _tlog_root_write_screen_log(struct tlog_log *log, struct tlog_loginfo *info, const char *buff, int bufflen) +{ + if (log->logscreen == 0) { + return 0; + } + + return _tlog_write_screen(log, info, buff, bufflen); +} + +static int _tlog_root_write_log(struct tlog_log *log, const char *buff, int bufflen) +{ + struct tlog_segment_log_head *head = NULL; + static struct tlog_segment_log_head empty_info = { .info.level = TLOG_INFO }; + if (tlog.output_func == NULL) { + if (log->segment_log) { + head = (struct tlog_segment_log_head *)buff; + _tlog_root_write_screen_log(log, &head->info, head->data, head->len); + return _tlog_write(log, head->data, head->len); + } + _tlog_root_write_screen_log(log, NULL, buff, bufflen); + return _tlog_write(log, buff, bufflen); + } + + if (log->segment_log && tlog.root == log) { + head = (struct tlog_segment_log_head *)buff; + _tlog_root_write_screen_log(log, &head->info, head->data, head->len); + return tlog.output_func(&head->info, head->data, head->len, tlog_get_private(log)); + } + + _tlog_root_write_screen_log(log, NULL, buff, bufflen); + return tlog.output_func(&empty_info.info, buff, bufflen, tlog_get_private(log)); +} + +static void tlog_wait_zip_fini(void) +{ + tlog_log *next; + if (tlog.root == NULL) { + return; + } + + int wait_zip = 1; + int time_out = 0; + while (wait_zip) { + wait_zip = 0; + time_out++; + next = tlog.log; + while (next) { + if (next->zip_pid > 0 && wait_zip == 0) { + wait_zip = 1; + usleep(1000); + } + + if (kill(next->zip_pid, 0) != 0 || time_out >= 5000) { + next->zip_pid = -1; + } + next = next->next; + } + } + + return; +} + +static void *_tlog_work(void *arg) +{ + int log_len = 0; + int log_extlen = 0; + int log_end = 0; + int log_extend = 0; + int log_dropped = 0; + struct tlog_log *log = NULL; + struct tlog_log *loop_log = NULL; + void *unused __attribute__((unused)); + + unused = arg; + + // for child process + tlog_wait_zip_fini(); + + while (1) { + log_len = 0; + log_extlen = 0; + log_extend = 0; + if (__atomic_load_n(&tlog.run, __ATOMIC_RELAXED) == 0) { + if (_tlog_any_has_data() == 0) { + break; + } + } + + _tlog_wait_pids(); + + pthread_mutex_lock(&tlog.lock); + if (loop_log == NULL) { + loop_log = log; + } + + log = _tlog_next_log(log); + if (log == NULL) { + pthread_mutex_unlock(&tlog.lock); + continue; + } + + /* if buffer is empty, wait */ + if (_tlog_any_has_data_locked() == 0 && __atomic_load_n(&tlog.run, __ATOMIC_RELAXED)) { + log = _tlog_wait_log_locked(log); + if (log == NULL) { + pthread_mutex_unlock(&tlog.lock); + if (errno != ETIMEDOUT && __atomic_load_n(&tlog.run, __ATOMIC_RELAXED)) { + sleep(1); + } + continue; + } + } + + if (_tlog_has_data(log) == 0) { + if (log->is_exit) { + if (_tlog_close(log, 0) == 0) { + log = NULL; + loop_log = NULL; + }; + } + pthread_mutex_unlock(&tlog.lock); + continue; + } + + loop_log = NULL; + + if (log->ext_end > 0) { + log_len = log->ext_end - log->start; + log_extend = log->ext_end; + } + if (log->end < log->start) { + log_extlen = log->end; + } else if (log->end > log->start) { + log_len = log->end - log->start; + } + log_end = log->end; + log_dropped = log->dropped; + log->dropped = 0; + pthread_mutex_unlock(&tlog.lock); + + /* start write log work */ + _tlog_work_write(log, log_len, log_extlen, log_dropped); + + pthread_mutex_lock(&tlog.lock); + /* release finished buffer */ + log->start = log_end; + if (log_extend > 0) { + log->ext_end = 0; + } + pthread_mutex_unlock(&tlog.lock); + + _tlog_wakeup_waiters(log); + } + + return NULL; +} + +void tlog_set_early_printf(int enable, int no_prefix, int color) +{ + tlog.early_print_disable = (enable == 0) ? 1 : 0; + tlog.early_print_no_prefix = (no_prefix == 0) ? 0 : 1; + tlog.early_print_color = (color == 0 || isatty(STDOUT_FILENO) == 0) ? 0 : 1; +} + +void tlog_reg_early_printf_callback(tlog_early_print_func callback) +{ + tlog.tlog_early_print = callback; +} + +void tlog_reg_early_printf_output_callback(tlog_log_output_func callback, int log_screen, void *private_data) +{ + tlog.early_print_output = callback; + tlog.early_print_userptr = private_data; + tlog.early_print_with_screen = (log_screen == 0) ? 0 : 1; +} + +const char *tlog_get_level_string(tlog_level level) +{ + if (level >= TLOG_END) { + return NULL; + } + + return tlog_level_str[level]; +} + +void tlog_set_maxlog_count(int count) +{ + tlog_logcount(tlog.root, count); +} + +static void _tlog_log_setlogscreen(struct tlog_log *log, int enable) +{ + if (log == NULL) { + return; + } + + log->logscreen = (enable != 0) ? 1 : 0; +} + +void tlog_setlogscreen(int enable) +{ + _tlog_log_setlogscreen(tlog.root, enable); +} + +int tlog_write_log(const char *buff, int bufflen) +{ + if (unlikely(tlog.root == NULL)) { + return -1; + } + + return _tlog_write(tlog.root, buff, bufflen); +} + +void tlog_logscreen(tlog_log *log, int enable) +{ + if (log == NULL) { + return; + } + + _tlog_log_setlogscreen(log, enable); +} + +static int _tlog_reg_output_func(tlog_log *log, tlog_output_func output) +{ + if (log == NULL) { + return -1; + } + + if (output == NULL) { + log->output_func = _tlog_write; + return 0; + } + + log->output_func = output; + + return 0; +} + +int tlog_reg_output_func(tlog_log *log, tlog_output_func output) +{ + if (log == tlog.root) { + return -1; + } + + int ret = _tlog_reg_output_func(log, output); + if (ret == 0) { + log->set_custom_output_func = 1; + } + + return ret; +} + +int tlog_reg_format_func(tlog_format_func callback) +{ + tlog.root_format = callback; + return 0; +} + +int tlog_reg_log_output_func(tlog_log_output_func output, void *private_data) +{ + tlog.output_func = output; + tlog_set_private(tlog.root, private_data); + tlog.log->set_custom_output_func = 1; + return 0; +} + +int tlog_setlevel(tlog_level level) +{ + if (level >= TLOG_END) { + return -1; + } + + tlog_set_level = level; + return 0; +} + +int tlog_log_enabled(tlog_level level) +{ + if (level >= TLOG_END) { + return 0; + } + + return (tlog_set_level >= level) ? 1 : 0; +} + +tlog_level tlog_getlevel(void) +{ + return tlog_set_level; +} + +void tlog_set_logfile(const char *logfile) +{ + tlog_rename_logfile(tlog.root, logfile); +} + +static void _tlog_get_gzip_cmd_path(void) +{ + char *copy_path = NULL; + char gzip_cmd_path[PATH_MAX]; + const char *env_path = getenv("PATH"); + char *save_ptr = NULL; + + if (env_path == NULL) { + env_path = "/bin:/usr/bin:/usr/local/bin"; + } + + copy_path = strdup(env_path); + if (copy_path == NULL) { + return; + } + + for (char *tok = strtok_r(copy_path, ":", &save_ptr); tok; tok = strtok_r(NULL, ":", &save_ptr)) { + snprintf(gzip_cmd_path, sizeof(gzip_cmd_path), "%s/gzip", tok); + if (access(gzip_cmd_path, X_OK) != 0) { + continue; + } + + snprintf(tlog.gzip_cmd, sizeof(tlog.gzip_cmd), "%s", gzip_cmd_path); + break; + } + + free(copy_path); +} + +tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag) +{ + struct tlog_log *log = NULL; + + if (__atomic_load_n(&tlog.run, __ATOMIC_RELAXED) == 0) { + fprintf(stderr, "tlog: tlog is not initialized.\n"); + return NULL; + } + + log = (struct tlog_log *)malloc(sizeof(*log)); + if (log == NULL) { + fprintf(stderr, "tlog: malloc log failed.\n"); + return NULL; + } + + memset(log, 0, sizeof(*log)); + log->start = 0; + log->end = 0; + log->ext_end = 0; + log->dropped = 0; + log->buffsize = (buffsize > 0) ? buffsize : TLOG_BUFF_SIZE; + log->logsize = (maxlogsize >= 0) ? maxlogsize : TLOG_LOG_SIZE; + log->logcount = (maxlogcount <= 0) ? 0 : maxlogcount; + log->fd = -1; + log->filesize = 0; + log->zip_pid = -1; + log->is_exit = 0; + log->fail = 0; + log->print_errmsg = 1; + log->waiters = 0; + log->block = ((flag & TLOG_NONBLOCK) == 0) ? 1 : 0; + log->nocompress = ((flag & TLOG_NOCOMPRESS) == 0) ? 0 : 1; + log->logscreen = ((flag & TLOG_SCREEN) == 0) ? 0 : 1; + log->logscreen_color = ((flag & TLOG_SCREEN_COLOR) == 0 || isatty(STDOUT_FILENO) == 0) ? 0 : 1; + log->multi_log = ((flag & TLOG_MULTI_WRITE) == 0) ? 0 : 1; + log->segment_log = ((flag & TLOG_SEGMENT) == 0) ? 0 : 1; + log->max_line_size = TLOG_MAX_LINE_LEN; + log->output_func = _tlog_write; + log->file_perm = S_IRUSR | S_IWUSR | S_IRGRP; + log->archive_perm = S_IRUSR | S_IRGRP; + + if (log->nocompress == 0 && tlog.gzip_cmd[0] == '\0') { + log->nocompress = 1; + } + + if (log->logscreen_color == 1) { + log->logscreen = 1; + log->segment_log = 1; + } + + tlog_rename_logfile(log, logfile); + if (log->nocompress) { + strncpy(log->suffix, TLOG_SUFFIX_LOG, sizeof(log->suffix)); + } else { + strncpy(log->suffix, TLOG_SUFFIX_GZ, sizeof(log->suffix)); + } + + log->buff = (char *)malloc(log->buffsize); + if (log->buff == NULL) { + fprintf(stderr, "tlog: malloc log buffer failed, %s\n", strerror(errno)); + goto errout; + } + + pthread_mutex_lock(&tlog.lock); + if (tlog.log == NULL) { + tlog.log = log; + } else { + log->next = tlog.log; + tlog.log = log; + } + pthread_mutex_unlock(&tlog.lock); + + return log; + +errout: + if (log) { + pthread_cond_destroy(&log->client_cond); + pthread_mutex_destroy(&log->lock); + free(log); + log = NULL; + } + + return NULL; +} + +void tlog_close(tlog_log *log) +{ + if (log == NULL) { + return; + } + + log->is_exit = 1; +} + +void tlog_rename_logfile(struct tlog_log *log, const char *logfile) +{ + pthread_mutex_lock(&tlog.lock); + strncpy(log->pending_logfile, logfile, sizeof(log->pending_logfile) - 1); + pthread_mutex_unlock(&tlog.lock); + log->rename_pending = 1; +} + +static void tlog_fork_prepare(void) +{ + if (tlog.root == NULL) { + return; + } + + pthread_mutex_lock(&tlog.lock); + tlog_log *next; + next = tlog.log; + while (next) { + next->multi_log = 1; + next = next->next; + } +} + +static void tlog_fork_parent(void) +{ + if (tlog.root == NULL) { + return; + } + + pthread_mutex_unlock(&tlog.lock); +} + +static void tlog_fork_child(void) +{ + pthread_attr_t attr; + tlog_log *next; + if (tlog.root == NULL) { + return; + } + + next = tlog.log; + while (next) { + next->start = 0; + next->end = 0; + next->ext_end = 0; + next->dropped = 0; + next->filesize = 0; + next = next->next; + } + + pthread_attr_init(&attr); + int ret = pthread_create(&tlog.tid, &attr, _tlog_work, NULL); + if (ret != 0) { + fprintf(stderr, "tlog: create tlog work thread failed, %s\n", strerror(errno)); + goto errout; + } + + goto out; +errout: + next = tlog.log; + while (next) { + next->fail = 1; + next = next->next; + } +out: + pthread_mutex_unlock(&tlog.lock); +} + +int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag) +{ + pthread_attr_t attr; + int ret; + struct tlog_log *log = NULL; + + if (tlog.root_format != NULL) { + fprintf(stderr, "tlog: already initialized.\n"); + return -1; + } + + if (buffsize > 0 && buffsize < TLOG_MAX_LINE_SIZE_SET * 2) { + fprintf(stderr, "tlog: buffer size is invalid.\n"); + return -1; + } + + memset(&tlog, 0, sizeof(tlog)); + tlog.is_wait = 0; + + _tlog_get_gzip_cmd_path(); + pthread_attr_init(&attr); + pthread_cond_init(&tlog.cond, NULL); + pthread_mutex_init(&tlog.lock, NULL); + __atomic_store_n(&tlog.run, 1, __ATOMIC_RELAXED); + + log = tlog_open(logfile, maxlogsize, maxlogcount, buffsize, flag); + if (log == NULL) { + fprintf(stderr, "tlog: init tlog root failed.\n"); + goto errout; + } + _tlog_reg_output_func(log, _tlog_root_write_log); + + if ((flag & TLOG_NOCOMPRESS) == 0 && tlog.gzip_cmd[0] == '\0') { + fprintf(stderr, "tlog: can not find gzip command, disable compress.\n"); + } + + tlog.output_no_prefix = ((flag & TLOG_FORMAT_NO_PREFIX) == 0) ? 0 : 1; + tlog.root = log; + tlog.root_format = _tlog_root_default_format; + + ret = pthread_create(&tlog.tid, &attr, _tlog_work, NULL); + if (ret != 0) { + fprintf(stderr, "tlog: create tlog work thread failed, %s\n", strerror(errno)); + goto errout; + } + + if (flag & TLOG_SUPPORT_FORK) { + pthread_atfork(&tlog_fork_prepare, &tlog_fork_parent, &tlog_fork_child); + } + return 0; +errout: + if (tlog.tid) { + void *retval = NULL; + __atomic_store_n(&tlog.run, 0, __ATOMIC_RELAXED); + pthread_join(tlog.tid, &retval); + tlog.tid = 0; + } + + pthread_cond_destroy(&tlog.cond); + pthread_mutex_destroy(&tlog.lock); + __atomic_store_n(&tlog.run, 0, __ATOMIC_RELAXED); + tlog.root = NULL; + tlog.root_format = NULL; + + _tlog_close(log, 1); + + return -1; +} + +void tlog_exit(void) +{ + if (tlog.root_format == NULL) { + return; + } + + if (tlog.tid) { + void *ret = NULL; + __atomic_store_n(&tlog.run, 0, __ATOMIC_RELAXED); + pthread_mutex_lock(&tlog.lock); + pthread_cond_signal(&tlog.cond); + pthread_mutex_unlock(&tlog.lock); + pthread_join(tlog.tid, &ret); + tlog.tid = 0; + } + + tlog.root = NULL; + while (tlog.log) { + _tlog_close(tlog.log, 1); + } + + pthread_cond_destroy(&tlog.cond); + pthread_mutex_destroy(&tlog.lock); + + tlog.root_format = NULL; + tlog.is_wait = 0; +} diff --git a/src/subprojects/tinylog/tlog.h b/src/subprojects/tinylog/tlog.h new file mode 100644 index 00000000..0c39e271 --- /dev/null +++ b/src/subprojects/tinylog/tlog.h @@ -0,0 +1,363 @@ +/* + * tinylog + * Copyright (C) 2018-2025 Ruilin Peng (Nick) + * https://github.com/pymumu/tinylog + */ + +#ifndef TLOG_H +#define TLOG_H +#include +#include +#include + +#ifdef __cplusplus +#include +#include +#include +#include +#include +extern "C" { +#endif /*__cplusplus */ + +typedef enum { + TLOG_DEBUG3 = 0, + TLOG_DEBUG2, + TLOG_DEBUG, + TLOG_INFO, + TLOG_NOTICE, + TLOG_WARN, + TLOG_ERROR, + TLOG_FATAL, + TLOG_OFF, + TLOG_END +} tlog_level; + +// Reset +#define ANSI_RESET "\033[0m" + +// Regular Colors +#define ANSI_BLACK "\033[30m" +#define ANSI_RED "\033[31m" +#define ANSI_GREEN "\033[32m" +#define ANSI_YELLOW "\033[33m" +#define ANSI_BLUE "\033[34m" +#define ANSI_MAGENTA "\033[35m" +#define ANSI_CYAN "\033[36m" +#define ANSI_WHITE "\033[37m" + +// Bright Colors +#define ANSI_BRIGHT_BLACK "\033[90m" +#define ANSI_BRIGHT_RED "\033[91m" +#define ANSI_BRIGHT_GREEN "\033[92m" +#define ANSI_BRIGHT_YELLOW "\033[93m" +#define ANSI_BRIGHT_BLUE "\033[94m" +#define ANSI_BRIGHT_MAGENTA "\033[95m" +#define ANSI_BRIGHT_CYAN "\033[96m" +#define ANSI_BRIGHT_WHITE "\033[97m" + +// Background Colors +#define ANSI_BG_BLACK "\033[40m" +#define ANSI_BG_RED "\033[41m" +#define ANSI_BG_GREEN "\033[42m" +#define ANSI_BG_YELLOW "\033[43m" +#define ANSI_BG_BLUE "\033[44m" +#define ANSI_BG_MAGENTA "\033[45m" +#define ANSI_BG_CYAN "\033[46m" +#define ANSI_BG_WHITE "\033[47m" + +// Text Styles +#define ANSI_BOLD "\033[1m" +#define ANSI_DIM "\033[2m" +#define ANSI_UNDERLINE "\033[4m" +#define ANSI_BLINK "\033[5m" +#define ANSI_REVERSE "\033[7m" +#define ANSI_HIDDEN "\033[8m" + +struct tlog_time { + int year; + unsigned int usec; + unsigned char mon; + unsigned char mday; + unsigned char hour; + unsigned char min; + unsigned char sec; +} __attribute__((packed)); + +#ifndef TLOG_MAX_LINE_LEN +#define TLOG_MAX_LINE_LEN (1024) +#endif + +/* TLOG FLAGS LIST */ +/* set tlog not compress file when archive */ +#define TLOG_NOCOMPRESS (1 << 0) + +/* Set the segmentation mode to process the log, Used by the callback function to return a full log*/ +#define TLOG_SEGMENT (1 << 1) + +/* + multiwrite: enable multi process write mode. + NOTICE: maxlogsize in all processes must be same when enable this mode. + */ +#define TLOG_MULTI_WRITE (1 << 2) + +/* Not Block if buffer is insufficient. */ +#define TLOG_NONBLOCK (1 << 3) + +/* enable log to screen */ +#define TLOG_SCREEN (1 << 4) + +/* enable support fork process */ +#define TLOG_SUPPORT_FORK (1 << 5) + +/* enable output to screen with color */ +#define TLOG_SCREEN_COLOR (1 << 6) + +/* Not output prefix */ +#define TLOG_FORMAT_NO_PREFIX (1 << 7) + +struct tlog_loginfo { + tlog_level level; + const char *file; + const char *func; + int line; + struct tlog_time time; +} __attribute__((packed)); + +/* +Function: Print log +level: Current log Levels +format: Log formats +*/ +#ifndef BASE_FILE_NAME +#define BASE_FILE_NAME \ + (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \ + : __FILE__) +#endif +#define tlog(level, format, ...) tlog_ext(level, BASE_FILE_NAME, __LINE__, __func__, NULL, format, ##__VA_ARGS__) + +extern int tlog_ext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, ...) + __attribute__((format(printf, 6, 7))) __attribute__((nonnull(6))); +extern int tlog_vext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, va_list ap); + +/* write buff to log file */ +extern int tlog_write_log(const char *buff, int bufflen); + +/* set log level */ +extern int tlog_setlevel(tlog_level level); + +/* is log level enabled*/ +extern int tlog_log_enabled(tlog_level level); + +/* get log level */ +extern tlog_level tlog_getlevel(void); + +/* set log file */ +extern void tlog_set_logfile(const char *logfile); + +/* enable log to screen */ +extern void tlog_setlogscreen(int enable); + +/* Get log level in string */ +extern const char *tlog_get_level_string(tlog_level level); + +/* set max log count */ +extern void tlog_set_maxlog_count(int count); + +/* +Function: Initialize log module +logfile: log file. +maxlogsize: The maximum size of a single log file. +maxlogcount: Number of archived logs. +buffsize: Buffer size, zero for default (128K) +flag: read tlog flags + */ +extern int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag); + +/* flush pending log message, and exit tlog */ +extern void tlog_exit(void); + +/* +customize log output format +steps: +1. define format function, function must be defined as tlog_format_func, use snprintf or vsnprintf format log to buffer +2. call tlog_reg_format_func to register format function. + +read _tlog_format for example. +*/ +typedef int (*tlog_format_func)(char *buff, int maxlen, struct tlog_loginfo *info, void *userptr, const char *format, va_list ap); +extern int tlog_reg_format_func(tlog_format_func callback); + +/* register log output callback + Note: info is invalid when flag TLOG_SEGMENT is not set. + */ +typedef int (*tlog_log_output_func)(struct tlog_loginfo *info, const char *buff, int bufflen, void *private_data); +extern int tlog_reg_log_output_func(tlog_log_output_func output, void *private_data); + +/* enable early log to screen */ +extern void tlog_set_early_printf(int enable, int no_prefix, int color); + +/* set early log callback */ +typedef void (*tlog_early_print_func)(struct tlog_loginfo *loginfo, const char *format, va_list ap); +extern void tlog_reg_early_printf_callback(tlog_early_print_func callback); + +/* set early log output callback */ +extern void tlog_reg_early_printf_output_callback(tlog_log_output_func callback, int log_screen, void *private_data); + +struct tlog_log; +typedef struct tlog_log tlog_log; + +/* get root log handler */ +extern tlog_log *tlog_get_root(void); + +/* +Function: open a new log stream, handler should close by tlog_close +logfile: log file. +maxlogsize: The maximum size of a single log file. +maxlogcount: Number of archived logs. +buffsize: Buffer size, zero for default (128K) +flag: read tlog flags +return: log stream handler. +*/ +extern tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag); + +/* write buff to log file */ +extern int tlog_write(struct tlog_log *log, const char *buff, int bufflen); + +/* close log stream */ +extern void tlog_close(tlog_log *log); + +/* change log file */ +extern void tlog_rename_logfile(struct tlog_log *log, const char *logfile); + +/* +Function: Print log to log stream +log: log stream +format: Log formats +*/ +extern int tlog_printf(tlog_log *log, const char *format, ...) __attribute__((format(printf, 2, 3))) __attribute__((nonnull(1, 2))); + +/* +Function: Print log to log stream with ap +log: log stream +format: Log formats +va_list: args list +*/ +extern int tlog_vprintf(tlog_log *log, const char *format, va_list ap); + +/* enable log to screen */ +extern void tlog_logscreen(tlog_log *log, int enable); + +/* register output callback */ +typedef int (*tlog_output_func)(struct tlog_log *log, const char *buff, int bufflen); +extern int tlog_reg_output_func(tlog_log *log, tlog_output_func output); + +/* set private data */ +extern void tlog_set_private(tlog_log *log, void *private_data); + +/* get private data */ +extern void *tlog_get_private(tlog_log *log); + +/* get local time */ +extern int tlog_localtime(struct tlog_time *tm); + +/* set max line size */ +extern void tlog_set_maxline_size(struct tlog_log *log, int size); + +/* set max log count */ +extern void tlog_logcount(struct tlog_log *log, int count); + +/* +Function: set log file and archive permission +log: log stream +file: log file permission, default is 640 +archive: archive file permission, default is 440 +*/ + +extern void tlog_set_permission(struct tlog_log *log, mode_t file, mode_t archive); + +/* Utility function, output colored logs to standard output */ +extern int tlog_stdout_with_color(tlog_level level, const char *buff, int bufflen); + +#ifdef __cplusplus +class Tlog { +public: + Tlog(tlog_level level, const char *file, int line, const char *func, void *userptr) + { + level_ = level; + file_ = file; + line_ = line; + func_ = func; + userptr_ = userptr; + } + + ~Tlog() + { + tlog_ext(level_, file_, line_, func_, userptr_, "%s", msg_.str().c_str()); + } + + std::ostream &Stream() + { + return msg_; + } + +private: + tlog_level level_; + const char *file_; + int line_; + const char *func_; + void *userptr_; + std::ostringstream msg_; +}; + +class TlogOut { +public: + TlogOut(tlog_log *log) + { + log_ = log; + } + + ~TlogOut() + { + if (log_ == nullptr) { + return; + } + + tlog_printf(log_, "%s", msg_.str().c_str()); + } + + std::ostream &Stream() + { + return msg_; + } + +private: + tlog_log *log_; + std::ostringstream msg_; +}; + +#define Tlog_stream(level) \ + if (tlog_getlevel() <= level) \ + Tlog(level, BASE_FILE_NAME, __LINE__, __func__, NULL).Stream() +#define tlog_debug Tlog_stream(TLOG_DEBUG) +#define tlog_debug2 Tlog_stream(TLOG_DEBUG2) +#define tlog_debug3 Tlog_stream(TLOG_DEBUG3) +#define tlog_info Tlog_stream(TLOG_INFO) +#define tlog_notice Tlog_stream(TLOG_NOTICE) +#define tlog_warn Tlog_stream(TLOG_WARN) +#define tlog_error Tlog_stream(TLOG_ERROR) +#define tlog_fatal Tlog_stream(TLOG_FATAL) + +#define tlog_out(stream) TlogOut(stream).Stream() + +} /*__cplusplus */ +#else +#define tlog_debug(...) tlog(TLOG_DEBUG, ##__VA_ARGS__) +#define tlog_debug2(...) tlog(TLOG_DEBUG2, ##__VA_ARGS__) +#define tlog_debug3(...) tlog(TLOG_DEBUG3, ##__VA_ARGS__) +#define tlog_info(...) tlog(TLOG_INFO, ##__VA_ARGS__) +#define tlog_notice(...) tlog(TLOG_NOTICE, ##__VA_ARGS__) +#define tlog_warn(...) tlog(TLOG_WARN, ##__VA_ARGS__) +#define tlog_error(...) tlog(TLOG_ERROR, ##__VA_ARGS__) +#define tlog_fatal(...) tlog(TLOG_FATAL, ##__VA_ARGS__) +#endif +#endif // !TLOG_H diff --git a/src/subprojects/unity.wrap b/src/subprojects/unity.wrap new file mode 100644 index 00000000..dd9cd8be --- /dev/null +++ b/src/subprojects/unity.wrap @@ -0,0 +1,10 @@ +[wrap-git] +directory = unity +url = https://github.com/ThrowTheSwitch/Unity +revision = v2.6.1 +depth = 1 +patch_directory = unity +diff_files = unity.patch + +[provide] +dependency_names = unity diff --git a/src/subprojects/unity/.editorconfig b/src/subprojects/unity/.editorconfig new file mode 100644 index 00000000..7b7a47a0 --- /dev/null +++ b/src/subprojects/unity/.editorconfig @@ -0,0 +1,27 @@ +############################################################################### +# Unity Project - A Test Framework for C +# .editorconfig - F. Zahn 2019 +############################################################################### + +# This is the topmost .editorconfig file +root = true + +# Settings that apply to all languages / files +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.txt] +trim_trailing_whitespace = false + +[*.rb] +indent_size = 2 + +[*.yml] +indent_size = 2 diff --git a/src/subprojects/unity/.gitattributes b/src/subprojects/unity/.gitattributes new file mode 100644 index 00000000..f84c1623 --- /dev/null +++ b/src/subprojects/unity/.gitattributes @@ -0,0 +1,31 @@ +* text=auto + +# These files are text and should be normalized (convert crlf to lf) +*.rb text +*.test text +*.c text +*.cpp text +*.h text +*.txt text +*.yml text +*.s79 text +*.bat text +*.xcl text +*.inc text +*.info text +*.md text +makefile text +rakefile text +meson.build text + + +#These files are binary and should not be normalized +*.doc binary +*.odt binary +*.pdf binary +*.ewd binary +*.eww binary +*.dni binary +*.wsdt binary +*.dbgdt binary +*.mac binary diff --git a/src/subprojects/unity/.github/workflows/main.yml b/src/subprojects/unity/.github/workflows/main.yml new file mode 100644 index 00000000..f0b6d930 --- /dev/null +++ b/src/subprojects/unity/.github/workflows/main.yml @@ -0,0 +1,35 @@ +--- +# Continuous Integration Workflow: Test case suite run + validation build check +name: CI + +# Controls when the action will run. +# Triggers the workflow on push or pull request events but only for the master branch +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + # Job: Unit test suite + unit-tests: + name: "Unit Tests" + runs-on: ubuntu-latest + strategy: + matrix: + ruby: ['2.7', '3.0', '3.1', '3.2'] + steps: + # Install Ruby Testing Tools + - name: Setup Ruby Testing Tools + run: | + sudo gem install rspec + sudo gem install rubocop -v 1.57.2 + + # Checks out repository under $GITHUB_WORKSPACE + - name: Checkout Latest Repo + uses: actions/checkout@v4 + + # Run Tests + - name: Run All Unit Tests + run: | + cd test && rake ci diff --git a/src/subprojects/unity/.gitignore b/src/subprojects/unity/.gitignore new file mode 100644 index 00000000..211683a8 --- /dev/null +++ b/src/subprojects/unity/.gitignore @@ -0,0 +1,19 @@ +build/ +builddir/ +test/sandbox +.DS_Store +examples/example_1/subprojects/unity +examples/example_1/test1.exe +examples/example_1/test2.exe +examples/example_2/all_tests.exe +examples/example_1/test1.out +examples/example_1/test2.out +examples/example_2/all_tests.out +examples/example_4/builddir +*.sublime-project +*.sublime-workspace +*.cmake +Makefile +CMakeFiles +CMakeCache.txt +!unityConfig.cmake diff --git a/src/subprojects/unity/CMakeLists.txt b/src/subprojects/unity/CMakeLists.txt new file mode 100644 index 00000000..f7062199 --- /dev/null +++ b/src/subprojects/unity/CMakeLists.txt @@ -0,0 +1,172 @@ +################################################################################### +# # +# NAME: CMakeLists.txt # +# # +# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams. # +# WRITTEN BY: Michael Brockus. # +# # +# License: MIT # +# # +################################################################################### + +cmake_minimum_required(VERSION 3.12) + +# Read src/unity.h file and get project version from it +set(UNITY_HEADER "src/unity.h") + +file(STRINGS "${UNITY_HEADER}" UNITY_HEADER_CONTENT + REGEX "^#define UNITY_VERSION_(MAJOR|MINOR|BUILD) +[0-9]+$" +) + +set(UNITY_HEADER_VERSION_MAJOR 0) +set(UNITY_HEADER_VERSION_MINOR 0) +set(UNITY_HEADER_VERSION_BUILD 0) + +foreach(VERSION_LINE IN LISTS UNITY_HEADER_CONTENT) + foreach(VERSION_PART MAJOR MINOR BUILD) + string(CONCAT REGEX_STRING "#define UNITY_VERSION_" + "${VERSION_PART}" + " +([0-9]+)" + ) + + if(VERSION_LINE MATCHES "${REGEX_STRING}") + set(UNITY_HEADER_VERSION_${VERSION_PART} "${CMAKE_MATCH_1}") + endif() + endforeach() +endforeach() + +project(unity + VERSION ${UNITY_HEADER_VERSION_MAJOR}.${UNITY_HEADER_VERSION_MINOR}.${UNITY_HEADER_VERSION_BUILD} + LANGUAGES C + DESCRIPTION "C Unit testing framework." +) + +# Options to Build With Extras ------------------------------------------------- +option(UNITY_EXTENSION_FIXTURE "Compiles Unity with the \"fixture\" extension." OFF) +option(UNITY_EXTENSION_MEMORY "Compiles Unity with the \"memory\" extension." OFF) + +set(UNITY_EXTENSION_FIXTURE_ENABLED $) +set(UNITY_EXTENSION_MEMORY_ENABLED $>) + +if(${UNITY_EXTENSION_FIXTURE}) + message(STATUS "Unity: Building with the fixture extension.") +endif() + +if(${UNITY_EXTENSION_MEMORY}) + message(STATUS "Unity: Building with the memory extension.") +endif() + +# Main target ------------------------------------------------------------------ +add_library(${PROJECT_NAME} STATIC) +add_library(${PROJECT_NAME}::framework ALIAS ${PROJECT_NAME}) + +# Includes --------------------------------------------------------------------- +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +target_sources(${PROJECT_NAME} + PRIVATE + src/unity.c + $<$:extras/fixture/src/unity_fixture.c> + $<$:extras/memory/src/unity_memory.c> +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + $ + $ + $ + $ + $:${CMAKE_CURRENT_SOURCE_DIR}/extras/memory/src>> + $:${CMAKE_CURRENT_SOURCE_DIR}/extras/fixture/src>> +) + +set(${PROJECT_NAME}_PUBLIC_HEADERS + src/unity.h + src/unity_internals.h + $<$:${CMAKE_CURRENT_SOURCE_DIR}/extras/fixture/src/unity_fixture.h> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/extras/fixture/src/unity_fixture_internals.h> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/extras/memory/src/unity_memory.h> +) + +set_target_properties(${PROJECT_NAME} + PROPERTIES + C_STANDARD 11 + C_STANDARD_REQUIRED ON + C_EXTENSIONS OFF + PUBLIC_HEADER "${${PROJECT_NAME}_PUBLIC_HEADERS}" + EXPORT_NAME framework +) + +target_compile_options(${PROJECT_NAME} + PRIVATE + # Clang + $<$: + -Wcast-align + -Wcast-qual + -Wconversion + -Wexit-time-destructors + -Wglobal-constructors + -Wmissing-noreturn + -Wmissing-prototypes + -Wno-missing-braces + -Wold-style-cast + -Wshadow + -Wweak-vtables + -Werror + -Wall + $<$,8.0.0>:-Wextra-semi-stmt> + > + + # GCC + $<$: + -Waddress + -Waggregate-return + -Wformat-nonliteral + -Wformat-security + -Wformat + -Winit-self + -Wmissing-declarations + -Wmissing-include-dirs + -Wno-multichar + -Wno-parentheses + -Wno-type-limits + -Wno-unused-parameter + -Wunreachable-code + -Wwrite-strings + -Wpointer-arith + -Werror + -Wall + > + + # MSVC + $<$: + /Wall + > +) + +write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion +) + +## Target installation +install(TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} + COMPONENT library +) + +## Target's cmake files: targets export +install(EXPORT ${PROJECT_NAME}Targets + NAMESPACE ${PROJECT_NAME}:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) + +## Target's cmake files: config and version config for find_package() +install(FILES ${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) diff --git a/src/subprojects/unity/LICENSE.txt b/src/subprojects/unity/LICENSE.txt new file mode 100644 index 00000000..3e3aad5b --- /dev/null +++ b/src/subprojects/unity/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/subprojects/unity/README.md b/src/subprojects/unity/README.md new file mode 100644 index 00000000..2ebf988e --- /dev/null +++ b/src/subprojects/unity/README.md @@ -0,0 +1,234 @@ +# Unity Test ![CI][] + +__Copyright (c) 2007 - 2024 Unity Project by Mike Karlesky, Mark VanderVoord, and Greg Williams__ + +Welcome to the Unity Test Project, one of the main projects of ThrowTheSwitch.org. +Unity Test is a unit testing framework built for C, with a focus on working with embedded toolchains. + +This project is made to test code targetting microcontrollers big and small. +The core project is a single C file and a pair of headers, allowing it to be added to your existing build setup without too much headache. +You may use any compiler you wish, and may use most existing build systems including Make, CMake, etc. +If you'd like to leave the hard work to us, you might be interested in Ceedling, a build tool also by ThrowTheSwitch.org. + +If you're new to Unity, we encourage you to tour the [getting started guide][]. + +You can also find the [change log][] and [known issues][] in our documentation. + +## Getting Started + +The [docs][] folder contains a [getting started guide][] and much more tips about using Unity. + +## Unity Assertion Summary + +For the full list, see [UnityAssertionsReference.md][]. + +### Basic Validity Tests + + TEST_ASSERT_TRUE(condition) + +Evaluates whatever code is in condition and fails if it evaluates to false + + TEST_ASSERT_FALSE(condition) + +Evaluates whatever code is in condition and fails if it evaluates to true + + TEST_ASSERT(condition) + +Another way of calling `TEST_ASSERT_TRUE` + + TEST_ASSERT_UNLESS(condition) + +Another way of calling `TEST_ASSERT_FALSE` + + TEST_FAIL() + TEST_FAIL_MESSAGE(message) + +This test is automatically marked as a failure. +The message is output stating why. + +### Numerical Assertions: Integers + + TEST_ASSERT_EQUAL_INT(expected, actual) + TEST_ASSERT_EQUAL_INT8(expected, actual) + TEST_ASSERT_EQUAL_INT16(expected, actual) + TEST_ASSERT_EQUAL_INT32(expected, actual) + TEST_ASSERT_EQUAL_INT64(expected, actual) + +Compare two integers for equality and display errors as signed integers. +A cast will be performed to your natural integer size so often this can just be used. +When you need to specify the exact size, you can use a specific version. + + TEST_ASSERT_EQUAL_UINT(expected, actual) + TEST_ASSERT_EQUAL_UINT8(expected, actual) + TEST_ASSERT_EQUAL_UINT16(expected, actual) + TEST_ASSERT_EQUAL_UINT32(expected, actual) + TEST_ASSERT_EQUAL_UINT64(expected, actual) + +Compare two integers for equality and display errors as unsigned integers. +Like INT, there are variants for different sizes also. + + TEST_ASSERT_EQUAL_HEX(expected, actual) + TEST_ASSERT_EQUAL_HEX8(expected, actual) + TEST_ASSERT_EQUAL_HEX16(expected, actual) + TEST_ASSERT_EQUAL_HEX32(expected, actual) + TEST_ASSERT_EQUAL_HEX64(expected, actual) + +Compares two integers for equality and display errors as hexadecimal. +Like the other integer comparisons, you can specify the size... +here the size will also effect how many nibbles are shown (for example, `HEX16` will show 4 nibbles). + + TEST_ASSERT_EQUAL(expected, actual) + +Another way of calling TEST_ASSERT_EQUAL_INT + + TEST_ASSERT_INT_WITHIN(delta, expected, actual) + +Asserts that the actual value is within plus or minus delta of the expected value. +This also comes in size specific variants. + + TEST_ASSERT_GREATER_THAN(threshold, actual) + +Asserts that the actual value is greater than the threshold. +This also comes in size specific variants. + + TEST_ASSERT_LESS_THAN(threshold, actual) + +Asserts that the actual value is less than the threshold. +This also comes in size specific variants. + +### Arrays + + _ARRAY + +You can append `_ARRAY` to any of these macros to make an array comparison of that type. +Here you will need to care a bit more about the actual size of the value being checked. +You will also specify an additional argument which is the number of elements to compare. +For example: + + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, elements) + + _EACH_EQUAL + +Another array comparison option is to check that EVERY element of an array is equal to a single expected value. +You do this by specifying the EACH_EQUAL macro. +For example: + + TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, elements) + +### Numerical Assertions: Bitwise + + TEST_ASSERT_BITS(mask, expected, actual) + +Use an integer mask to specify which bits should be compared between two other integers. +High bits in the mask are compared, low bits ignored. + + TEST_ASSERT_BITS_HIGH(mask, actual) + +Use an integer mask to specify which bits should be inspected to determine if they are all set high. +High bits in the mask are compared, low bits ignored. + + TEST_ASSERT_BITS_LOW(mask, actual) + +Use an integer mask to specify which bits should be inspected to determine if they are all set low. +High bits in the mask are compared, low bits ignored. + + TEST_ASSERT_BIT_HIGH(bit, actual) + +Test a single bit and verify that it is high. +The bit is specified 0-31 for a 32-bit integer. + + TEST_ASSERT_BIT_LOW(bit, actual) + +Test a single bit and verify that it is low. +The bit is specified 0-31 for a 32-bit integer. + +### Numerical Assertions: Floats + + TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) + TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) + +Asserts that the actual value is within plus or minus delta of the expected value. + + TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) + TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) + +Asserts that the actual value is NOT within plus or minus delta of the expected value. + + TEST_ASSERT_EQUAL_FLOAT(expected, actual) + TEST_ASSERT_EQUAL_DOUBLE(expected, actual) + +Asserts that two floating point values are "equal" within a small % delta of the expected value. + + TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) + TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) + +Asserts that two floating point values are NOT "equal" within a small % delta of the expected value. + + TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) + TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) + TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) + TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) + +Asserts that the actual value is less than or greater than the threshold. + +There are also `LESS_OR_EQUAL` and `GREATER_OR_EQUAL` variations. +These obey the same rules for equality as do `TEST_ASSERT_EQUAL_FLOAT` and `TEST_ASSERT_EQUAL_DOUBLE`: +If the two values are within a small % delta of the expected value, the assertion will pass. + +### String Assertions + + TEST_ASSERT_EQUAL_STRING(expected, actual) + +Compare two null-terminate strings. +Fail if any character is different or if the lengths are different. + + TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) + +Compare two strings. +Fail if any character is different, stop comparing after len characters. + + TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) + +Compare two null-terminate strings. +Fail if any character is different or if the lengths are different. +Output a custom message on failure. + + TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) + +Compare two strings. +Fail if any character is different, stop comparing after len characters. +Output a custom message on failure. + +### Pointer Assertions + +Most pointer operations can be performed by simply using the integer comparisons above. +However, a couple of special cases are added for clarity. + + TEST_ASSERT_NULL(pointer) + +Fails if the pointer is not equal to NULL + + TEST_ASSERT_NOT_NULL(pointer) + +Fails if the pointer is equal to NULL + +### Memory Assertions + + TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) + +Compare two blocks of memory. +This is a good generic assertion for types that can't be coerced into acting like standard types... +but since it's a memory compare, you have to be careful that your data types are packed. + +### \_MESSAGE + +You can append `\_MESSAGE` to any of the macros to make them take an additional argument. +This argument is a string that will be printed at the end of the failure strings. +This is useful for specifying more information about the problem. + +[CI]: https://github.com/ThrowTheSwitch/Unity/workflows/CI/badge.svg +[getting started guide]: docs/UnityGettingStartedGuide.md +[change log]: docs/UnityChangeLog.md +[known issues]: docs/UnityKnownIssues.md +[docs]: docs/ +[UnityAssertionsReference.md]: docs/UnityAssertionsReference.md diff --git a/src/subprojects/unity/auto/__init__.py b/src/subprojects/unity/auto/__init__.py new file mode 100644 index 00000000..15f87c39 --- /dev/null +++ b/src/subprojects/unity/auto/__init__.py @@ -0,0 +1,7 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + diff --git a/src/subprojects/unity/auto/colour_prompt.rb b/src/subprojects/unity/auto/colour_prompt.rb new file mode 100644 index 00000000..566efe9e --- /dev/null +++ b/src/subprojects/unity/auto/colour_prompt.rb @@ -0,0 +1,120 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +if RUBY_PLATFORM =~ /(win|w)32$/ + begin + require 'Win32API' + rescue LoadError + puts 'ERROR! "Win32API" library not found' + puts '"Win32API" is required for colour on a windows machine' + puts ' try => "gem install Win32API" on the command line' + puts + end + # puts + # puts 'Windows Environment Detected...' + # puts 'Win32API Library Found.' + # puts +end + +class ColourCommandLine + def initialize + return unless RUBY_PLATFORM =~ /(win|w)32$/ + + get_std_handle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L') + @set_console_txt_attrb = + Win32API.new('kernel32', 'SetConsoleTextAttribute', %w[L N], 'I') + @hout = get_std_handle.call(-11) + end + + def change_to(new_colour) + if RUBY_PLATFORM =~ /(win|w)32$/ + @set_console_txt_attrb.call(@hout, win32_colour(new_colour)) + else + "\033[30;#{posix_colour(new_colour)};22m" + end + end + + def win32_colour(colour) + case colour + when :black then 0 + when :dark_blue then 1 + when :dark_green then 2 + when :dark_cyan then 3 + when :dark_red then 4 + when :dark_purple then 5 + when :dark_yellow, :narrative then 6 + when :default_white, :default, :dark_white then 7 + when :silver then 8 + when :blue then 9 + when :green, :success then 10 + when :cyan, :output then 11 + when :red, :failure then 12 + when :purple then 13 + when :yellow then 14 + when :white then 15 + else + 0 + end + end + + def posix_colour(colour) + # ANSI Escape Codes - Foreground colors + # | Code | Color | + # | 39 | Default foreground color | + # | 30 | Black | + # | 31 | Red | + # | 32 | Green | + # | 33 | Yellow | + # | 34 | Blue | + # | 35 | Magenta | + # | 36 | Cyan | + # | 37 | Light gray | + # | 90 | Dark gray | + # | 91 | Light red | + # | 92 | Light green | + # | 93 | Light yellow | + # | 94 | Light blue | + # | 95 | Light magenta | + # | 96 | Light cyan | + # | 97 | White | + + case colour + when :black then 30 + when :red, :failure then 31 + when :green, :success then 32 + when :yellow then 33 + when :blue, :narrative then 34 + when :purple, :magenta then 35 + when :cyan, :output then 36 + when :white, :default_white then 37 + when :default then 39 + else + 39 + end + end + + def out_c(mode, colour, str) + case RUBY_PLATFORM + when /(win|w)32$/ + change_to(colour) + $stdout.puts str if mode == :puts + $stdout.print str if mode == :print + change_to(:default_white) + else + $stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts + $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print + end + end +end + +def colour_puts(role, str) + ColourCommandLine.new.out_c(:puts, role, str) +end + +def colour_print(role, str) + ColourCommandLine.new.out_c(:print, role, str) +end diff --git a/src/subprojects/unity/auto/colour_reporter.rb b/src/subprojects/unity/auto/colour_reporter.rb new file mode 100644 index 00000000..cac748f8 --- /dev/null +++ b/src/subprojects/unity/auto/colour_reporter.rb @@ -0,0 +1,40 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require_relative 'colour_prompt' + +$colour_output = true + +def report(message) + if !$colour_output + $stdout.puts(message) + else + message = message.join('\n') if message.instance_of?(Array) + message.each_line do |line| + line.chomp! + colour = case line + when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i + Regexp.last_match(1).to_i.zero? ? :green : :red + when /PASS/ + :green + when /^OK$/ + :green + when /(?:FAIL|ERROR)/ + :red + when /IGNORE/ + :yellow + when /^(?:Creating|Compiling|Linking)/ + :white + else + :silver + end + colour_puts(colour, line) + end + end + $stdout.flush + $stderr.flush +end diff --git a/src/subprojects/unity/auto/extract_version.py b/src/subprojects/unity/auto/extract_version.py new file mode 100755 index 00000000..7c2f3d30 --- /dev/null +++ b/src/subprojects/unity/auto/extract_version.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +import re +import sys + +ver_re = re.compile(r"^#define\s+UNITY_VERSION_(?:MAJOR|MINOR|BUILD)\s+(\d+)$") +version = [] + +with open(sys.argv[1], "r") as f: + for line in f: + m = ver_re.match(line) + if m: + version.append(m.group(1)) + +print(".".join(version)) + diff --git a/src/subprojects/unity/auto/generate_config.yml b/src/subprojects/unity/auto/generate_config.yml new file mode 100644 index 00000000..d1cd9b20 --- /dev/null +++ b/src/subprojects/unity/auto/generate_config.yml @@ -0,0 +1,43 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +#this is a sample configuration file for generate_module +#you would use it by calling generate_module with the -ygenerate_config.yml option +#files like this are useful for customizing generate_module to your environment +:generate_module: + :defaults: + #these defaults are used in place of any missing options at the command line + :path_src: ../src/ + :path_inc: ../src/ + :path_tst: ../test/ + :update_svn: true + :includes: + #use [] for no additional includes, otherwise list the includes on separate lines + :src: + - Defs.h + - Board.h + :inc: [] + :tst: + - Defs.h + - Board.h + - Exception.h + :boilerplates: + #these are inserted at the top of generated files. + #just comment out or remove if not desired. + #use %1$s where you would like the file name to appear (path/extension not included) + :src: | + //------------------------------------------- + // %1$s.c + //------------------------------------------- + :inc: | + //------------------------------------------- + // %1$s.h + //------------------------------------------- + :tst: | + //------------------------------------------- + // Test%1$s.c : Units tests for %1$s.c + //------------------------------------------- diff --git a/src/subprojects/unity/auto/generate_module.rb b/src/subprojects/unity/auto/generate_module.rb new file mode 100644 index 00000000..d335cab2 --- /dev/null +++ b/src/subprojects/unity/auto/generate_module.rb @@ -0,0 +1,318 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +# This script creates all the files with start code necessary for a new module. +# A simple module only requires a source file, header file, and test file. +# Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware). + +require 'rubygems' +require 'fileutils' +require 'pathname' + +# TEMPLATE_TST +TEMPLATE_TST ||= '#ifdef %5$s + +#include "unity.h" + +%2$s#include "%1$s.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_%4$s_NeedToImplement(void) +{ + TEST_IGNORE_MESSAGE("Need to Implement %1$s"); +} + +#endif // %5$s +'.freeze + +# TEMPLATE_SRC +TEMPLATE_SRC ||= '%2$s#include "%1$s.h" +'.freeze + +# TEMPLATE_INC +TEMPLATE_INC ||= '#ifndef %3$s_H +#define %3$s_H +%2$s + +#endif // %3$s_H +'.freeze + +class UnityModuleGenerator + ############################ + def initialize(options = nil) + @options = UnityModuleGenerator.default_options + case options + when NilClass then @options + when String then @options.merge!(UnityModuleGenerator.grab_config(options)) + when Hash then @options.merge!(options) + else raise 'If you specify arguments, it should be a filename or a hash of options' + end + + # Create default file paths if none were provided + @options[:path_src] = "#{__dir__}/../src/" if @options[:path_src].nil? + @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil? + @options[:path_tst] = "#{__dir__}/../test/" if @options[:path_tst].nil? + @options[:path_src] += '/' unless @options[:path_src][-1] == 47 + @options[:path_inc] += '/' unless @options[:path_inc][-1] == 47 + @options[:path_tst] += '/' unless @options[:path_tst][-1] == 47 + + # Built in patterns + @patterns = { + 'src' => { + '' => { inc: [] } + }, + 'test' => { + '' => { inc: [] } + }, + 'dh' => { + 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h')] }, + 'Hardware' => { inc: [] } + }, + 'dih' => { + 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h'), create_filename('%1$s', 'Interrupt.h')] }, + 'Interrupt' => { inc: [create_filename('%1$s', 'Hardware.h')] }, + 'Hardware' => { inc: [] } + }, + 'mch' => { + 'Model' => { inc: [] }, + 'Conductor' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'Hardware.h')] }, + 'Hardware' => { inc: [] } + }, + 'mvp' => { + 'Model' => { inc: [] }, + 'Presenter' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'View.h')] }, + 'View' => { inc: [] } + } + } + end + + ############################ + def self.default_options + { + pattern: 'src', + includes: { + src: [], + inc: [], + tst: [] + }, + update_svn: false, + boilerplates: {}, + test_prefix: 'Test', + mock_prefix: 'Mock', + test_define: 'TEST' + } + end + + ############################ + def self.grab_config(config_file) + options = default_options + unless config_file.nil? || config_file.empty? + require_relative 'yaml_helper' + yaml_guts = YamlHelper.load_file(config_file) + options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) + raise "No :unity or :cmock section found in #{config_file}" unless options + end + options + end + + ############################ + def files_to_operate_on(module_name, pattern = nil) + # strip any leading path information from the module name and save for later + subfolder = File.dirname(module_name) + module_name = File.basename(module_name) + + # create triad definition + prefix = @options[:test_prefix] || 'Test' + triad = [{ ext: '.c', path: @options[:path_src], prefix: '', template: TEMPLATE_SRC, inc: :src, boilerplate: @options[:boilerplates][:src] }, + { ext: '.h', path: @options[:path_inc], prefix: '', template: TEMPLATE_INC, inc: :inc, boilerplate: @options[:boilerplates][:inc] }, + { ext: '.c', path: @options[:path_tst], prefix: prefix, template: TEMPLATE_TST, inc: :tst, boilerplate: @options[:boilerplates][:tst], test_define: @options[:test_define] }] + + # prepare the pattern for use + pattern = (pattern || @options[:pattern] || 'src').downcase + patterns = @patterns[pattern] + raise "ERROR: The design pattern '#{pattern}' specified isn't one that I recognize!" if patterns.nil? + + # single file patterns (currently just 'test') can reject the other parts of the triad + triad.select! { |v| v[:inc] == :tst } if pattern == 'test' + + # Assemble the path/names of the files we need to work with. + files = [] + triad.each do |cfg| + patterns.each_pair do |pattern_file, pattern_traits| + submodule_name = create_filename(module_name, pattern_file) + filename = cfg[:prefix] + submodule_name + cfg[:ext] + files << { + path: (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath, + name: submodule_name, + template: cfg[:template], + test_define: cfg[:test_define], + boilerplate: cfg[:boilerplate], + includes: case (cfg[:inc]) + when :src then (@options[:includes][:src] || []) | (pattern_traits[:inc].map { |f| format(f, module_name) }) + when :inc then @options[:includes][:inc] || [] + when :tst then (@options[:includes][:tst] || []) | (pattern_traits[:inc].map { |f| format("#{@options[:mock_prefix]}#{f}", module_name) }) + end + } + end + end + + files + end + + ############################ + def neutralize_filename(name, start_cap: true) + return name if name.empty? + + name = name.split(/(?:\s+|_|(?=[A-Z][a-z]))|(?<=[a-z])(?=[A-Z])/).map(&:capitalize).join('_') + name = name[0].downcase + name[1..] unless start_cap + name + end + + ############################ + def create_filename(part1, part2 = '') + name = part2.empty? ? part1 : "#{part1}_#{part2}" + case (@options[:naming]) + when 'bumpy' then neutralize_filename(name, start_cap: false).delete('_') + when 'camel' then neutralize_filename(name).delete('_') + when 'snake' then neutralize_filename(name).downcase + when 'caps' then neutralize_filename(name).upcase + else name + end + end + + ############################ + def generate(module_name, pattern = nil) + files = files_to_operate_on(module_name, pattern) + + # Abort if all of the module files already exist + all_files_exist = true + files.each do |file| + all_files_exist = false unless File.exist?(file[:path]) + end + raise "ERROR: File #{files[0][:name]} already exists. Exiting." if all_files_exist + + # Create Source Modules + files.each_with_index do |file, _i| + # If this file already exists, don't overwrite it. + if File.exist?(file[:path]) + puts "File #{file[:path]} already exists!" + next + end + # Create the path first if necessary. + FileUtils.mkdir_p(File.dirname(file[:path]), verbose: false) + File.open(file[:path], 'w') do |f| + f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil? + f.write(file[:template] % [file[:name], + file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join, + file[:name].upcase.tr('-', '_'), + file[:name].tr('-', '_'), + file[:test_define]]) + end + if @options[:update_svn] + `svn add \"#{file[:path]}\"` + if $!.exitstatus.zero? + puts "File #{file[:path]} created and added to source control" + else + puts "File #{file[:path]} created but FAILED adding to source control!" + end + else + puts "File #{file[:path]} created" + end + end + puts 'Generate Complete' + end + + ############################ + def destroy(module_name, pattern = nil) + files_to_operate_on(module_name, pattern).each do |filespec| + file = filespec[:path] + if File.exist?(file) + if @options[:update_svn] + `svn delete \"#{file}\" --force` + puts "File #{file} deleted and removed from source control" + else + FileUtils.remove(file) + puts "File #{file} deleted" + end + else + puts "File #{file} does not exist so cannot be removed." + end + end + puts 'Destroy Complete' + end +end + +############################ +# Handle As Command Line If Called That Way +if $0 == __FILE__ + destroy = false + options = {} + module_name = nil + + # Parse the command line parameters. + ARGV.each do |arg| + case arg + when /^-d/ then destroy = true + when /^-u/ then options[:update_svn] = true + when /^-p"?(\w+)"?/ then options[:pattern] = Regexp.last_match(1) + when /^-s"?(.+)"?/ then options[:path_src] = Regexp.last_match(1) + when /^-i"?(.+)"?/ then options[:path_inc] = Regexp.last_match(1) + when /^-t"?(.+)"?/ then options[:path_tst] = Regexp.last_match(1) + when /^-n"?(.+)"?/ then options[:naming] = Regexp.last_match(1) + when /^-y"?(.+)"?/ then options = UnityModuleGenerator.grab_config(Regexp.last_match(1)) + when /^(\w+)/ + raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil? + + module_name = arg + when /^-(h|-help)/ + ARGV = [].freeze + else + raise "ERROR: Unknown option specified '#{arg}'" + end + end + + unless ARGV[0] + puts ["\nGENERATE MODULE\n-------- ------", + "\nUsage: ruby generate_module [options] module_name", + " -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)", + " -s\"../src\" sets the path to output source to '../src' (DEFAULT ../src)", + " -t\"C:/test\" sets the path to output source to 'C:/test' (DEFAULT ../test)", + ' -p"MCH" sets the output pattern to MCH.', + ' dh - driver hardware.', + ' dih - driver interrupt hardware.', + ' mch - model conductor hardware.', + ' mvp - model view presenter.', + ' src - just a source module, header and test. (DEFAULT)', + ' test - just a test file.', + ' -d destroy module instead of creating it.', + ' -n"camel" sets the file naming convention.', + ' bumpy - BumpyCaseFilenames.', + ' camel - camelCaseFilenames.', + ' snake - snake_case_filenames.', + ' caps - CAPS_CASE_FILENAMES.', + ' -u update subversion too (requires subversion command line)', + ' -y"my.yml" selects a different yaml config file for module generation', + ''].join("\n") + exit + end + + raise 'ERROR: You must have a Module name specified! (use option -h for help)' if module_name.nil? + + if destroy + UnityModuleGenerator.new(options).destroy(module_name) + else + UnityModuleGenerator.new(options).generate(module_name) + end + +end diff --git a/src/subprojects/unity/auto/generate_test_runner.rb b/src/subprojects/unity/auto/generate_test_runner.rb new file mode 100755 index 00000000..2c2d5956 --- /dev/null +++ b/src/subprojects/unity/auto/generate_test_runner.rb @@ -0,0 +1,547 @@ +#!/usr/bin/ruby +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +class UnityTestRunnerGenerator + def initialize(options = nil) + @options = UnityTestRunnerGenerator.default_options + case options + when NilClass + @options + when String + @options.merge!(UnityTestRunnerGenerator.grab_config(options)) + when Hash + # Check if some of these have been specified + @options[:has_setup] = !options[:setup_name].nil? + @options[:has_teardown] = !options[:teardown_name].nil? + @options[:has_suite_setup] = !options[:suite_setup].nil? + @options[:has_suite_teardown] = !options[:suite_teardown].nil? + @options.merge!(options) + else + raise 'If you specify arguments, it should be a filename or a hash of options' + end + require_relative 'type_sanitizer' + end + + def self.default_options + { + includes: [], + defines: [], + plugins: [], + framework: :unity, + test_prefix: 'test|spec|should', + mock_prefix: 'Mock', + mock_suffix: '', + setup_name: 'setUp', + teardown_name: 'tearDown', + test_reset_name: 'resetTest', + test_verify_name: 'verifyTest', + main_name: 'main', # set to :auto to automatically generate each time + main_export_decl: '', + cmdline_args: false, + omit_begin_end: false, + use_param_tests: false, + use_system_files: true, + include_extensions: '(?:hpp|hh|H|h)', + source_extensions: '(?:cpp|cc|ino|C|c)' + } + end + + def self.grab_config(config_file) + options = default_options + unless config_file.nil? || config_file.empty? + require_relative 'yaml_helper' + yaml_guts = YamlHelper.load_file(config_file) + options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) + raise "No :unity or :cmock section found in #{config_file}" unless options + end + options + end + + def run(input_file, output_file, options = nil) + @options.merge!(options) unless options.nil? + + # pull required data from source file + source = File.read(input_file) + source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil) + tests = find_tests(source) + headers = find_includes(source) + testfile_includes = @options[:use_system_files] ? (headers[:local] + headers[:system]) : (headers[:local]) + used_mocks = find_mocks(testfile_includes) + testfile_includes = (testfile_includes - used_mocks) + testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ } + find_setup_and_teardown(source) + + # build runner file + generate(input_file, output_file, tests, used_mocks, testfile_includes) + + # determine which files were used to return them + all_files_used = [input_file, output_file] + all_files_used += testfile_includes.map { |filename| "#{filename}.c" } unless testfile_includes.empty? + all_files_used += @options[:includes] unless @options[:includes].empty? + all_files_used += headers[:linkonly] unless headers[:linkonly].empty? + all_files_used.uniq + end + + def generate(input_file, output_file, tests, used_mocks, testfile_includes) + File.open(output_file, 'w') do |output| + create_header(output, used_mocks, testfile_includes) + create_externs(output, tests, used_mocks) + create_mock_management(output, used_mocks) + create_setup(output) + create_teardown(output) + create_suite_setup(output) + create_suite_teardown(output) + create_reset(output) + create_run_test(output) unless tests.empty? + create_args_wrappers(output, tests) + create_main(output, input_file, tests, used_mocks) + end + + return unless @options[:header_file] && !@options[:header_file].empty? + + File.open(@options[:header_file], 'w') do |output| + create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks) + end + end + + def find_tests(source) + tests_and_line_numbers = [] + + # contains characters which will be substituted from within strings, doing + # this prevents these characters from interfering with scrubbers + # @ is not a valid C character, so there should be no clashes with files genuinely containing these markers + substring_subs = { '{' => '@co@', '}' => '@cc@', ';' => '@ss@', '/' => '@fs@' } + substring_re = Regexp.union(substring_subs.keys) + substring_unsubs = substring_subs.invert # the inverse map will be used to fix the strings afterwords + substring_unsubs['@quote@'] = '\\"' + substring_unsubs['@apos@'] = '\\\'' + substring_unre = Regexp.union(substring_unsubs.keys) + source_scrubbed = source.clone + source_scrubbed = source_scrubbed.gsub(/\\"/, '@quote@') # hide escaped quotes to allow capture of the full string/char + source_scrubbed = source_scrubbed.gsub(/\\'/, '@apos@') # hide escaped apostrophes to allow capture of the full string/char + source_scrubbed = source_scrubbed.gsub(/("[^"\n]*")|('[^'\n]*')/) { |s| s.gsub(substring_re, substring_subs) } # temporarily hide problematic characters within strings + source_scrubbed = source_scrubbed.gsub(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks + source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments + source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments (all that remain) + lines = source_scrubbed.split(/(^\s*\#.*$) | (;|\{|\}) /x) # Treat preprocessor directives as a logical line. Match ;, {, and } as end of lines + .map { |line| line.gsub(substring_unre, substring_unsubs) } # unhide the problematic characters previously removed + + lines.each_with_index do |line, _index| + # find tests + next unless line =~ /^((?:\s*(?:TEST_(?:CASE|RANGE|MATRIX))\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m + next unless line =~ /^((?:\s*(?:TEST_(?:CASE|RANGE|MATRIX))\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]})\w*)\s*\(\s*(.*)\s*\)/m + + arguments = Regexp.last_match(1) + name = Regexp.last_match(2) + call = Regexp.last_match(3) + params = Regexp.last_match(4) + args = nil + + if @options[:use_param_tests] && !arguments.empty? + args = [] + type_and_args = arguments.split(/TEST_(CASE|RANGE|MATRIX)/) + (1...type_and_args.length).step(2).each do |i| + case type_and_args[i] + when 'CASE' + args << type_and_args[i + 1].sub(/^\s*\(\s*(.*?)\s*\)\s*$/m, '\1') + + when 'RANGE' + args += type_and_args[i + 1].scan(/(\[|<)\s*(-?\d+.?\d*)\s*,\s*(-?\d+.?\d*)\s*,\s*(-?\d+.?\d*)\s*(\]|>)/m).map do |arg_values_str| + exclude_end = arg_values_str[0] == '<' && arg_values_str[-1] == '>' + arg_values_str[1...-1].map do |arg_value_str| + arg_value_str.include?('.') ? arg_value_str.to_f : arg_value_str.to_i + end.push(exclude_end) + end.map do |arg_values| + Range.new(arg_values[0], arg_values[1], arg_values[3]).step(arg_values[2]).to_a + end.reduce(nil) do |result, arg_range_expanded| + result.nil? ? arg_range_expanded.map { |a| [a] } : result.product(arg_range_expanded) + end.map do |arg_combinations| + arg_combinations.flatten.join(', ') + end + + when 'MATRIX' + single_arg_regex_string = /(?:(?:"(?:\\"|[^\\])*?")+|(?:'\\?.')+|(?:[^\s\]\["',]|\[[\d\S_-]+\])+)/.source + args_regex = /\[((?:\s*#{single_arg_regex_string}\s*,?)*(?:\s*#{single_arg_regex_string})?\s*)\]/m + arg_elements_regex = /\s*(#{single_arg_regex_string})\s*,\s*/m + + args += type_and_args[i + 1].scan(args_regex).flatten.map do |arg_values_str| + "#{arg_values_str},".scan(arg_elements_regex) + end.reduce do |result, arg_range_expanded| + result.product(arg_range_expanded) + end.map do |arg_combinations| + arg_combinations.flatten.join(', ') + end + end + end + end + + tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 } + end + + tests_and_line_numbers.uniq! { |v| v[:test] } + + # determine line numbers and create tests to run + source_lines = source.split("\n") + source_index = 0 + tests_and_line_numbers.size.times do |i| + source_lines[source_index..].each_with_index do |line, index| + next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/ + + source_index += index + tests_and_line_numbers[i][:line_number] = source_index + 1 + break + end + end + + tests_and_line_numbers + end + + def find_includes(source) + # remove comments (block and line, in three steps to ensure correct precedence) + source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks + source.gsub!(/\/\*.*?\*\//m, '') # remove block comments + source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain) + + # parse out includes + { + local: source.scan(/^\s*#include\s+"\s*(.+\.#{@options[:include_extensions]})\s*"/).flatten, + system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" }, + linkonly: source.scan(/^TEST_SOURCE_FILE\(\s*"\s*(.+\.#{@options[:source_extensions]})\s*"/).flatten + } + end + + def find_mocks(includes) + mock_headers = [] + includes.each do |include_path| + include_file = File.basename(include_path) + mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}.*#{@options[:mock_suffix]}\.h$/i + end + mock_headers + end + + def find_setup_and_teardown(source) + @options[:has_setup] = source =~ /void\s+#{@options[:setup_name]}\s*\(/ + @options[:has_teardown] = source =~ /void\s+#{@options[:teardown_name]}\s*\(/ + @options[:has_suite_setup] ||= (source =~ /void\s+suiteSetUp\s*\(/) + @options[:has_suite_teardown] ||= (source =~ /int\s+suiteTearDown\s*\(int\s+([a-zA-Z0-9_])+\s*\)/) + end + + def create_header(output, mocks, testfile_includes = []) + output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') + output.puts("\n/*=======Automagically Detected Files To Include=====*/") + output.puts('extern "C" {') if @options[:externcincludes] + output.puts("#include \"#{@options[:framework]}.h\"") + output.puts('#include "cmock.h"') unless mocks.empty? + output.puts('}') if @options[:externcincludes] + if @options[:defines] && !@options[:defines].empty? + output.puts('/* injected defines for unity settings, etc */') + @options[:defines].each do |d| + def_only = d.match(/(\w+).*/)[1] + output.puts("#ifndef #{def_only}\n#define #{d}\n#endif /* #{def_only} */") + end + end + if @options[:header_file] && !@options[:header_file].empty? + output.puts("#include \"#{File.basename(@options[:header_file])}\"") + else + @options[:includes].flatten.uniq.compact.each do |inc| + output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}") + end + testfile_includes.each do |inc| + output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}") + end + end + output.puts('extern "C" {') if @options[:externcincludes] + mocks.each do |mock| + output.puts("#include \"#{mock}\"") + end + output.puts('}') if @options[:externcincludes] + output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception) + + return unless @options[:enforce_strict_ordering] + + output.puts('') + output.puts('int GlobalExpectCount;') + output.puts('int GlobalVerifyOrder;') + output.puts('char* GlobalOrderError;') + end + + def create_externs(output, tests, _mocks) + output.puts("\n/*=======External Functions This Runner Calls=====*/") + output.puts("extern void #{@options[:setup_name]}(void);") + output.puts("extern void #{@options[:teardown_name]}(void);") + output.puts("\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif") if @options[:externc] + tests.each do |test| + output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});") + end + output.puts("#ifdef __cplusplus\n}\n#endif") if @options[:externc] + output.puts('') + end + + def create_mock_management(output, mock_headers) + output.puts("\n/*=======Mock Management=====*/") + output.puts('static void CMock_Init(void)') + output.puts('{') + + if @options[:enforce_strict_ordering] + output.puts(' GlobalExpectCount = 0;') + output.puts(' GlobalVerifyOrder = 0;') + output.puts(' GlobalOrderError = NULL;') + end + + mocks = mock_headers.map { |mock| File.basename(mock, '.*') } + mocks.each do |mock| + mock_clean = TypeSanitizer.sanitize_c_identifier(mock) + output.puts(" #{mock_clean}_Init();") + end + output.puts("}\n") + + output.puts('static void CMock_Verify(void)') + output.puts('{') + mocks.each do |mock| + mock_clean = TypeSanitizer.sanitize_c_identifier(mock) + output.puts(" #{mock_clean}_Verify();") + end + output.puts("}\n") + + output.puts('static void CMock_Destroy(void)') + output.puts('{') + mocks.each do |mock| + mock_clean = TypeSanitizer.sanitize_c_identifier(mock) + output.puts(" #{mock_clean}_Destroy();") + end + output.puts("}\n") + end + + def create_setup(output) + return if @options[:has_setup] + + output.puts("\n/*=======Setup (stub)=====*/") + output.puts("void #{@options[:setup_name]}(void) {}") + end + + def create_teardown(output) + return if @options[:has_teardown] + + output.puts("\n/*=======Teardown (stub)=====*/") + output.puts("void #{@options[:teardown_name]}(void) {}") + end + + def create_suite_setup(output) + return if @options[:suite_setup].nil? + + output.puts("\n/*=======Suite Setup=====*/") + output.puts('void suiteSetUp(void)') + output.puts('{') + output.puts(@options[:suite_setup]) + output.puts('}') + end + + def create_suite_teardown(output) + return if @options[:suite_teardown].nil? + + output.puts("\n/*=======Suite Teardown=====*/") + output.puts('int suiteTearDown(int num_failures)') + output.puts('{') + output.puts(@options[:suite_teardown]) + output.puts('}') + end + + def create_reset(output) + output.puts("\n/*=======Test Reset Options=====*/") + output.puts("void #{@options[:test_reset_name]}(void);") + output.puts("void #{@options[:test_reset_name]}(void)") + output.puts('{') + output.puts(" #{@options[:teardown_name]}();") + output.puts(' CMock_Verify();') + output.puts(' CMock_Destroy();') + output.puts(' CMock_Init();') + output.puts(" #{@options[:setup_name]}();") + output.puts('}') + output.puts("void #{@options[:test_verify_name]}(void);") + output.puts("void #{@options[:test_verify_name]}(void)") + output.puts('{') + output.puts(' CMock_Verify();') + output.puts('}') + end + + def create_run_test(output) + require 'erb' + file = File.read(File.join(__dir__, 'run_test.erb')) + template = ERB.new(file, trim_mode: '<>') + output.puts("\n#{template.result(binding)}") + end + + def create_args_wrappers(output, tests) + return unless @options[:use_param_tests] + + output.puts("\n/*=======Parameterized Test Wrappers=====*/") + tests.each do |test| + next if test[:args].nil? || test[:args].empty? + + test[:args].each.with_index(1) do |args, idx| + output.puts("static void runner_args#{idx}_#{test[:test]}(void)") + output.puts('{') + output.puts(" #{test[:test]}(#{args});") + output.puts("}\n") + end + end + end + + def create_main(output, filename, tests, used_mocks) + output.puts("\n/*=======MAIN=====*/") + main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s + if @options[:cmdline_args] + if main_name != 'main' + output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);") + end + output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)") + output.puts('{') + output.puts('#ifdef UNITY_USE_COMMAND_LINE_ARGS') + output.puts(' int parse_status = UnityParseOptions(argc, argv);') + output.puts(' if (parse_status != 0)') + output.puts(' {') + output.puts(' if (parse_status < 0)') + output.puts(' {') + output.puts(" UnityPrint(\"#{filename.gsub('.c', '').gsub(/\\/, '\\\\\\')}.\");") + output.puts(' UNITY_PRINT_EOL();') + tests.each do |test| + if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty? + output.puts(" UnityPrint(\" #{test[:test]}\");") + output.puts(' UNITY_PRINT_EOL();') + else + test[:args].each do |args| + output.puts(" UnityPrint(\" #{test[:test]}(#{args})\");") + output.puts(' UNITY_PRINT_EOL();') + end + end + end + output.puts(' return 0;') + output.puts(' }') + output.puts(' return parse_status;') + output.puts(' }') + output.puts('#endif') + else + main_return = @options[:omit_begin_end] ? 'void' : 'int' + if main_name != 'main' + output.puts("#{@options[:main_export_decl]} #{main_return} #{main_name}(void);") + end + output.puts("#{main_return} #{main_name}(void)") + output.puts('{') + end + output.puts(' suiteSetUp();') if @options[:has_suite_setup] + if @options[:omit_begin_end] + output.puts(" UnitySetTestFile(\"#{filename.gsub(/\\/, '\\\\\\')}\");") + else + output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");") + end + tests.each do |test| + if (!@options[:use_param_tests]) || test[:args].nil? || test[:args].empty? + output.puts(" run_test(#{test[:test]}, \"#{test[:test]}\", #{test[:line_number]});") + else + test[:args].each.with_index(1) do |args, idx| + wrapper = "runner_args#{idx}_#{test[:test]}" + testname = "#{test[:test]}(#{args})".dump + output.puts(" run_test(#{wrapper}, #{testname}, #{test[:line_number]});") + end + end + end + output.puts + output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty? + if @options[:has_suite_teardown] + if @options[:omit_begin_end] + output.puts(' (void) suite_teardown(0);') + else + output.puts(' return suiteTearDown(UNITY_END());') + end + else + output.puts(' return UNITY_END();') unless @options[:omit_begin_end] + end + output.puts('}') + end + + def create_h_file(output, filename, tests, testfile_includes, used_mocks) + filename = File.basename(filename).gsub(/[-\/\\.,\s]/, '_').upcase + output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') + output.puts("#ifndef _#{filename}") + output.puts("#define _#{filename}\n\n") + output.puts("#include \"#{@options[:framework]}.h\"") + output.puts('#include "cmock.h"') unless used_mocks.empty? + @options[:includes].flatten.uniq.compact.each do |inc| + output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}") + end + testfile_includes.each do |inc| + output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}") + end + output.puts "\n" + tests.each do |test| + if test[:params].nil? || test[:params].empty? + output.puts("void #{test[:test]}(void);") + else + output.puts("void #{test[:test]}(#{test[:params]});") + end + end + output.puts("#endif\n\n") + end +end + +if $0 == __FILE__ + options = { includes: [] } + + # parse out all the options first (these will all be removed as we go) + ARGV.reject! do |arg| + case arg + when '-cexception' + options[:plugins] = [:cexception] + true + when '-externcincludes' + options[:externcincludes] = true + true + when /\.*\.ya?ml$/ + options = UnityTestRunnerGenerator.grab_config(arg) + true + when /--(\w+)="?(.*)"?/ + options[Regexp.last_match(1).to_sym] = Regexp.last_match(2) + true + when /\.*\.(?:hpp|hh|H|h)$/ + options[:includes] << arg + true + else false + end + end + + # make sure there is at least one parameter left (the input file) + unless ARGV[0] + puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)", + "\n input_test_file - this is the C file you want to create a runner for", + ' output - this is the name of the runner file to generate', + ' defaults to (input_test_file)_Runner', + ' files:', + ' *.yml / *.yaml - loads configuration from here in :unity or :cmock', + ' *.h - header files are added as #includes in runner', + ' options:', + ' -cexception - include cexception support', + ' -externc - add extern "C" for cpp support', + ' --setup_name="" - redefine setUp func name to something else', + ' --teardown_name="" - redefine tearDown func name to something else', + ' --main_name="" - redefine main func name to something else', + ' --test_prefix="" - redefine test prefix from default test|spec|should', + ' --test_reset_name="" - redefine resetTest func name to something else', + ' --test_verify_name="" - redefine verifyTest func name to something else', + ' --suite_setup="" - code to execute for setup of entire suite', + ' --suite_teardown="" - code to execute for teardown of entire suite', + ' --use_param_tests=1 - enable parameterized tests (disabled by default)', + ' --omit_begin_end=1 - omit calls to UnityBegin and UNITY_END (disabled by default)', + ' --header_file="" - path/name of test header file to generate too'].join("\n") + exit 1 + end + + # create the default test runner name if not specified + ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1] + + UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1]) +end diff --git a/src/subprojects/unity/auto/parse_output.rb b/src/subprojects/unity/auto/parse_output.rb new file mode 100644 index 00000000..1711337a --- /dev/null +++ b/src/subprojects/unity/auto/parse_output.rb @@ -0,0 +1,390 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +#============================================================ +# Author: John Theofanopoulos +# A simple parser. Takes the output files generated during the +# build process and extracts information relating to the tests. +# +# Notes: +# To capture an output file under VS builds use the following: +# devenv [build instructions] > Output.txt & type Output.txt +# +# To capture an output file under Linux builds use the following: +# make | tee Output.txt +# +# This script can handle the following output formats: +# - normal output (raw unity) +# - fixture output (unity_fixture.h/.c) +# - fixture output with verbose flag set ("-v") +# - time output flag set (UNITY_INCLUDE_EXEC_TIME define enabled with milliseconds output) +# +# To use this parser use the following command +# ruby parseOutput.rb [options] [file] +# options: -xml : produce a JUnit compatible XML file +# -suiteRequiredSuiteName +# : replace default test suite name to +# "RequiredSuiteName" (can be any name) +# file: file to scan for results +#============================================================ + +# Parser class for handling the input file +class ParseOutput + def initialize + # internal data + @class_name_idx = 0 + @result_usual_idx = 3 + @path_delim = nil + + # xml output related + @xml_out = false + @array_list = false + + # current suite name and statistics + ## testsuite name + @real_test_suite_name = 'Unity' + ## classname for testcase + @test_suite = nil + @total_tests = 0 + @test_passed = 0 + @test_failed = 0 + @test_ignored = 0 + end + + # Set the flag to indicate if there will be an XML output file or not + def set_xml_output + @xml_out = true + end + + # Set the flag to indicate if there will be an XML output file or not + def test_suite_name=(cli_arg) + @real_test_suite_name = cli_arg + puts "Real test suite name will be '#{@real_test_suite_name}'" + end + + def xml_encode_s(str) + str.encode(:xml => :attr) + end + + # If write our output to XML + def write_xml_output + output = File.open('report.xml', 'w') + output << "\n" + @array_list.each do |item| + output << item << "\n" + end + end + + # Pushes the suite info as xml to the array list, which will be written later + def push_xml_output_suite_info + # Insert opening tag at front + heading = "" + @array_list.insert(0, heading) + # Push back the closing tag + @array_list.push '' + end + + # Pushes xml output data to the array list, which will be written later + def push_xml_output_passed(test_name, execution_time = 0) + @array_list.push " " + end + + # Pushes xml output data to the array list, which will be written later + def push_xml_output_failed(test_name, reason, execution_time = 0) + @array_list.push " " + @array_list.push " #{reason}" + @array_list.push ' ' + end + + # Pushes xml output data to the array list, which will be written later + def push_xml_output_ignored(test_name, reason, execution_time = 0) + @array_list.push " " + @array_list.push " #{reason}" + @array_list.push ' ' + end + + # This function will try and determine when the suite is changed. This is + # is the name that gets added to the classname parameter. + def test_suite_verify(test_suite_name) + # Split the path name + test_name = test_suite_name.split(@path_delim) + + # Remove the extension and extract the base_name + base_name = test_name[test_name.size - 1].split('.')[0] + + # Return if the test suite hasn't changed + return unless base_name.to_s != @test_suite.to_s + + @test_suite = base_name + printf "New Test: %s\n", @test_suite + end + + # Prepares the line for verbose fixture output ("-v") + def prepare_fixture_line(line) + line = line.sub('IGNORE_TEST(', '') + line = line.sub('TEST(', '') + line = line.sub(')', ',') + line = line.chomp + array = line.split(',') + array.map { |x| x.to_s.lstrip.chomp } + end + + # Test was flagged as having passed so format the output. + # This is using the Unity fixture output and not the original Unity output. + def test_passed_unity_fixture(array) + class_name = array[0] + test_name = array[1] + test_suite_verify(class_name) + printf "%-40s PASS\n", test_name + + push_xml_output_passed(test_name) if @xml_out + end + + # Test was flagged as having failed so format the output. + # This is using the Unity fixture output and not the original Unity output. + def test_failed_unity_fixture(array) + class_name = array[0] + test_name = array[1] + test_suite_verify(class_name) + reason_array = array[2].split(':') + reason = "#{reason_array[-1].lstrip.chomp} at line: #{reason_array[-4]}" + + printf "%-40s FAILED\n", test_name + + push_xml_output_failed(test_name, reason) if @xml_out + end + + # Test was flagged as being ignored so format the output. + # This is using the Unity fixture output and not the original Unity output. + def test_ignored_unity_fixture(array) + class_name = array[0] + test_name = array[1] + reason = 'No reason given' + if array.size > 2 + reason_array = array[2].split(':') + tmp_reason = reason_array[-1].lstrip.chomp + reason = tmp_reason == 'IGNORE' ? 'No reason given' : tmp_reason + end + test_suite_verify(class_name) + printf "%-40s IGNORED\n", test_name + + push_xml_output_ignored(test_name, reason) if @xml_out + end + + # Test was flagged as having passed so format the output + def test_passed(array) + # ':' symbol will be valid in function args now + real_method_name = array[@result_usual_idx - 1..-2].join(':') + array = array[0..@result_usual_idx - 2] + [real_method_name] + [array[-1]] + + last_item = array.length - 1 + test_time = get_test_time(array[last_item]) + test_name = array[last_item - 1] + test_suite_verify(array[@class_name_idx]) + printf "%-40s PASS %10d ms\n", test_name, test_time + + return unless @xml_out + + push_xml_output_passed(test_name, test_time) if @xml_out + end + + # Test was flagged as having failed so format the line + def test_failed(array) + # ':' symbol will be valid in function args now + real_method_name = array[@result_usual_idx - 1..-3].join(':') + array = array[0..@result_usual_idx - 3] + [real_method_name] + array[-2..] + + last_item = array.length - 1 + test_time = get_test_time(array[last_item]) + test_name = array[last_item - 2] + reason = "#{array[last_item].chomp.lstrip} at line: #{array[last_item - 3]}" + class_name = array[@class_name_idx] + + if test_name.start_with? 'TEST(' + array2 = test_name.split(' ') + + test_suite = array2[0].sub('TEST(', '') + test_suite = test_suite.sub(',', '') + class_name = test_suite + + test_name = array2[1].sub(')', '') + end + + test_suite_verify(class_name) + printf "%-40s FAILED %10d ms\n", test_name, test_time + + push_xml_output_failed(test_name, reason, test_time) if @xml_out + end + + # Test was flagged as being ignored so format the output + def test_ignored(array) + # ':' symbol will be valid in function args now + real_method_name = array[@result_usual_idx - 1..-3].join(':') + array = array[0..@result_usual_idx - 3] + [real_method_name] + array[-2..] + + last_item = array.length - 1 + test_time = get_test_time(array[last_item]) + test_name = array[last_item - 2] + reason = array[last_item].chomp.lstrip + class_name = array[@class_name_idx] + + if test_name.start_with? 'TEST(' + array2 = test_name.split(' ') + + test_suite = array2[0].sub('TEST(', '') + test_suite = test_suite.sub(',', '') + class_name = test_suite + + test_name = array2[1].sub(')', '') + end + + test_suite_verify(class_name) + printf "%-40s IGNORED %10d ms\n", test_name, test_time + + push_xml_output_ignored(test_name, reason, test_time) if @xml_out + end + + # Test time will be in ms + def get_test_time(value_with_time) + test_time_array = value_with_time.scan(/\((-?\d+.?\d*) ms\)\s*$/).flatten.map do |arg_value_str| + arg_value_str.include?('.') ? arg_value_str.to_f : arg_value_str.to_i + end + + test_time_array.any? ? test_time_array[0] : 0 + end + + # Adjusts the os specific members according to the current path style + # (Windows or Unix based) + def detect_os_specifics(line) + if line.include? '\\' + # Windows X:\Y\Z + @class_name_idx = 1 + @path_delim = '\\' + else + # Unix Based /X/Y/Z + @class_name_idx = 0 + @path_delim = '/' + end + end + + # Main function used to parse the file that was captured. + def process(file_name) + @array_list = [] + + puts "Parsing file: #{file_name}" + + @test_passed = 0 + @test_failed = 0 + @test_ignored = 0 + puts '' + puts '=================== RESULTS =====================' + puts '' + # Apply binary encoding. Bad symbols will be unchanged + File.open(file_name, 'rb').each do |line| + # Typical test lines look like these: + # ---------------------------------------------------- + # 1. normal output: + # /.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0 + # /.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented + # /.c:115:test_tc5100_initCanVoidPtrs:PASS + # + # 2. fixture output + # /.c:63:TEST(, ):FAIL: Expected 0x00001234 Was 0x00005A5A + # /.c:36:TEST(, ):IGNORE + # Note: "PASS" information won't be generated in this mode + # + # 3. fixture output with verbose information ("-v") + # TEST()/:168::FAIL: Expected 0x8D Was 0x8C + # TEST(, )/:22::IGNORE: This Test Was Ignored On Purpose + # IGNORE_TEST() + # TEST() PASS + # + # Note: Where path is different on Unix vs Windows devices (Windows leads with a drive letter)! + detect_os_specifics(line) + line_array = line.split(':') + + # If we were able to split the line then we can look to see if any of our target words + # were found. Case is important. + next unless (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(') + + # check if the output is fixture output (with verbose flag "-v") + if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(') + line_array = prepare_fixture_line(line) + if line.include? ' PASS' + test_passed_unity_fixture(line_array) + @test_passed += 1 + elsif line.include? 'FAIL' + test_failed_unity_fixture(line_array) + @test_failed += 1 + elsif line.include? 'IGNORE' + test_ignored_unity_fixture(line_array) + @test_ignored += 1 + end + # normal output / fixture output (without verbose "-v") + elsif line.include? ':PASS' + test_passed(line_array) + @test_passed += 1 + elsif line.include? ':FAIL' + test_failed(line_array) + @test_failed += 1 + elsif line.include? ':IGNORE:' + test_ignored(line_array) + @test_ignored += 1 + elsif line.include? ':IGNORE' + line_array.push('No reason given') + test_ignored(line_array) + @test_ignored += 1 + elsif line_array.size >= 4 + # We will check output from color compilation + if line_array[@result_usual_idx..].any? { |l| l.include? 'PASS' } + test_passed(line_array) + @test_passed += 1 + elsif line_array[@result_usual_idx..].any? { |l| l.include? 'FAIL' } + test_failed(line_array) + @test_failed += 1 + elsif line_array[@result_usual_idx..-2].any? { |l| l.include? 'IGNORE' } + test_ignored(line_array) + @test_ignored += 1 + elsif line_array[@result_usual_idx..].any? { |l| l.include? 'IGNORE' } + line_array.push("No reason given (#{get_test_time(line_array[@result_usual_idx..])} ms)") + test_ignored(line_array) + @test_ignored += 1 + end + end + @total_tests = @test_passed + @test_failed + @test_ignored + end + puts '' + puts '=================== SUMMARY =====================' + puts '' + puts "Tests Passed : #{@test_passed}" + puts "Tests Failed : #{@test_failed}" + puts "Tests Ignored : #{@test_ignored}" + + return unless @xml_out + + # push information about the suite + push_xml_output_suite_info + # write xml output file + write_xml_output + end +end + +# If the command line has no values in, used a default value of Output.txt +parse_my_file = ParseOutput.new + +if ARGV.size >= 1 + ARGV.each do |arg| + if arg == '-xml' + parse_my_file.set_xml_output + elsif arg.start_with?('-suite') + parse_my_file.test_suite_name = arg.delete_prefix('-suite') + else + parse_my_file.process(arg) + break + end + end +end diff --git a/src/subprojects/unity/auto/run_test.erb b/src/subprojects/unity/auto/run_test.erb new file mode 100644 index 00000000..e334d657 --- /dev/null +++ b/src/subprojects/unity/auto/run_test.erb @@ -0,0 +1,37 @@ +/*=======Test Runner Used To Run Each Test=====*/ +static void run_test(UnityTestFunction func, const char* name, UNITY_LINE_TYPE line_num) +{ + Unity.CurrentTestName = name; + Unity.CurrentTestLineNumber = (UNITY_UINT) line_num; +#ifdef UNITY_USE_COMMAND_LINE_ARGS + if (!UnityTestMatches()) + return; +#endif + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + UNITY_EXEC_TIME_START(); + CMock_Init(); + if (TEST_PROTECT()) + { +<% if @options[:plugins].include?(:cexception) %> + volatile CEXCEPTION_T e; + Try { + <%= @options[:setup_name] %>(); + func(); + } Catch(e) { + TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); + } +<% else %> + <%= @options[:setup_name] %>(); + func(); +<% end %> + } + if (TEST_PROTECT()) + { + <%= @options[:teardown_name] %>(); + CMock_Verify(); + } + CMock_Destroy(); + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} diff --git a/src/subprojects/unity/auto/stylize_as_junit.py b/src/subprojects/unity/auto/stylize_as_junit.py new file mode 100644 index 00000000..020ec440 --- /dev/null +++ b/src/subprojects/unity/auto/stylize_as_junit.py @@ -0,0 +1,161 @@ +#! python3 +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +import sys +import os +from glob import glob +import argparse + +from pyparsing import * +from junit_xml import TestSuite, TestCase + + +class UnityTestSummary: + def __init__(self): + self.report = '' + self.total_tests = 0 + self.failures = 0 + self.ignored = 0 + self.targets = 0 + self.root = None + self.output = None + self.test_suites = dict() + + def run(self): + # Clean up result file names + results = [] + for target in self.targets: + results.append(target.replace('\\', '/')) + + # Dig through each result file, looking for details on pass/fail: + for result_file in results: + lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) + if len(lines) == 0: + raise Exception("Empty test result file: %s" % result_file) + + # define an expression for your file reference + entry_one = Combine( + oneOf(list(alphas)) + ':/' + + Word(alphanums + '_-./')) + + entry_two = Word(printables + ' ', excludeChars=':') + entry = entry_one | entry_two + + delimiter = Literal(':').suppress() + # Format of a result line is `[file_name]:line:test_name:RESULT[:msg]` + tc_result_line = Group(ZeroOrMore(entry.setResultsName('tc_file_name')) + + delimiter + entry.setResultsName('tc_line_nr') + + delimiter + entry.setResultsName('tc_name') + + delimiter + entry.setResultsName('tc_status') + + Optional(delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line") + + eol = LineEnd().suppress() + sol = LineStart().suppress() + blank_line = sol + eol + + # Format of the summary line is `# Tests # Failures # Ignored` + tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName( + "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName( + "tc_summary") + tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result") + + # run it and see... + pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line) + pp1.ignore(blank_line | OneOrMore("-")) + + result = list() + for l in lines: + result.append((pp1.parseString(l)).asDict()) + # delete empty results + result = filter(None, result) + + tc_list = list() + for r in result: + if 'tc_line' in r: + tmp_tc_line = r['tc_line'] + + # get only the file name which will be used as the classname + if 'tc_file_name' in tmp_tc_line: + file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0] + else: + file_name = result_file.strip("./") + tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name) + if 'tc_status' in tmp_tc_line: + if str(tmp_tc_line['tc_status']) == 'IGNORE': + if 'tc_msg' in tmp_tc_line: + tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'], + output=r'[File]={0}, [Line]={1}'.format( + tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) + else: + tmp_tc.add_skipped_info(message=" ") + elif str(tmp_tc_line['tc_status']) == 'FAIL': + if 'tc_msg' in tmp_tc_line: + tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'], + output=r'[File]={0}, [Line]={1}'.format( + tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr'])) + else: + tmp_tc.add_failure_info(message=" ") + + tc_list.append((str(result_file), tmp_tc)) + + for k, v in tc_list: + try: + self.test_suites[k].append(v) + except KeyError: + self.test_suites[k] = [v] + ts = [] + for suite_name in self.test_suites: + ts.append(TestSuite(suite_name, self.test_suites[suite_name])) + + with open(self.output, 'w') as f: + TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8') + + return self.report + + def set_targets(self, target_array): + self.targets = target_array + + def set_root_path(self, path): + self.root = path + + def set_output(self, output): + self.output = output + + +if __name__ == '__main__': + uts = UnityTestSummary() + parser = argparse.ArgumentParser(description= + """Takes as input the collection of *.testpass and *.testfail result + files, and converts them to a JUnit formatted XML.""") + parser.add_argument('targets_dir', metavar='result_file_directory', + type=str, nargs='?', default='./', + help="""The location of your results files. + Defaults to current directory if not specified.""") + parser.add_argument('root_path', nargs='?', + default='os.path.split(__file__)[0]', + help="""Helpful for producing more verbose output if + using relative paths.""") + parser.add_argument('--output', '-o', type=str, default="result.xml", + help="""The name of the JUnit-formatted file (XML).""") + args = parser.parse_args() + + if args.targets_dir[-1] != '/': + args.targets_dir+='/' + targets = list(map(lambda x: x.replace('\\', '/'), glob(args.targets_dir + '*.test*'))) + if len(targets) == 0: + raise Exception("No *.testpass or *.testfail files found in '%s'" % args.targets_dir) + uts.set_targets(targets) + + # set the root path + uts.set_root_path(args.root_path) + + # set output + uts.set_output(args.output) + + # run the summarizer + print(uts.run()) diff --git a/src/subprojects/unity/auto/stylize_as_junit.rb b/src/subprojects/unity/auto/stylize_as_junit.rb new file mode 100755 index 00000000..23d89a65 --- /dev/null +++ b/src/subprojects/unity/auto/stylize_as_junit.rb @@ -0,0 +1,253 @@ +#!/usr/bin/ruby +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require 'fileutils' +require 'optparse' +require 'ostruct' +require 'set' + +VERSION = 1.0 + +class ArgvParser + # + # Return a structure describing the options. + # + def self.parse(args) + # The options specified on the command line will be collected in *options*. + # We set default values here. + options = OpenStruct.new + options.results_dir = '.' + options.root_path = '.' + options.out_file = 'results.xml' + + opts = OptionParser.new do |o| + o.banner = 'Usage: unity_to_junit.rb [options]' + + o.separator '' + o.separator 'Specific options:' + + o.on('-r', '--results ', 'Look for Unity Results files here.') do |results| + # puts "results #{results}" + options.results_dir = results + end + + o.on('-p', '--root_path ', 'Prepend this path to files in results.') do |root_path| + options.root_path = root_path + end + + o.on('-o', '--output ', 'XML file to generate.') do |out_file| + # puts "out_file: #{out_file}" + options.out_file = out_file + end + + o.separator '' + o.separator 'Common options:' + + # No argument, shows at tail. This will print an options summary. + o.on_tail('-h', '--help', 'Show this message') do + puts o + exit + end + + # Another typical switch to print the version. + o.on_tail('--version', 'Show version') do + puts "unity_to_junit.rb version #{VERSION}" + exit + end + end + + opts.parse!(args) + options + end +end + +class UnityToJUnit + include FileUtils::Verbose + attr_reader :report, :total_tests, :failures, :ignored + attr_writer :targets, :root, :out_file + + def initialize + @report = '' + @unit_name = '' + end + + def run + # Clean up result file names + results = @targets.map { |target| target.tr('\\', '/') } + # puts "Output File: #{@out_file}" + f = File.new(@out_file, 'w') + write_xml_header(f) + write_suites_header(f) + results.each do |result_file| + lines = File.readlines(result_file).map(&:chomp) + + raise "Empty test result file: #{result_file}" if lines.empty? + + result_output = get_details(result_file, lines) + tests, failures, ignored = parse_test_summary(lines) + result_output[:counts][:total] = tests + result_output[:counts][:failed] = failures + result_output[:counts][:ignored] = ignored + result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored]) + + # use line[0] from the test output to get the test_file path and name + test_file_str = lines[0].tr('\\', '/') + test_file_str = test_file_str.split(':') + test_file = if test_file_str.length < 2 + result_file + else + "#{test_file_str[0]}:#{test_file_str[1]}" + end + result_output[:source][:path] = File.dirname(test_file) + result_output[:source][:file] = File.basename(test_file) + + # save result_output + @unit_name = File.basename(test_file, '.*') + + write_suite_header(result_output[:counts], f) + write_failures(result_output, f) + write_tests(result_output, f) + write_ignored(result_output, f) + write_suite_footer(f) + end + write_suites_footer(f) + f.close + end + + def usage(err_msg = nil) + puts "\nERROR: " + puts err_msg if err_msg + puts 'Usage: unity_to_junit.rb [options]' + puts '' + puts 'Specific options:' + puts ' -r, --results Look for Unity Results files here.' + puts ' -p, --root_path Prepend this path to files in results.' + puts ' -o, --output XML file to generate.' + puts '' + puts 'Common options:' + puts ' -h, --help Show this message' + puts ' --version Show version' + + exit 1 + end + + protected + + def get_details(_result_file, lines) + results = results_structure + lines.each do |line| + line = line.tr('\\', '/') + _src_file, src_line, test_name, status, msg = line.split(/:/) + case status + when 'IGNORE' then results[:ignores] << { test: test_name, line: src_line, message: msg } + when 'FAIL' then results[:failures] << { test: test_name, line: src_line, message: msg } + when 'PASS' then results[:successes] << { test: test_name, line: src_line, message: msg } + end + end + results + end + + def parse_test_summary(summary) + raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + + [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] + end + + private + + def results_structure + { + source: { path: '', file: '' }, + successes: [], + failures: [], + ignores: [], + counts: { total: 0, passed: 0, failed: 0, ignored: 0 }, + stdout: [] + } + end + + def write_xml_header(stream) + stream.puts "" + end + + def write_suites_header(stream) + stream.puts '' + end + + def write_suite_header(counts, stream) + stream.puts "\t" + end + + def write_failures(results, stream) + result = results[:failures] + result.each do |item| + filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) + stream.puts "\t\t" + stream.puts "\t\t\t" + stream.puts "\t\t\t [File] #{filename} [Line] #{item[:line]} " + stream.puts "\t\t" + end + end + + def write_tests(results, stream) + result = results[:successes] + result.each do |item| + stream.puts "\t\t" + end + end + + def write_ignored(results, stream) + result = results[:ignores] + result.each do |item| + filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) + puts "Writing ignored tests for test harness: #{filename}" + stream.puts "\t\t" + stream.puts "\t\t\t" + stream.puts "\t\t\t [File] #{filename} [Line] #{item[:line]} " + stream.puts "\t\t" + end + end + + def write_suite_footer(stream) + stream.puts "\t" + end + + def write_suites_footer(stream) + stream.puts '' + end +end + +if $0 == __FILE__ + # parse out the command options + options = ArgvParser.parse(ARGV) + + # create an instance to work with + utj = UnityToJUnit.new + begin + # look in the specified or current directory for result files + targets = "#{options.results_dir.tr('\\', '/')}**/*.test*" + + results = Dir[targets] + + raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? + + utj.targets = results + + # set the root path + utj.root = options.root_path + + # set the output XML file name + # puts "Output File from options: #{options.out_file}" + utj.out_file = options.out_file + + # run the summarizer + puts utj.run + rescue StandardError => e + utj.usage e.message + end +end diff --git a/src/subprojects/unity/auto/test_file_filter.rb b/src/subprojects/unity/auto/test_file_filter.rb new file mode 100644 index 00000000..f9c8d904 --- /dev/null +++ b/src/subprojects/unity/auto/test_file_filter.rb @@ -0,0 +1,28 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require_relative 'yaml_helper' + +module RakefileHelpers + class TestFileFilter + def initialize(all_files = false) + @all_files = all_files + + return unless @all_files + + file = 'test_file_filter.yml' + return unless File.exist?(file) + + filters = YamlHelper.load_file(file) + @all_files = filters[:all_files] + @only_files = filters[:only_files] + @exclude_files = filters[:exclude_files] + end + + attr_accessor :all_files, :only_files, :exclude_files + end +end diff --git a/src/subprojects/unity/auto/type_sanitizer.rb b/src/subprojects/unity/auto/type_sanitizer.rb new file mode 100644 index 00000000..cfadb0dc --- /dev/null +++ b/src/subprojects/unity/auto/type_sanitizer.rb @@ -0,0 +1,13 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +module TypeSanitizer + def self.sanitize_c_identifier(unsanitized) + # convert filename to valid C identifier by replacing invalid chars with '_' + unsanitized.gsub(/[-\/\\.,\s]/, '_') + end +end diff --git a/src/subprojects/unity/auto/unity_test_summary.py b/src/subprojects/unity/auto/unity_test_summary.py new file mode 100644 index 00000000..43e5af7c --- /dev/null +++ b/src/subprojects/unity/auto/unity_test_summary.py @@ -0,0 +1,140 @@ +#! python3 +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +import sys +import os +import re +from glob import glob + +class UnityTestSummary: + def __init__(self): + self.report = '' + self.total_tests = 0 + self.failures = 0 + self.ignored = 0 + + def run(self): + # Clean up result file names + results = [] + for target in self.targets: + results.append(target.replace('\\', '/')) + + # Dig through each result file, looking for details on pass/fail: + failure_output = [] + ignore_output = [] + + for result_file in results: + lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n'))) + if len(lines) == 0: + raise Exception("Empty test result file: %s" % result_file) + + details = self.get_details(result_file, lines) + failures = details['failures'] + ignores = details['ignores'] + if len(failures) > 0: failure_output.append('\n'.join(failures)) + if len(ignores) > 0: ignore_output.append('n'.join(ignores)) + tests,failures,ignored = self.parse_test_summary('\n'.join(lines)) + self.total_tests += tests + self.failures += failures + self.ignored += ignored + + if self.ignored > 0: + self.report += "\n" + self.report += "--------------------------\n" + self.report += "UNITY IGNORED TEST SUMMARY\n" + self.report += "--------------------------\n" + self.report += "\n".join(ignore_output) + + if self.failures > 0: + self.report += "\n" + self.report += "--------------------------\n" + self.report += "UNITY FAILED TEST SUMMARY\n" + self.report += "--------------------------\n" + self.report += '\n'.join(failure_output) + + self.report += "\n" + self.report += "--------------------------\n" + self.report += "OVERALL UNITY TEST SUMMARY\n" + self.report += "--------------------------\n" + self.report += "{total_tests} TOTAL TESTS {failures} TOTAL FAILURES {ignored} IGNORED\n".format(total_tests = self.total_tests, failures=self.failures, ignored=self.ignored) + self.report += "\n" + + return self.report + + def set_targets(self, target_array): + self.targets = target_array + + def set_root_path(self, path): + self.root = path + + def usage(self, err_msg=None): + print("\nERROR: ") + if err_msg: + print(err_msg) + print("\nUsage: unity_test_summary.py result_file_directory/ root_path/") + print(" result_file_directory - The location of your results files.") + print(" Defaults to current directory if not specified.") + print(" Should end in / if specified.") + print(" root_path - Helpful for producing more verbose output if using relative paths.") + sys.exit(1) + + def get_details(self, result_file, lines): + results = { 'failures': [], 'ignores': [], 'successes': [] } + for line in lines: + parts = line.split(':') + if len(parts) == 5: + src_file,src_line,test_name,status,msg = parts + elif len(parts) == 4: + src_file,src_line,test_name,status = parts + msg = '' + else: + continue + if len(self.root) > 0: + line_out = "%s%s" % (self.root, line) + else: + line_out = line + if status == 'IGNORE': + results['ignores'].append(line_out) + elif status == 'FAIL': + results['failures'].append(line_out) + elif status == 'PASS': + results['successes'].append(line_out) + return results + + def parse_test_summary(self, summary): + m = re.search(r"([0-9]+) Tests ([0-9]+) Failures ([0-9]+) Ignored", summary) + if not m: + raise Exception("Couldn't parse test results: %s" % summary) + + return int(m.group(1)), int(m.group(2)), int(m.group(3)) + + +if __name__ == '__main__': + uts = UnityTestSummary() + try: + #look in the specified or current directory for result files + if len(sys.argv) > 1: + targets_dir = sys.argv[1] + else: + targets_dir = './' + targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '**/*.test*', recursive=True))) + if len(targets) == 0: + raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir) + uts.set_targets(targets) + + #set the root path + if len(sys.argv) > 2: + root_path = sys.argv[2] + else: + root_path = os.path.split(__file__)[0] + uts.set_root_path(root_path) + + #run the summarizer + print(uts.run()) + except Exception as e: + uts.usage(e) diff --git a/src/subprojects/unity/auto/unity_test_summary.rb b/src/subprojects/unity/auto/unity_test_summary.rb new file mode 100644 index 00000000..33c8d7a3 --- /dev/null +++ b/src/subprojects/unity/auto/unity_test_summary.rb @@ -0,0 +1,140 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +# !/usr/bin/ruby +# +# unity_test_summary.rb +# +require 'fileutils' +require 'set' + +class UnityTestSummary + include FileUtils::Verbose + + attr_reader :report, :total_tests, :failures, :ignored + attr_writer :targets, :root + + def initialize(_opts = {}) + @report = '' + @total_tests = 0 + @failures = 0 + @ignored = 0 + end + + def run + # Clean up result file names + results = @targets.map { |target| target.tr('\\', '/') } + + # Dig through each result file, looking for details on pass/fail: + failure_output = [] + ignore_output = [] + + results.each do |result_file| + lines = File.readlines(result_file).map(&:chomp) + + raise "Empty test result file: #{result_file}" if lines.empty? + + output = get_details(result_file, lines) + failure_output << output[:failures] unless output[:failures].empty? + ignore_output << output[:ignores] unless output[:ignores].empty? + tests, failures, ignored = parse_test_summary(lines) + @total_tests += tests + @failures += failures + @ignored += ignored + end + + if @ignored > 0 + @report += "\n" + @report += "--------------------------\n" + @report += "UNITY IGNORED TEST SUMMARY\n" + @report += "--------------------------\n" + @report += ignore_output.flatten.join("\n") + end + + if @failures > 0 + @report += "\n" + @report += "--------------------------\n" + @report += "UNITY FAILED TEST SUMMARY\n" + @report += "--------------------------\n" + @report += failure_output.flatten.join("\n") + end + + @report += "\n" + @report += "--------------------------\n" + @report += "OVERALL UNITY TEST SUMMARY\n" + @report += "--------------------------\n" + @report += "#{@total_tests} TOTAL TESTS #{@failures} TOTAL FAILURES #{@ignored} IGNORED\n" + @report += "\n" + end + + def usage(err_msg = nil) + puts "\nERROR: " + puts err_msg if err_msg + puts "\nUsage: unity_test_summary.rb result_file_directory/ root_path/" + puts ' result_file_directory - The location of your results files.' + puts ' Defaults to current directory if not specified.' + puts ' Should end in / if specified.' + puts ' root_path - Helpful for producing more verbose output if using relative paths.' + exit 1 + end + + protected + + def get_details(_result_file, lines) + results = { failures: [], ignores: [], successes: [] } + lines.each do |line| + status_match = line.match(/^[^:]+:[^:]+:\w+(?:\([^)]*\))?:([^:]+):?/) + next unless status_match + + status = status_match.captures[0] + + line_out = (@root && (@root != 0) ? "#{@root}#{line}" : line).gsub(/\//, '\\') + case status + when 'IGNORE' then results[:ignores] << line_out + when 'FAIL' then results[:failures] << line_out + when 'PASS' then results[:successes] << line_out + end + end + results + end + + def parse_test_summary(summary) + raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + + [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] + end +end + +if $0 == __FILE__ + + # parse out the command options + opts, args = ARGV.partition { |v| v =~ /^--\w+/ } + opts.map! { |v| v[2..].to_sym } + + # create an instance to work with + uts = UnityTestSummary.new(opts) + + begin + # look in the specified or current directory for result files + args[0] ||= './' + targets = "#{ARGV[0].tr('\\', '/')}**/*.test*" + results = Dir[targets] + + raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? + + uts.targets = results + + # set the root path + args[1] ||= "#{Dir.pwd}/" + uts.root = ARGV[1] + + # run the summarizer + puts uts.run + rescue StandardError => e + uts.usage e.message + end +end diff --git a/src/subprojects/unity/auto/yaml_helper.rb b/src/subprojects/unity/auto/yaml_helper.rb new file mode 100644 index 00000000..6d1bf7ae --- /dev/null +++ b/src/subprojects/unity/auto/yaml_helper.rb @@ -0,0 +1,23 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require 'yaml' + +module YamlHelper + def self.load(body) + if YAML.respond_to?(:unsafe_load) + YAML.unsafe_load(body) + else + YAML.load(body) + end + end + + def self.load_file(file) + body = File.read(file) + self.load(body) + end +end diff --git a/src/subprojects/unity/docs/CODE_OF_CONDUCT.md b/src/subprojects/unity/docs/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..84e34806 --- /dev/null +++ b/src/subprojects/unity/docs/CODE_OF_CONDUCT.md @@ -0,0 +1,138 @@ + +# ThrowTheSwitch.org Code of Conduct + +Thank you for participating in a ThrowTheSwitch.org community project! We want +this to continue to be a warm and inviting place for everyone to share ideas +and get help. To accomplish this goal, we've developed this Code of Conduct. + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +hello@thingamabyte.com. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/src/subprojects/unity/docs/CONTRIBUTING.md b/src/subprojects/unity/docs/CONTRIBUTING.md new file mode 100644 index 00000000..e64a285a --- /dev/null +++ b/src/subprojects/unity/docs/CONTRIBUTING.md @@ -0,0 +1,238 @@ +# Contributing to a ThrowTheSwitch.org Project + +👍🎉 _First off, thanks for taking the time to contribute!_ 🎉👍 + +The following is a set of guidelines for contributing to any of ThrowTheSwitch.org's projects or the website itself, hosted at throwtheswitch.org or ThrowTheSwitch's organization on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. + +### Table Of Contents + +- [Code of Conduct](#book-code-of-conduct) +- [Asking Questions](#bulb-asking-questions) +- [Opening an Issue](#inbox_tray-opening-an-issue) +- [Feature Requests](#love_letter-feature-requests) +- [Triaging Issues](#mag-triaging-issues) +- [Submitting Pull Requests](#repeat-submitting-pull-requests) +- [Writing Commit Messages](#memo-writing-commit-messages) +- [Code Review](#white_check_mark-code-review) +- [Coding Style](#nail_care-coding-style) +- [Certificate of Origin](#medal_sports-certificate-of-origin) +- [Credits](#pray-credits) + +## :book: Code of Conduct + +Please review our [Code of Conduct](CODE_OF_CONDUCT.md). It is in effect at all times. We expect it to be honored by everyone who contributes to this project. Be a Good Human! + +## :bulb: Asking Questions + +> **Note:** Please don't file an issue to ask a question. We have an official forum where the community chimes in with helpful advice if you have questions. + +* [ThrowTheSwitch Forums](https://throwtheswitch.org/forums) + +### What should I know before I get started? + +ThrowTheSwitch hosts a number of open source projects — Ceedling is the entrypoint for many users. Ceedling is actually built upon the foundation of Unity Test (a flexible C testing framework) and CMock (a mocking tool for C) and it coordinates many other open source and proprietary tools. Please do your best to focus your ideas and questions at the correct tool. We'll do our best to help you find your way, but there will be times where we'll have to direct your attention to another subtool. + +Here are some of the main projects hosted by ThrowTheSwitch.org: + + - [Ceedling](https://www.github.com/throwtheswitch/ceedling) -- Build coordinator for testing C applications, especially embedded C (and optionally your release build too!) + - [CMock](https://www.github.com/throwtheswitch/cmock) -- Mocking tool for automatically creating stubs, mocks, and skeletons in C + - [Unity](https://www.github.com/throwtheswitch/unity) -- Unit Testing framework for C, specially embedded C. + - [MadScienceLabDocker](https://www.github.com/throwtheswitch/madsciencelabdocker) -- Docker image giving you a shortcut to getting running with Ceedling + - [CException](https://www.github.com/throwtheswitch/cexception) -- An exception framework for using simple exceptions in C. + +There are many more, but this list should be a good starting point. + +## :inbox_tray: Opening an Issue + +Before [creating an issue](https://help.github.com/en/github/managing-your-work-on-github/creating-an-issue), check if you are using the latest version of the project. If you are not up-to-date, see if updating fixes your issue first. + +### :beetle: Bug Reports and Other Issues + +A great way to contribute to the project is to send a detailed issue when you encounter a problem. We always appreciate a well-written, thorough bug report. :v: + +In short, since you are most likely a developer, **provide a ticket that you would like to receive**. + +- **Review the documentation** before opening a new issue. + +- **Do not open a duplicate issue!** Search through existing issues to see if your issue has previously been reported. If your issue exists, comment with any additional information you have. You may simply note "I have this problem too", which helps prioritize the most common problems and requests. + +- **Prefer using [reactions](https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/)**, not comments, if you simply want to "+1" an existing issue. + +- **Fully complete the provided issue template.** The bug report template requests all the information we need to quickly and efficiently address your issue. Be clear, concise, and descriptive. Provide as much information as you can, including steps to reproduce, stack traces, compiler errors, library versions, OS versions, and screenshots (if applicable). + +- **Use [GitHub-flavored Markdown](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax).** Especially put code blocks and console outputs in backticks (```). This improves readability. + +## :seedling: Feature Requests + +Feature requests are welcome! We don't have all the answers and we truly love the collaborative experience of building software together! That being said, we cannot guarantee your request will be accepted. We want to avoid [feature creep](https://en.wikipedia.org/wiki/Feature_creep). Your idea may be great, but also out-of-scope for the project. If accepted, we'll do our best to tackle it in a timely manner, but cannot make any commitments regarding the timeline for implementation and release. However, you are welcome to submit a pull request to help! + +- **Please don't open a duplicate feature request.** Search for existing feature requests first. If you find your feature (or one very similar) previously requested, comment on that issue. + +- **Fully complete the provided issue template.** The feature request template asks for all necessary information for us to begin a productive conversation. + +- Be precise about the proposed outcome of the feature and how it relates to existing features. Include implementation details if possible. + +## :mag: Triaging Issues + +You can triage issues which may include reproducing bug reports or asking for additional information, such as version numbers or reproduction instructions. Any help you can provide to quickly resolve an issue is very much appreciated! + +## :repeat: Submitting Pull Requests + +We **love** pull requests! Before [forking the repo](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) and [creating a pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests) for non-trivial changes, it is usually best to first open an issue to discuss the changes, or discuss your intended approach for solving the problem in the comments for an existing issue. + +For most contributions, after your first pull request is accepted and merged, you will be [invited to the project](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/inviting-collaborators-to-a-personal-repository) and given **push access**. :tada: + +*Note: All contributions will be licensed under the project's license.* + +- **Smaller is better.** Submit **one** pull request per bug fix or feature. A pull request should contain isolated changes pertaining to a single bug fix or feature implementation. **Do not** refactor or reformat code that is unrelated to your change. It is better to **submit many small pull requests** rather than a single large one. Enormous pull requests will take enormous amounts of time to review, or may be rejected altogether. + +- **Coordinate bigger changes.** For large and non-trivial changes, open an issue to discuss a strategy with the maintainers. Otherwise, you risk doing a lot of work for nothing! + +- **Prioritize understanding over cleverness.** Write code clearly and concisely. Remember that source code usually gets written once and read often. Ensure the code is clear to the reader. The purpose and logic should be obvious to a reasonably skilled developer, otherwise you should add a comment that explains it. + +- **Follow existing coding style and conventions.** Keep your code consistent with the style, formatting, and conventions in the rest of the code base. When possible, these will be enforced with a linter. Consistency makes it easier to review and modify in the future. + +- **Include test coverage.** Add unit tests when possible. Follow existing patterns for implementing tests. + +- **Update the example project** if one exists to exercise any new functionality you have added. + +- **Add documentation.** Document your changes with code doc comments or in existing guides. + +- **Update the CHANGELOG** for all enhancements and bug fixes. Include the corresponding issue number if one exists, and your GitHub username. (example: "- Fixed crash in profile view. #123 @jessesquires") + +- **Use the repo's default branch.** Branch from and [submit your pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork) to the repo's default branch. Usually this is `main`, but it could be `dev`, `develop`, or `master`. + +- **[Resolve any merge conflicts](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/resolving-a-merge-conflict-on-github)** that occur. + +- **Promptly address any CI failures**. If your pull request fails to build or pass tests, please push another commit to fix it. + +- When writing comments, use properly constructed sentences, including punctuation. + +- Use spaces, not tabs. + +## :memo: Writing Commit Messages + +Please [write a great commit message](https://chris.beams.io/posts/git-commit/). + +1. Separate subject from body with a blank line +1. Limit the subject line to 50 characters +1. Capitalize the subject line +1. Do not end the subject line with a period +1. Wrap the body at _about_ 72 characters +1. Use the body to explain **why**, *not what and how* (the code shows that!) +1. If applicable, prefix the title with the relevant component name or emoji (see below. examples: "[Docs] Fix typo", "[Profile] Fix missing avatar") + +``` +:palm_tree: Summary of Amazing Feature Here + +Add a more detailed explanation here, if necessary. Possibly give +some background about the issue being fixed, etc. The body of the +commit message can be several paragraphs. Further paragraphs come +after blank lines and please do proper word-wrap. + +Wrap it to about 72 characters or so. In some contexts, +the first line is treated as the subject of the commit and the +rest of the text as the body. The blank line separating the summary +from the body is critical (unless you omit the body entirely); +various tools like `log`, `shortlog` and `rebase` can get confused +if you run the two together. + +Explain the problem that this commit is solving. Focus on why you +are making this change as opposed to how or what. The code explains +how or what. Reviewers and your future self can read the patch, +but might not understand why a particular solution was implemented. +Are there side effects or other unintuitive consequences of this +change? Here's the place to explain them. + + - Bullet points are awesome, too + + - A hyphen should be used for the bullet, preceded + by a single space, with blank lines in between + +Note the fixed or relevant GitHub issues at the end: + +Resolves: #123 +See also: #456, #789 +``` + +## :heart: Who Loves Emoji? + +Commit comments, Issues, Feature Requests... they can all use a little sprucing up, right? Consider using the following emoji for a mix of function and :sparkles: dazzle! + + - actions + - :seedling: `:seedling:` (or other plants) when growing new features. Choose your fav! :cactus: :herb: :evergreen_tree: :palm_tree: :deciduous_tree: :blossom: + - :art: `:art:` when improving the format/structure of the code + - :racehorse: `:racehorse:` when improving performance + - :non-potable_water: `:non-potable_water:` when plugging memory leaks + - :memo: `:memo:` when writing docs + - :bug: `:bug:` (or other insects) when fixing a bug. Maybe :beetle: :ant: or :honeybee: ? + - :fire: `:fire:` when removing code or files + - :green_heart: `:green_heart:` when fixing the CI build + - :white_check_mark: `:white_check_mark:` when adding tests + - :lock: `:lock:` when dealing with security + - :arrow_up: `:arrow_up:` when upgrading dependencies + - :arrow_down: `:arrow_down:` when downgrading dependencies + - :shirt: `:shirt:` when removing linter warnings + + - platforms + - :penguin: `:penguin:` when fixing something on Linux + - :apple: `:apple:` when fixing something on macOS + - :checkered_flag: `:checkered_flag:` when fixing something on Windows + +## :white_check_mark: Code Review + +- **Review the code, not the author.** Look for and suggest improvements without disparaging or insulting the author. Provide actionable feedback and explain your reasoning. + +- **You are not your code.** When your code is critiqued, questioned, or constructively criticized, remember that you are not your code. Do not take code review personally. + +- **Always do your best.** No one writes bugs on purpose. Do your best, and learn from your mistakes. + +- Kindly note any violations to the guidelines specified in this document. + +## :violin: Coding Style + +Consistency is the most important. Following the existing style, formatting, and naming conventions of the file you are modifying and of the overall project. Failure to do so will result in a prolonged review process that has to focus on updating the superficial aspects of your code, rather than improving its functionality and performance. + +For example, if all private properties are prefixed with an underscore `_`, then new ones you add should be prefixed in the same way. Or, if methods are named using camelcase, like `thisIsMyNewMethod`, then do not diverge from that by writing `this_is_my_new_method`. You get the idea. If in doubt, please ask or search the codebase for something similar. + +When possible, style and format will be enforced with a linter. + +### C Styleguide + +C code is linted with [AStyle](https://astyle.sourceforge.net/). + +### Ruby Styleguide + +Ruby code is linted with [Rubocop](https://github.com/rubocop/rubocop) + +## :medal_sports: Certificate of Origin + +*Developer's Certificate of Origin 1.1* + +By making a contribution to this project, I certify that: + +> 1. The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or +> 1. The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or +> 1. The contribution was provided directly to me by some other person who certified (1), (2) or (3) and I have not modified it. +> 1. I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. + +## [No Brown M&M's](https://en.wikipedia.org/wiki/Van_Halen#Contract_riders) + +If you are reading this, bravo dear user and (hopefully) contributor for making it this far! You are awesome. :100: + +To confirm that you have read this guide and are following it as best as possible, **include this emoji at the top** of your issue or pull request: :pineapple: `:pineapple:` + +## :pray: Credits + +Written by [@jessesquires](https://github.com/jessesquires). Lovingly adapted to ThrowTheSwitch.org by [@mvandervoord](https://github.com/mvandervoord). + +**Please feel free to adopt this guide in your own projects. Fork it wholesale or remix it for your needs.** + +*Many of the ideas and prose for the statements in this document were based on or inspired by work from the following communities:* + +- [Alamofire](https://github.com/Alamofire/Alamofire/blob/master/CONTRIBUTING.md) +- [CocoaPods](https://github.com/CocoaPods/CocoaPods/blob/master/CONTRIBUTING.md) +- [Docker](https://github.com/moby/moby/blob/master/CONTRIBUTING.md) +- [Linux](https://elinux.org/Developer_Certificate_Of_Origin) + +*We commend them for their efforts to facilitate collaboration in their projects.* diff --git a/src/subprojects/unity/docs/MesonGeneratorRunner.md b/src/subprojects/unity/docs/MesonGeneratorRunner.md new file mode 100644 index 00000000..3b81e378 --- /dev/null +++ b/src/subprojects/unity/docs/MesonGeneratorRunner.md @@ -0,0 +1,18 @@ +# Meson Generator - Test Runner + +One of the really nice things about using Unity with Ceedling is that Ceedling takes care of generating all of the test runners automatically. If you're not using Ceedling though, you'll need to do this yourself. + +The way this is done in Unity is via a Ruby script called `generate_test_runner.rb`. When given a test file such as `test_example.c`, the script will generate `test_example_Runner.c`, which provides the `main` method and some other useful plumbing. + +So that you don't have to run this by hand, a Meson generator is provided to generate the runner automatically for you. Generally with Meson, you would use Unity as a subproject and you'd want to access the generator from the parent. + +For example, to get the generator you can use: + + unity_proj = subproject('unity') + runner_gen = unity_proj.get_variable('gen_test_runner') + +Once you have the generator you need to pass it the absolute path of your test file. This seems to be a bug in how the paths work with subprojects in Meson. You can get the full path with `meson.source_root()`, so you could do: + + test_runner = meson.source_root() / 'test/test_example.c' + +You can then include `test_runner` as a normal dependency to your builds. Meson will create the test runner in a private directory for each build target. It's only meant to be used as part of the build, so if you need to refer to the runner after the build, you won't be able to use the generator. \ No newline at end of file diff --git a/src/subprojects/unity/docs/ThrowTheSwitchCodingStandard.md b/src/subprojects/unity/docs/ThrowTheSwitchCodingStandard.md new file mode 100644 index 00000000..517b8fb6 --- /dev/null +++ b/src/subprojects/unity/docs/ThrowTheSwitchCodingStandard.md @@ -0,0 +1,187 @@ +# ThrowTheSwitch.org Coding Standard + +Hi. +Welcome to the coding standard for ThrowTheSwitch.org. +For the most part, we try to follow these standards to unify our contributors' code into a cohesive unit (puns intended). +You might find places where these standards aren't followed. +We're not perfect. Please be polite where you notice these discrepancies and we'll try to be polite when we notice yours. + +;) + +## Why Have A Coding Standard? + +Being consistent makes code easier to understand. +We've tried to keep our standard simple because we also believe that we can only expect someone to follow something that is understandable. +Please do your best. + +## Our Philosophy + +Before we get into details on syntax, let's take a moment to talk about our vision for these tools. +We're C developers and embedded software developers. +These tools are great to test any C code, but catering to embedded software made us more tolerant of compiler quirks. +There are a LOT of quirky compilers out there. +By quirky I mean "doesn't follow standards because they feel like they have a license to do as they wish." + +Our philosophy is "support every compiler we can". +Most often, this means that we aim for writing C code that is standards compliant (often C89... that seems to be a sweet spot that is almost always compatible). +But it also means these tools are tolerant of things that aren't common. +Some that aren't even compliant. +There are configuration options to override the size of standard types. +There are configuration options to force Unity to not use certain standard library functions. +A lot of Unity is configurable and we have worked hard to make it not TOO ugly in the process. + +Similarly, our tools that parse C do their best. +They aren't full C parsers (yet) and, even if they were, they would still have to accept non-standard additions like gcc extensions or specifying `@0x1000` to force a variable to compile to a particular location. +It's just what we do, because we like everything to Just Work™. + +Speaking of having things Just Work™, that's our second philosophy. +By that, we mean that we do our best to have EVERY configuration option have a logical default. +We believe that if you're working with a simple compiler and target, you shouldn't need to configure very much... we try to make the tools guess as much as they can, but give the user the power to override it when it's wrong. + +## Naming Things + +Let's talk about naming things. +Programming is all about naming things. +We name files, functions, variables, and so much more. +While we're not always going to find the best name for something, we actually put a bit of effort into finding *What Something WANTS to be Called*™. + +When naming things, we follow this hierarchy, the first being the most important to us (but we do all four when possible): + +1. Readable +2. Descriptive +3. Consistent +4. Memorable + +### Readable + +We want to read our code. +This means we like names and flow that are more naturally read. +We try to avoid double negatives. +We try to avoid cryptic abbreviations (sticking to ones we feel are common). + +### Descriptive + +We like descriptive names for things, especially functions and variables. +Finding the right name for something is an important endeavour. +You might notice from poking around our code that this often results in names that are a little longer than the average. +Guilty. +We're okay with a bit more typing if it means our code is easier to understand. + +There are two exceptions to this rule that we also stick to as religiously as possible: + +First, while we realize hungarian notation (and similar systems for encoding type information into variable names) is providing a more descriptive name, we feel that (for the average developer) it takes away from readability and is to be avoided. + +Second, loop counters and other local throw-away variables often have a purpose which is obvious. +There's no need, therefore, to get carried away with complex naming. +We find i, j, and k are better loop counters than loopCounterVar or whatnot. +We only break this rule when we see that more description could improve understanding of an algorithm. + +### Consistent + +We like consistency, but we're not really obsessed with it. +We try to name our configuration macros in a consistent fashion... you'll notice a repeated use of UNITY_EXCLUDE_BLAH or UNITY_USES_BLAH macros. +This helps users avoid having to remember each macro's details. + +### Memorable + +Where ever it doesn't violate the above principles, we try to apply memorable names. +Sometimes this means using something that is simply descriptive, but often we strive for descriptive AND unique... we like quirky names that stand out in our memory and are easier to search for. +Take a look through the file names in Ceedling and you'll get a good idea of what we are talking about here. +Why use preprocess when you can use preprocessinator? +Or what better describes a module in charge of invoking tasks during releases than release_invoker? +Don't get carried away. +The names are still descriptive and fulfil the above requirements, but they don't feel stale. + +## C and C++ Details + +We don't really want to add to the style battles out there. +Tabs or spaces? +How many spaces? +Where do the braces go? +These are age-old questions that will never be answered... or at least not answered in a way that will make everyone happy. + +We've decided on our own style preferences. +If you'd like to contribute to these projects (and we hope that you do), then we ask if you do your best to follow the same. +It will only hurt a little. We promise. + +### Whitespace in C/C++ + +Our C-style is to use spaces and to use 4 of them per indent level. +It's a nice power-of-2 number that looks decent on a wide-screen. +We have no more reason than that. +We break that rule when we have lines that wrap (macros or function arguments or whatnot). +When that happens, we like to indent further to line things up in nice tidy columns. + +```C + if (stuff_happened) + { + do_something(); + } +``` + +### Case in C/C++ + +- Files - all lower case with underscores. +- Variables - all lower case with underscores +- Macros - all caps with underscores. +- Typedefs - all caps with underscores. (also ends with _T). +- Functions - camel cased. Usually named ModuleName_FuncName +- Constants and Globals - camel cased. + +### Braces in C/C++ + +The left brace is on the next line after the declaration. +The right brace is directly below that. +Everything in between in indented one level. +If you're catching an error and you have a one-line, go ahead and to it on the same line. + +```C + while (blah) + { + //Like so. Even if only one line, we use braces. + } +``` + +### Comments in C/C++ + +Do you know what we hate? +Old-school C block comments. +BUT, we're using them anyway. +As we mentioned, our goal is to support every compiler we can, especially embedded compilers. +There are STILL C compilers out there that only support old-school block comments. +So that is what we're using. +We apologize. +We think they are ugly too. + +## Ruby Details + +Is there really such thing as a Ruby coding standard? +Ruby is such a free form language, it seems almost sacrilegious to suggest that people should comply to one method! +We'll keep it really brief! + +### Whitespace in Ruby + +Our Ruby style is to use spaces and to use 2 of them per indent level. +It's a nice power-of-2 number that really grooves with Ruby's compact style. +We have no more reason than that. +We break that rule when we have lines that wrap. +When that happens, we like to indent further to line things up in nice tidy columns. + +### Case in Ruby + +- Files - all lower case with underscores. +- Variables - all lower case with underscores +- Classes, Modules, etc - Camel cased. +- Functions - all lower case with underscores +- Constants - all upper case with underscores + +## Documentation + +Egad. +Really? +We use markdown and we like PDF files because they can be made to look nice while still being portable. +Good enough? + +*Find The Latest of This And More at [ThrowTheSwitch.org][]* + +[ThrowTheSwitch.org]: https://throwtheswitch.org \ No newline at end of file diff --git a/src/subprojects/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf b/src/subprojects/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf new file mode 100644 index 0000000000000000000000000000000000000000..28f0c32144c4f2b55ff07007555e5777480320ac GIT binary patch literal 144467 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�G6f)G0Z<|?<~7vze(%ccPG)`yA`|sb~tX_zc~C& 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 z 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 z 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 ["stdio.h", "microdefs.h"], + :cexception => 1, + :suite_setup => "blah = malloc(1024);", + :suite_teardown => "free(blah);" +} +UnityTestRunnerGenerator.new.run(testfile, runner_name, options) +``` + +If you have multiple files to generate in a build script (such as a Rakefile), you might want to instantiate a generator object with your options and call it to generate each runner afterwards. +Like thus: + +```Ruby +gen = UnityTestRunnerGenerator.new(options) +test_files.each do |f| + gen.run(f, File.basename(f,'.c')+"Runner.c" +end +``` + +#### Options accepted by generate_test_runner.rb + +The following options are available when executing `generate_test_runner`. +You may pass these as a Ruby hash directly or specify them in a YAML file, both of which are described above. +In the `examples` directory, Example 3's Rakefile demonstrates using a Ruby hash. + +##### `:includes` + +This option specifies an array of file names to be `#include`'d at the top of your runner C file. +You might use it to reference custom types or anything else universally needed in your generated runners. + +##### `:defines` + +This option specifies an array of definitions to be `#define`'d at the top of your runner C file. +Each definition will be wrapped in an `#ifndef`. + +##### `:suite_setup` + +Define this option with C code to be executed _before any_ test cases are run. + +Alternatively, if your C compiler supports weak symbols, you can leave this option unset and instead provide a `void suiteSetUp(void)` function in your test suite. +The linker will look for this symbol and fall back to a Unity-provided stub if it is not found. + +This option can also be specified at the command prompt as `--suite_setup=""` + +##### `:suite_teardown` + +Define this option with C code to be executed _after all_ test cases have finished. +An integer variable `num_failures` is available for diagnostics. +The code should end with a `return` statement; the value returned will become the exit code of `main`. +You can normally just return `num_failures`. + +Alternatively, if your C compiler supports weak symbols, you can leave this option unset and instead provide a `int suiteTearDown(int num_failures)` function in your test suite. +The linker will look for this symbol and fall back to a Unity-provided stub if it is not found. + +This option can also be specified at the command prompt as `--suite_teardown=""` + +##### `:enforce_strict_ordering` + +This option should be defined if you have the strict order feature enabled in CMock (see CMock documentation). +This generates extra variables required for everything to run smoothly. +If you provide the same YAML to the generator as used in CMock's configuration, you've already configured the generator properly. + +##### `:externc` + +This option should be defined if you are mixing C and CPP and want your test runners to automatically include extern "C" support when they are generated. + +This option can also be specified at the command prompt as `--externc` + +##### `:mock_prefix` and `:mock_suffix` + +Unity automatically generates calls to Init, Verify and Destroy for every file included in the main test file that starts with the given mock prefix and ends with the given mock suffix, file extension not included. +By default, Unity assumes a `Mock` prefix and no suffix. + +##### `:plugins` + +This option specifies an array of plugins to be used (of course, the array can contain only a single plugin). +This is your opportunity to enable support for CException support, which will add a check for unhandled exceptions in each test, reporting a failure if one is detected. +To enable this feature using Ruby: + +```Ruby +:plugins => [ :cexception ] +``` + +Or as a yaml file: + +```YAML +:plugins: + -:cexception +``` + +If you are using CMock, it is very likely that you are already passing an array of plugins to CMock. +You can just use the same array here. + +This script will just ignore the plugins that don't require additional support. + +This option can also be specified at the command prompt as `--cexception` + +##### `:include_extensions` + +This option specifies the pattern for matching acceptable header file extensions. +By default it will accept hpp, hh, H, and h files. +If you need a different combination of files to search, update this from the default `'(?:hpp|hh|H|h)'`. + +##### `:source_extensions` + +This option specifies the pattern for matching acceptable source file extensions. +By default it will accept cpp, cc, C, c, and ino files. +If you need a different combination of files to search, update this from the default `'(?:cpp|cc|ino|C|c)'`. + +##### `:use_param_tests` + +This option enables parameterized test usage. +That tests accepts arguments from `TEST_CASE` and `TEST_RANGE` macros, +that are located above current test definition. +By default, Unity assumes, that parameterized tests are disabled. + +Few usage examples can be found in `/test/tests/test_unity_parameterized.c` file. + +You should define `UNITY_SUPPORT_TEST_CASES` macro for tests success compiling, +if you enable current option. + +You can see list of supported macros list in the +[Parameterized tests provided macros](#parameterized-tests-provided-macros) +section that follows. + +This option can also be specified at the command prompt as `--use_param_tests=1` + +##### `:cmdline_args` + +When set to `true`, the generated test runner can accept a number of +options to modify how the test(s) are run. + +Ensure Unity is compiled with `UNITY_USE_COMMAND_LINE_ARGS` defined or else +the required functions will not exist. + +These are the available options: + +| Option | Description | +| --------- | ------------------------------------------------- | +| `-l` | List all tests and exit | +| `-f NAME` | Filter to run only tests whose name includes NAME | +| `-n NAME` | Run only the test named NAME | +| `-h` | show the Help menu that lists these options | +| `-q` | Quiet/decrease verbosity | +| `-v` | increase Verbosity | +| `-x NAME` | eXclude tests whose name includes NAME | + +##### `:setup_name` + +Override the default test `setUp` function name. + +This option can also be specified at the command prompt as `--setup_name=""` + +##### `:teardown_name` + +Override the default test `tearDown` function name. + +This option can also be specified at the command prompt as `--teardown_name=""` + +##### `:test_reset_name` + +Override the default test `resetTest` function name. + +This option can also be specified at the command prompt as `--test_reset_name=""` + +##### `:test_verify_name` + +Override the default test `verifyTest` function name. + +This option can also be specified at the command prompt as `--test_verify_name=""` + +##### `:main_name` + +Override the test's `main()` function name (from `main` to whatever is specified). +The sentinel value `:auto` will use the test's filename with the `.c` extension removed prefixed +with `main_` as the "main" function. + +To clarify, if `:main_name == :auto` and the test filename is "test_my_project.c", then the +generated function name will be `main_test_my_project(int argc, char** argv)`. + +This option can also be specified at the command prompt as `--main_name=""` + +##### `main_export_decl` + +Provide any `cdecl` for the `main()` test function. Is empty by default. + +##### `:omit_begin_end` + +If `true`, the `UnityBegin` and `UnityEnd` function will not be called for +Unity test state setup and cleanup. + +This option can also be specified at the command prompt as `--omit_begin_end` + +#### Parameterized tests provided macros + +Unity provides support for few param tests generators, that can be combined +with each other. You must define test function as usual C function with usual +C arguments, and test generator will pass what you tell as a list of arguments. + +Let's show how all of them works on the following test function definitions: + +```C +/* Place your test generators here, usually one generator per one or few lines */ +void test_demoParamFunction(int a, int b, int c) +{ + TEST_ASSERT_GREATER_THAN_INT(a + b, c); +} +``` + +##### `TEST_CASE` + +Test case is a basic generator, that can be used for param testing. +One call of that macro will generate only one call for test function. +It can be used with different args, such as numbers, enums, strings, +global variables, another preprocessor defines. + +If we use replace comment before test function with the following code: + +```C +TEST_CASE(1, 2, 5) +TEST_CASE(10, 7, 20) +``` + +script will generate 2 test calls: + +```C +test_demoParamFunction(1, 2, 5); +test_demoParamFunction(10, 7, 20); +``` + +That calls will be wrapped with `setUp`, `tearDown` and other +usual Unity calls, as for independent unit tests. +The following output can be generated after test executable startup: + +```Log +tests/test_unity_parameterizedDemo.c:14:test_demoParamFunction(1, 2, 5):PASS +tests/test_unity_parameterizedDemo.c:14:test_demoParamFunction(10, 7, 20):PASS +``` + +##### `TEST_RANGE` + +Test range is an advanced generator. It single call can be converted to zero, +one or few `TEST_CASE` equivalent commands. + +That generator can be used for creating numeric ranges in decimal representation +only: integers & floating point numbers. It uses few formats for every parameter: + +1. `[start, stop, step]` is stop-inclusive format +2. `` is stop-exclusive formats + +Format providers 1 and 2 accept only three arguments: + +* `start` is start number +* `stop` is end number (can or cannot exists in result sequence for format 1, +will be always skipped for format 2) +* `step` is incrementing step: can be either positive or negative value. + +Let's use our `test_demoParamFunction` test for checking, what ranges +will be generated for our single `TEST_RANGE` row: + +```C +TEST_RANGE([3, 4, 1], [10, 5, -2], <30, 31, 1>) +``` + +Tests execution output will be similar to that text: + +```Log +tests/test_unity_parameterizedDemo.c:14:test_demoParamFunction(3, 10, 30):PASS +tests/test_unity_parameterizedDemo.c:14:test_demoParamFunction(3, 8, 30):PASS +tests/test_unity_parameterizedDemo.c:14:test_demoParamFunction(3, 6, 30):PASS +tests/test_unity_parameterizedDemo.c:14:test_demoParamFunction(4, 10, 30):PASS +tests/test_unity_parameterizedDemo.c:14:test_demoParamFunction(4, 8, 30):PASS +tests/test_unity_parameterizedDemo.c:14:test_demoParamFunction(4, 6, 30):PASS +``` + +As we can see: + +| Parameter | Format | Possible values | Total of values | Format number | +|---|---|---|---|---| +| `a` | `[3, 4, 1]` | `3`, `4` | 2 | Format 1 | +| `b` | `[10, 5, -2]` | `10`, `8`, `6` | 3 | Format 1, negative step, end number is not included | +| `c` | `<30, 31, 1>` | `30` | 1 | Format 2 | + +_Note_, that format 2 also supports negative step. + +We totally have 2 * 3 * 1 = 6 equal test cases, that can be written as following: + +```C +TEST_CASE(3, 10, 30) +TEST_CASE(3, 8, 30) +TEST_CASE(3, 6, 30) +TEST_CASE(4, 10, 30) +TEST_CASE(4, 8, 30) +TEST_CASE(4, 6, 30) +``` + +##### `TEST_MATRIX` + +Test matix is an advanced generator. It single call can be converted to zero, +one or few `TEST_CASE` equivalent commands. + +That generator will create tests for all cobinations of the provided list. Each argument has to be given as a list of one or more elements in the format `[, , ..., , ]`. + +All parameters supported by the `TEST_CASE` is supported as arguments: +- Numbers incl type specifiers e.g. `<1>`, `<1u>`, `<1l>`, `<2.3>`, or `<2.3f>` +- Strings incl string concatianion e.g. `<"string">`, or `<"partial" "string">` +- Chars e.g. `<'c'>` +- Enums e.g. `` +- Elements of arrays e.g. `` + +Let's use our `test_demoParamFunction` test for checking, what ranges +will be generated for our single `TEST_RANGE` row: + +```C +TEST_MATRIX([3, 4, 7], [10, 8, 2, 1],[30u, 20.0f]) +``` + +Tests execution output will be similar to that text: + +```Log +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 10, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 10, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 8, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 8, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 2, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 2, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 1, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(3, 1, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 10, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 10, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 8, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 8, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 2, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 2, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 1, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(4, 1, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 10, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 10, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 8, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 8, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 2, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 2, 20.0f):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 1, 30u):PASS +tests/test_unity_parameterizedDemo.c:18:test_demoParamFunction(7, 1, 20.0f):PASS +``` + +As we can see: + +| Parameter | Format | Count of values | +|---|---|---| +| `a` | `[3, 4, 7]` | 2 | +| `b` | `[10, 8, 2, 1]` | 4 | +| `c` | `[30u, 20.0f]` | 2 | + +We totally have 2 * 4 * 2 = 16 equal test cases, that can be written as following: + +```C +TEST_CASE(3, 10, 30u) +TEST_CASE(3, 10, 20.0f) +TEST_CASE(3, 8, 30u) +TEST_CASE(3, 8, 20.0f) +TEST_CASE(3, 2, 30u) +TEST_CASE(3, 2, 20.0f) +TEST_CASE(3, 1, 30u) +TEST_CASE(3, 1, 20.0f) +TEST_CASE(4, 10, 30u) +TEST_CASE(4, 10, 20.0f) +TEST_CASE(4, 8, 30u) +TEST_CASE(4, 8, 20.0f) +TEST_CASE(4, 2, 30u) +TEST_CASE(4, 2, 20.0f) +TEST_CASE(4, 1, 30u) +TEST_CASE(4, 1, 20.0f) +TEST_CASE(7, 10, 30u) +TEST_CASE(7, 10, 20.0f) +TEST_CASE(7, 8, 30u) +TEST_CASE(7, 8, 20.0f) +TEST_CASE(7, 2, 30u) +TEST_CASE(7, 2, 20.0f) +TEST_CASE(7, 1, 30u) +TEST_CASE(7, 1, 20.0f) +``` + +### `unity_test_summary.rb` + +A Unity test file contains one or more test case functions. +Each test case can pass, fail, or be ignored. +Each test file is run individually producing results for its collection of test cases. +A given project will almost certainly be composed of multiple test files. +Therefore, the suite of tests is comprised of one or more test cases spread across one or more test files. +This script aggregates individual test file results to generate a summary of all executed test cases. +The output includes how many tests were run, how many were ignored, and how many failed. In addition, the output includes a listing of which specific tests were ignored and failed. +A good example of the breadth and details of these results can be found in the `examples` directory. +Intentionally ignored and failing tests in this project generate corresponding entries in the summary report. + +If you're interested in other (prettier?) output formats, check into the [Ceedling][] build tool project that works with Unity and CMock and supports xunit-style xml as well as other goodies. + +This script assumes the existence of files ending with the extensions `.testpass` and `.testfail`. +The contents of these files includes the test results summary corresponding to each test file executed with the extension set according to the presence or absence of failures for that test file. +The script searches a specified path for these files, opens each one it finds, parses the results, and aggregates and prints a summary. +Calling it from the command line looks like this: + +```Shell +ruby unity_test_summary.rb build/test/ +``` + +You can optionally specify a root path as well. +This is really helpful when you are using relative paths in your tools' setup, but you want to pull the summary into an IDE like Eclipse for clickable shortcuts. + +```Shell +ruby unity_test_summary.rb build/test/ ~/projects/myproject/ +``` + +Or, if you're more of a Windows sort of person: + +```Shell +ruby unity_test_summary.rb build\teat\ C:\projects\myproject\ +``` + +When configured correctly, you'll see a final summary, like so: + +```Shell +-------------------------- +UNITY IGNORED TEST SUMMARY +-------------------------- +blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE + +------------------------- +UNITY FAILED TEST SUMMARY +------------------------- +blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0 +meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke" + +-------------------------- +OVERALL UNITY TEST SUMMARY +-------------------------- +45 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED +``` + +How convenient is that? + +*Find The Latest of This And More at [ThrowTheSwitch.org][]* + +[ruby-lang.org]: https://ruby-lang.org/ +[YAML]: http://www.yaml.org/ +[Ceedling]: http://www.throwtheswitch.org/ceedling +[ThrowTheSwitch.org]: https://throwtheswitch.org diff --git a/src/subprojects/unity/docs/UnityKnownIssues.md b/src/subprojects/unity/docs/UnityKnownIssues.md new file mode 100644 index 00000000..34493197 --- /dev/null +++ b/src/subprojects/unity/docs/UnityKnownIssues.md @@ -0,0 +1,13 @@ +# Unity Test - Known Issues + +## A Note + +This project will do its best to keep track of significant bugs that might effect your usage of this +project and its supporting scripts. A more detailed and up-to-date list for cutting edge Unity can +be found on our Github repository. + +## Issues + + - No built-in validation of no-return functions + - Incomplete support for Printf-style formatting + - Incomplete support for VarArgs diff --git a/src/subprojects/unity/examples/example_1/makefile b/src/subprojects/unity/examples/example_1/makefile new file mode 100644 index 00000000..9c97687e --- /dev/null +++ b/src/subprojects/unity/examples/example_1/makefile @@ -0,0 +1,73 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +#We try to detect the OS we are running on, and adjust commands as needed +ifeq ($(OS),Windows_NT) + ifeq ($(shell uname -s),) # not in a bash-like shell + CLEANUP = del /F /Q + MKDIR = mkdir + else # in a bash-like shell, like msys + CLEANUP = rm -f + MKDIR = mkdir -p + endif + TARGET_EXTENSION=.exe +else + CLEANUP = rm -f + MKDIR = mkdir -p + TARGET_EXTENSION=.out +endif + +C_COMPILER=gcc +ifeq ($(shell uname -s), Darwin) +C_COMPILER=clang +endif + +UNITY_ROOT=../.. + +CFLAGS=-std=c89 +CFLAGS += -Wall +CFLAGS += -Wextra +CFLAGS += -Wpointer-arith +CFLAGS += -Wcast-align +CFLAGS += -Wwrite-strings +CFLAGS += -Wswitch-default +CFLAGS += -Wunreachable-code +CFLAGS += -Winit-self +CFLAGS += -Wmissing-field-initializers +CFLAGS += -Wno-unknown-pragmas +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wundef +CFLAGS += -Wold-style-definition +#CFLAGS += -Wno-misleading-indentation + +TARGET_BASE1=test1 +TARGET_BASE2=test2 +TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION) +TARGET2 = $(TARGET_BASE2)$(TARGET_EXTENSION) +SRC_FILES1=$(UNITY_ROOT)/src/unity.c src/ProductionCode.c test/TestProductionCode.c test/test_runners/TestProductionCode_Runner.c +SRC_FILES2=$(UNITY_ROOT)/src/unity.c src/ProductionCode2.c test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c +INC_DIRS=-Isrc -I$(UNITY_ROOT)/src +SYMBOLS= + +all: clean default + +default: $(SRC_FILES1) $(SRC_FILES2) + $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1) + $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES2) -o $(TARGET2) + - ./$(TARGET1) + - ./$(TARGET2) + +test/test_runners/TestProductionCode_Runner.c: test/TestProductionCode.c + ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode.c test/test_runners/TestProductionCode_Runner.c +test/test_runners/TestProductionCode2_Runner.c: test/TestProductionCode2.c + ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/TestProductionCode2.c test/test_runners/TestProductionCode2_Runner.c + +clean: + $(CLEANUP) $(TARGET1) $(TARGET2) + +ci: CFLAGS += -Werror +ci: default diff --git a/src/subprojects/unity/examples/example_1/meson.build b/src/subprojects/unity/examples/example_1/meson.build new file mode 100644 index 00000000..645eeb99 --- /dev/null +++ b/src/subprojects/unity/examples/example_1/meson.build @@ -0,0 +1,48 @@ +project('Unity example', 'c', + license: 'MIT', + default_options: [ + 'c_std=c99', + 'warning_level=3', + ], + meson_version: '>= 0.49.0' +) + +unity_subproject = subproject('unity') +unity_dependency = unity_subproject.get_variable('unity_dep') +unity_gen_runner = unity_subproject.get_variable('gen_test_runner') + +src1 = files([ + 'src' / 'ProductionCode.c', + 'test' / 'TestProductionCode.c', +]) + +src2 = files([ + 'src' / 'ProductionCode2.c', + 'test' / 'TestProductionCode2.c', +]) + +inc = include_directories('src') + +test1 = executable('test1', + sources: [ + src1, + unity_gen_runner.process('test' / 'TestProductionCode.c') + ], + include_directories: [ inc ], + dependencies: [ unity_dependency ], +) + +test('test1', test1, + should_fail: true) + +test2 = executable('test2', + sources: [ + src2, + unity_gen_runner.process('test' / 'TestProductionCode2.c') + ], + include_directories: [ inc ], + dependencies: [ unity_dependency ], +) + +test('test2', test2) + diff --git a/src/subprojects/unity/examples/example_1/readme.txt b/src/subprojects/unity/examples/example_1/readme.txt new file mode 100644 index 00000000..ddddd369 --- /dev/null +++ b/src/subprojects/unity/examples/example_1/readme.txt @@ -0,0 +1,12 @@ +Example 1 +========= + +Close to the simplest possible example of Unity, using only basic features. + +Build and run with Make +--- +Just run `make`. + +Build and run with Meson +--- +Run `meson setup build` to create the build directory, and then `meson test -C build` to build and run the tests. diff --git a/src/subprojects/unity/examples/example_1/src/ProductionCode.c b/src/subprojects/unity/examples/example_1/src/ProductionCode.c new file mode 100644 index 00000000..8a52aff0 --- /dev/null +++ b/src/subprojects/unity/examples/example_1/src/ProductionCode.c @@ -0,0 +1,30 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode.h" + +int Counter = 0; +int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */ + +/* This function is supposed to search through NumbersToFind and find a particular number. + * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since + * NumbersToFind is indexed from 1. Unfortunately it's broken + * (and should therefore be caught by our tests) */ +int FindFunction_WhichIsBroken(int NumberToFind) +{ + int i = 0; + while (i < 8) /* Notice I should have been in braces */ + i++; + if (NumbersToFind[i] == NumberToFind) /* Yikes! I'm getting run after the loop finishes instead of during it! */ + return i; + return 0; +} + +int FunctionWhichReturnsLocalVariable(void) +{ + return Counter; +} diff --git a/src/subprojects/unity/examples/example_1/src/ProductionCode.h b/src/subprojects/unity/examples/example_1/src/ProductionCode.h new file mode 100644 index 00000000..d8929bfb --- /dev/null +++ b/src/subprojects/unity/examples/example_1/src/ProductionCode.h @@ -0,0 +1,9 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +int FindFunction_WhichIsBroken(int NumberToFind); +int FunctionWhichReturnsLocalVariable(void); diff --git a/src/subprojects/unity/examples/example_1/src/ProductionCode2.c b/src/subprojects/unity/examples/example_1/src/ProductionCode2.c new file mode 100644 index 00000000..ff8a537f --- /dev/null +++ b/src/subprojects/unity/examples/example_1/src/ProductionCode2.c @@ -0,0 +1,17 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode2.h" + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) +{ + (void)Poor; + (void)LittleFunction; + /* Since There Are No Tests Yet, This Function Could Be Empty For All We Know. + * Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget */ + return (char*)0; +} diff --git a/src/subprojects/unity/examples/example_1/src/ProductionCode2.h b/src/subprojects/unity/examples/example_1/src/ProductionCode2.h new file mode 100644 index 00000000..5204543f --- /dev/null +++ b/src/subprojects/unity/examples/example_1/src/ProductionCode2.h @@ -0,0 +1,8 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/src/subprojects/unity/examples/example_1/subprojects/unity.wrap b/src/subprojects/unity/examples/example_1/subprojects/unity.wrap new file mode 100644 index 00000000..6df241bd --- /dev/null +++ b/src/subprojects/unity/examples/example_1/subprojects/unity.wrap @@ -0,0 +1,3 @@ +[wrap-git] +url = https://github.com/ThrowTheSwitch/Unity.git +revision = head diff --git a/src/subprojects/unity/examples/example_1/test/TestProductionCode.c b/src/subprojects/unity/examples/example_1/test/TestProductionCode.c new file mode 100644 index 00000000..ceb6d8b5 --- /dev/null +++ b/src/subprojects/unity/examples/example_1/test/TestProductionCode.c @@ -0,0 +1,68 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode.h" +#include "unity.h" + +/* sometimes you may want to get at local data in a module. + * for example: If you plan to pass by reference, this could be useful + * however, it should often be avoided */ +extern int Counter; + +void setUp(void) +{ + /* This is run before EACH TEST */ + Counter = 0x5a5a; +} + +void tearDown(void) +{ +} + +void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void) +{ + /* All of these should pass */ + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(2)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); +} + +void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) +{ + /* You should see this line fail in your test summary */ + TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); + + /* Notice the rest of these didn't get a chance to run because the line above failed. + * Unit tests abort each test function on the first sign of trouble. + * Then NEXT test function runs as normal. */ + TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void) +{ + /* This should be true because setUp set this up for us before this test */ + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); + + /* This should be true because we can still change our answer */ + Counter = 0x1234; + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void) +{ + /* This should be true again because setup was rerun before this test (and after we changed it to 0x1234) */ + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void) +{ + /* Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell + * you what actually happened...which in this case was a failure to setup the initial condition. */ + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} diff --git a/src/subprojects/unity/examples/example_1/test/TestProductionCode2.c b/src/subprojects/unity/examples/example_1/test/TestProductionCode2.c new file mode 100644 index 00000000..32bbfdf0 --- /dev/null +++ b/src/subprojects/unity/examples/example_1/test/TestProductionCode2.c @@ -0,0 +1,37 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode2.h" +#include "unity.h" + +/* These should be ignored because they are commented out in various ways: +#include "whatever.h" +#include "somethingelse.h" +*/ + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_IgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); +} + +void test_AnotherIgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); +} + +void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void) +{ + TEST_IGNORE(); /* Like This */ +} diff --git a/src/subprojects/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c b/src/subprojects/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c new file mode 100644 index 00000000..cf72c219 --- /dev/null +++ b/src/subprojects/unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c @@ -0,0 +1,53 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT()) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "ProductionCode2.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_IgnoredTest(void); +extern void test_AnotherIgnoredTest(void); +extern void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("test/TestProductionCode2.c"); + RUN_TEST(test_IgnoredTest, 18); + RUN_TEST(test_AnotherIgnoredTest, 23); + RUN_TEST(test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented, 28); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c b/src/subprojects/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c new file mode 100644 index 00000000..3b49af74 --- /dev/null +++ b/src/subprojects/unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c @@ -0,0 +1,57 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT()) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "ProductionCode.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void); +extern void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("test/TestProductionCode.c"); + RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode, 20); + RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken, 30); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue, 41); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain, 51); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed, 57); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/examples/example_2/makefile b/src/subprojects/unity/examples/example_2/makefile new file mode 100644 index 00000000..c0b41852 --- /dev/null +++ b/src/subprojects/unity/examples/example_2/makefile @@ -0,0 +1,72 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +#We try to detect the OS we are running on, and adjust commands as needed +ifeq ($(OS),Windows_NT) + ifeq ($(shell uname -s),) # not in a bash-like shell + CLEANUP = del /F /Q + MKDIR = mkdir + else # in a bash-like shell, like msys + CLEANUP = rm -f + MKDIR = mkdir -p + endif + TARGET_EXTENSION=.exe +else + CLEANUP = rm -f + MKDIR = mkdir -p + TARGET_EXTENSION=.out +endif + +C_COMPILER=gcc +ifeq ($(shell uname -s), Darwin) +C_COMPILER=clang +endif + +UNITY_ROOT=../.. + +CFLAGS=-std=c99 +CFLAGS += -Wall +CFLAGS += -Wextra +CFLAGS += -Wpointer-arith +CFLAGS += -Wcast-align +CFLAGS += -Wwrite-strings +CFLAGS += -Wswitch-default +CFLAGS += -Wunreachable-code +CFLAGS += -Winit-self +CFLAGS += -Wmissing-field-initializers +CFLAGS += -Wno-unknown-pragmas +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wundef +CFLAGS += -Wold-style-definition +#CFLAGS += -Wno-misleading-indentation + +TARGET_BASE1=all_tests +TARGET1 = $(TARGET_BASE1)$(TARGET_EXTENSION) +SRC_FILES1=\ + $(UNITY_ROOT)/src/unity.c \ + $(UNITY_ROOT)/extras/fixture/src/unity_fixture.c \ + src/ProductionCode.c \ + src/ProductionCode2.c \ + test/TestProductionCode.c \ + test/TestProductionCode2.c \ + test/test_runners/TestProductionCode_Runner.c \ + test/test_runners/TestProductionCode2_Runner.c \ + test/test_runners/all_tests.c +INC_DIRS=-Isrc -I$(UNITY_ROOT)/src -I$(UNITY_ROOT)/extras/fixture/src +SYMBOLS=-DUNITY_FIXTURE_NO_EXTRAS + +all: clean default + +default: + $(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) -o $(TARGET1) + - ./$(TARGET1) -v + +clean: + $(CLEANUP) $(TARGET1) + +ci: CFLAGS += -Werror +ci: default diff --git a/src/subprojects/unity/examples/example_2/readme.txt b/src/subprojects/unity/examples/example_2/readme.txt new file mode 100644 index 00000000..f0fce657 --- /dev/null +++ b/src/subprojects/unity/examples/example_2/readme.txt @@ -0,0 +1,5 @@ +Example 2 +========= + +Same as the first example, but now using Unity's test fixture to group tests +together. Using the test fixture also makes writing test runners much easier. \ No newline at end of file diff --git a/src/subprojects/unity/examples/example_2/src/ProductionCode.c b/src/subprojects/unity/examples/example_2/src/ProductionCode.c new file mode 100644 index 00000000..b84c4276 --- /dev/null +++ b/src/subprojects/unity/examples/example_2/src/ProductionCode.c @@ -0,0 +1,30 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode.h" + +int Counter = 0; +int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0. + +// This function is supposed to search through NumbersToFind and find a particular number. +// If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since +// NumbersToFind is indexed from 1. Unfortunately it's broken +// (and should therefore be caught by our tests) +int FindFunction_WhichIsBroken(int NumberToFind) +{ + int i = 0; + while (i < 8) //Notice I should have been in braces + i++; + if (NumbersToFind[i] == NumberToFind) //Yikes! I'm getting run after the loop finishes instead of during it! + return i; + return 0; +} + +int FunctionWhichReturnsLocalVariable(void) +{ + return Counter; +} diff --git a/src/subprojects/unity/examples/example_2/src/ProductionCode.h b/src/subprojects/unity/examples/example_2/src/ProductionCode.h new file mode 100644 index 00000000..d8929bfb --- /dev/null +++ b/src/subprojects/unity/examples/example_2/src/ProductionCode.h @@ -0,0 +1,9 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +int FindFunction_WhichIsBroken(int NumberToFind); +int FunctionWhichReturnsLocalVariable(void); diff --git a/src/subprojects/unity/examples/example_2/src/ProductionCode2.c b/src/subprojects/unity/examples/example_2/src/ProductionCode2.c new file mode 100644 index 00000000..80040187 --- /dev/null +++ b/src/subprojects/unity/examples/example_2/src/ProductionCode2.c @@ -0,0 +1,17 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode2.h" + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) +{ + (void)Poor; + (void)LittleFunction; + //Since There Are No Tests Yet, This Function Could Be Empty For All We Know. + // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget + return (char*)0; +} diff --git a/src/subprojects/unity/examples/example_2/src/ProductionCode2.h b/src/subprojects/unity/examples/example_2/src/ProductionCode2.h new file mode 100644 index 00000000..5204543f --- /dev/null +++ b/src/subprojects/unity/examples/example_2/src/ProductionCode2.h @@ -0,0 +1,8 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/src/subprojects/unity/examples/example_2/test/TestProductionCode.c b/src/subprojects/unity/examples/example_2/test/TestProductionCode.c new file mode 100644 index 00000000..9635f32a --- /dev/null +++ b/src/subprojects/unity/examples/example_2/test/TestProductionCode.c @@ -0,0 +1,71 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode.h" +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP(ProductionCode); + +//sometimes you may want to get at local data in a module. +//for example: If you plan to pass by reference, this could be useful +//however, it should often be avoided +extern int Counter; + +TEST_SETUP(ProductionCode) +{ + //This is run before EACH TEST + Counter = 0x5a5a; +} + +TEST_TEAR_DOWN(ProductionCode) +{ +} + +TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode) +{ + //All of these should pass + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(2)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); +} + +TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken) +{ + // You should see this line fail in your test summary + TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); + + // Notice the rest of these didn't get a chance to run because the line above failed. + // Unit tests abort each test function on the first sign of trouble. + // Then NEXT test function runs as normal. + TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); +} + +TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue) +{ + //This should be true because setUp set this up for us before this test + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); + + //This should be true because we can still change our answer + Counter = 0x1234; + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} + +TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain) +{ + //This should be true again because setup was rerun before this test (and after we changed it to 0x1234) + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); +} + +TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed) +{ + //Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell + // you what actually happened...which in this case was a failure to setup the initial condition. + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} diff --git a/src/subprojects/unity/examples/example_2/test/TestProductionCode2.c b/src/subprojects/unity/examples/example_2/test/TestProductionCode2.c new file mode 100644 index 00000000..d0233c0a --- /dev/null +++ b/src/subprojects/unity/examples/example_2/test/TestProductionCode2.c @@ -0,0 +1,40 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode2.h" +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP(ProductionCode2); + +/* These should be ignored because they are commented out in various ways: +#include "whatever.h" +*/ +//#include "somethingelse.h" + +TEST_SETUP(ProductionCode2) +{ +} + +TEST_TEAR_DOWN(ProductionCode2) +{ +} + +TEST(ProductionCode2, IgnoredTest) +{ + TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); +} + +TEST(ProductionCode2, AnotherIgnoredTest) +{ + TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); +} + +TEST(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented) +{ + TEST_IGNORE(); //Like This +} diff --git a/src/subprojects/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c b/src/subprojects/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c new file mode 100644 index 00000000..eaa057fd --- /dev/null +++ b/src/subprojects/unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c @@ -0,0 +1,16 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP_RUNNER(ProductionCode2) +{ + RUN_TEST_CASE(ProductionCode2, IgnoredTest); + RUN_TEST_CASE(ProductionCode2, AnotherIgnoredTest); + RUN_TEST_CASE(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented); +} \ No newline at end of file diff --git a/src/subprojects/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c b/src/subprojects/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c new file mode 100644 index 00000000..f0acf24f --- /dev/null +++ b/src/subprojects/unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c @@ -0,0 +1,18 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP_RUNNER(ProductionCode) +{ + RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode); + RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken); + RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue); + RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain); + RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed); +} \ No newline at end of file diff --git a/src/subprojects/unity/examples/example_2/test/test_runners/all_tests.c b/src/subprojects/unity/examples/example_2/test/test_runners/all_tests.c new file mode 100644 index 00000000..5376dbe2 --- /dev/null +++ b/src/subprojects/unity/examples/example_2/test/test_runners/all_tests.c @@ -0,0 +1,19 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity_fixture.h" + +static void RunAllTests(void) +{ + RUN_TEST_GROUP(ProductionCode); + RUN_TEST_GROUP(ProductionCode2); +} + +int main(int argc, const char * argv[]) +{ + return UnityMain(argc, argv, RunAllTests); +} diff --git a/src/subprojects/unity/examples/example_3/helper/UnityHelper.c b/src/subprojects/unity/examples/example_3/helper/UnityHelper.c new file mode 100644 index 00000000..17830959 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/helper/UnityHelper.c @@ -0,0 +1,17 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "UnityHelper.h" +#include +#include + +void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line) +{ + UNITY_TEST_ASSERT_EQUAL_INT(expected.x, actual.x, line, "Example Struct Failed For Field x"); + UNITY_TEST_ASSERT_EQUAL_INT(expected.y, actual.y, line, "Example Struct Failed For Field y"); +} diff --git a/src/subprojects/unity/examples/example_3/helper/UnityHelper.h b/src/subprojects/unity/examples/example_3/helper/UnityHelper.h new file mode 100644 index 00000000..6ebf8604 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/helper/UnityHelper.h @@ -0,0 +1,19 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef _TESTHELPER_H +#define _TESTHELPER_H + +#include "Types.h" + +void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line); + +#define UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, line, message) AssertEqualExampleStruct(expected, actual, line); + +#define TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual) UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, __LINE__, NULL); + +#endif // _TESTHELPER_H diff --git a/src/subprojects/unity/examples/example_3/rakefile.rb b/src/subprojects/unity/examples/example_3/rakefile.rb new file mode 100644 index 00000000..a1eb35a4 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/rakefile.rb @@ -0,0 +1,45 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require 'rake' +require 'rake/clean' +require_relative 'rakefile_helper' + +TEMP_DIRS = [ + File.join(__dir__, 'build') +].freeze + +TEMP_DIRS.each do |dir| + directory(dir) + CLOBBER.include(dir) +end + +task prepare_for_tests: TEMP_DIRS + +# Load default configuration, for now +DEFAULT_CONFIG_FILE = 'target_gcc_32.yml'.freeze +configure_toolchain(DEFAULT_CONFIG_FILE) + +task unit: [:prepare_for_tests] do + run_tests unit_test_files +end + +desc 'Generate test summary' +task :summary do + report_summary +end + +desc 'Build and test Unity' +task all: %i[clean unit summary] +task default: %i[clobber all] +task ci: [:default] +task cruise: [:default] + +desc 'Load configuration' +task :config, :config_file do |_t, args| + configure_toolchain(args[:config_file]) +end diff --git a/src/subprojects/unity/examples/example_3/rakefile_helper.rb b/src/subprojects/unity/examples/example_3/rakefile_helper.rb new file mode 100644 index 00000000..55885741 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/rakefile_helper.rb @@ -0,0 +1,255 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require 'fileutils' +require_relative '../../auto/unity_test_summary' +require_relative '../../auto/generate_test_runner' +require_relative '../../auto/colour_reporter' +require_relative '../../auto/yaml_helper' +C_EXTENSION = '.c'.freeze + +def load_configuration(config_file) + $cfg_file = config_file + $cfg = YamlHelper.load_file($cfg_file) +end + +def configure_clean + CLEAN.include("#{$cfg['compiler']['build_path']}*.*") unless $cfg['compiler']['build_path'].nil? +end + +def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) + config_file += '.yml' unless config_file =~ /\.yml$/ + load_configuration(config_file) + configure_clean +end + +def unit_test_files + path = "#{$cfg['compiler']['unit_tests_path']}Test*#{C_EXTENSION}" + path.tr!('\\', '/') + FileList.new(path) +end + +def local_include_dirs + include_dirs = $cfg['compiler']['includes']['items'].dup + include_dirs.delete_if { |dir| dir.is_a?(Array) } + include_dirs +end + +def extract_headers(filename) + includes = [] + lines = File.readlines(filename) + lines.each do |line| + m = line.match(/^\s*#include\s+"\s*(.+\.[hH])\s*"/) + includes << m[1] unless m.nil? + end + includes +end + +def find_source_file(header, paths) + paths.each do |dir| + src_file = dir + header.ext(C_EXTENSION) + return src_file if File.exist?(src_file) + end + nil +end + +def tackit(strings) + if strings.is_a?(Array) + "\"#{strings.join}\"" + else + strings + end +end + +def squash(prefix, items) + result = '' + items.each { |item| result += " #{prefix}#{tackit(item)}" } + result +end + +def build_compiler_fields + command = tackit($cfg['compiler']['path']) + defines = if $cfg['compiler']['defines']['items'].nil? + '' + else + squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items']) + end + options = squash('', $cfg['compiler']['options']) + includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) + includes = includes.gsub(/\\ /, ' ').gsub(/\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + + { command: command, defines: defines, options: options, includes: includes } +end + +def compile(file, _defines = []) + compiler = build_compiler_fields + cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \ + "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" + obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" + execute(cmd_str + obj_file) + obj_file +end + +def build_linker_fields + command = tackit($cfg['linker']['path']) + options = if $cfg['linker']['options'].nil? + '' + else + squash('', $cfg['linker']['options']) + end + includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil? + '' + else + squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) + end.gsub(/\\ /, ' ').gsub(/\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + + { command: command, options: options, includes: includes } +end + +def link_it(exe_name, obj_list) + linker = build_linker_fields + cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]}" + cmd_str += " #{(obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj}" }).join(' ')}" + cmd_str += " #{$cfg['linker']['bin_files']['prefix']} " + cmd_str += $cfg['linker']['bin_files']['destination'] + cmd_str += exe_name + $cfg['linker']['bin_files']['extension'] + execute(cmd_str) +end + +def build_simulator_fields + return nil if $cfg['simulator'].nil? + + command = if $cfg['simulator']['path'].nil? + '' + else + "#{tackit($cfg['simulator']['path'])} " + end + pre_support = if $cfg['simulator']['pre_support'].nil? + '' + else + squash('', $cfg['simulator']['pre_support']) + end + post_support = if $cfg['simulator']['post_support'].nil? + '' + else + squash('', $cfg['simulator']['post_support']) + end + + { command: command, pre_support: pre_support, post_support: post_support } +end + +def execute(command_string, verbose = true, raise_on_fail = true) + report command_string + output = `#{command_string}`.chomp + report(output) if verbose && !output.nil? && !output.empty? + + if !$?.nil? && !$?.exitstatus.zero? && raise_on_fail + raise "Command failed. (Returned #{$?.exitstatus})" + end + + output +end + +def report_summary + summary = UnityTestSummary.new + summary.root = __dir__ + results_glob = "#{$cfg['compiler']['build_path']}*.test*" + results_glob.tr!('\\', '/') + results = Dir[results_glob] + summary.targets = results + summary.run + fail_out 'FAIL: There were failures' if summary.failures > 0 +end + +def run_tests(test_files) + report 'Running system tests...' + + # Tack on TEST define for compiling unit tests + load_configuration($cfg_file) + test_defines = ['TEST'] + $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? + $cfg['compiler']['defines']['items'] << 'TEST' + + include_dirs = local_include_dirs + + # Build and execute each unit test + test_files.each do |test| + obj_list = [] + + # Detect dependencies and build required required modules + extract_headers(test).each do |header| + # Compile corresponding source file if it exists + src_file = find_source_file(header, include_dirs) + obj_list << compile(src_file, test_defines) unless src_file.nil? + end + + # Build the test runner (generate if configured to do so) + test_base = File.basename(test, C_EXTENSION) + runner_name = "#{test_base}_Runner.c" + if $cfg['compiler']['runner_path'].nil? + runner_path = $cfg['compiler']['build_path'] + runner_name + test_gen = UnityTestRunnerGenerator.new($cfg_file) + test_gen.run(test, runner_path) + else + runner_path = $cfg['compiler']['runner_path'] + runner_name + end + + obj_list << compile(runner_path, test_defines) + + # Build the test module + obj_list << compile(test, test_defines) + + # Link the test executable + link_it(test_base, obj_list) + + # Execute unit test and generate results file + simulator = build_simulator_fields + executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] + cmd_str = if simulator.nil? + executable + else + "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" + end + output = execute(cmd_str, true, false) + test_results = $cfg['compiler']['build_path'] + test_base + test_results += if output.match(/OK$/m).nil? + '.testfail' + else + '.testpass' + end + File.open(test_results, 'w') { |f| f.print output } + end +end + +def build_application(main) + report 'Building application...' + + obj_list = [] + load_configuration($cfg_file) + main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION + + # Detect dependencies and build required required modules + include_dirs = get_local_include_dirs + extract_headers(main_path).each do |header| + src_file = find_source_file(header, include_dirs) + obj_list << compile(src_file) unless src_file.nil? + end + + # Build the main source file + main_base = File.basename(main_path, C_EXTENSION) + obj_list << compile(main_path) + + # Create the executable + link_it(main_base, obj_list) +end + +def fail_out(msg) + puts msg + puts 'Not returning exit code so continuous integration can pass' + # exit(-1) # Only removed to pass example_3, which has failing tests on purpose. + # Still fail if the build fails for any other reason. +end diff --git a/src/subprojects/unity/examples/example_3/readme.txt b/src/subprojects/unity/examples/example_3/readme.txt new file mode 100644 index 00000000..7371fea0 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/readme.txt @@ -0,0 +1,13 @@ +Example 3 +========= + +This example project gives an example of some passing, ignored, and failing tests. +It's simple and meant for you to look over and get an idea for what all of this stuff does. + +You can build and test using rake. The rake version will let you test with gcc or a couple +versions of IAR. You can tweak the yaml files to get those versions running. + +Ruby is required if you're using the rake version (obviously). This version shows off most of +Unity's advanced features (automatically creating test runners, fancy summaries, etc.) +Without ruby, you have to maintain your own test runners. Do that for a while and you'll learn +why you really want to start using the Ruby tools. diff --git a/src/subprojects/unity/examples/example_3/src/ProductionCode.c b/src/subprojects/unity/examples/example_3/src/ProductionCode.c new file mode 100644 index 00000000..b84c4276 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/src/ProductionCode.c @@ -0,0 +1,30 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode.h" + +int Counter = 0; +int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0. + +// This function is supposed to search through NumbersToFind and find a particular number. +// If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since +// NumbersToFind is indexed from 1. Unfortunately it's broken +// (and should therefore be caught by our tests) +int FindFunction_WhichIsBroken(int NumberToFind) +{ + int i = 0; + while (i < 8) //Notice I should have been in braces + i++; + if (NumbersToFind[i] == NumberToFind) //Yikes! I'm getting run after the loop finishes instead of during it! + return i; + return 0; +} + +int FunctionWhichReturnsLocalVariable(void) +{ + return Counter; +} diff --git a/src/subprojects/unity/examples/example_3/src/ProductionCode.h b/src/subprojects/unity/examples/example_3/src/ProductionCode.h new file mode 100644 index 00000000..d8929bfb --- /dev/null +++ b/src/subprojects/unity/examples/example_3/src/ProductionCode.h @@ -0,0 +1,9 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +int FindFunction_WhichIsBroken(int NumberToFind); +int FunctionWhichReturnsLocalVariable(void); diff --git a/src/subprojects/unity/examples/example_3/src/ProductionCode2.c b/src/subprojects/unity/examples/example_3/src/ProductionCode2.c new file mode 100644 index 00000000..80040187 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/src/ProductionCode2.c @@ -0,0 +1,17 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode2.h" + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) +{ + (void)Poor; + (void)LittleFunction; + //Since There Are No Tests Yet, This Function Could Be Empty For All We Know. + // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget + return (char*)0; +} diff --git a/src/subprojects/unity/examples/example_3/src/ProductionCode2.h b/src/subprojects/unity/examples/example_3/src/ProductionCode2.h new file mode 100644 index 00000000..5204543f --- /dev/null +++ b/src/subprojects/unity/examples/example_3/src/ProductionCode2.h @@ -0,0 +1,8 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/src/subprojects/unity/examples/example_3/target_gcc_32.yml b/src/subprojects/unity/examples/example_3/target_gcc_32.yml new file mode 100644 index 00000000..a3d123d4 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/target_gcc_32.yml @@ -0,0 +1,54 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +# Copied from ~Unity/targets/gcc_32.yml +unity_root: &unity_root '../..' +unity_source: &unity_source '../../src/' +compiler: + path: gcc + source_path: &source_path 'src/' + unit_tests_path: &unit_tests_path 'test/' + build_path: &build_path 'build/' + options: + - '-c' + - '-m32' + - '-Wall' + - '-Wno-address' + - '-std=c99' + - '-pedantic' + includes: + prefix: '-I' + items: + - *source_path + - *unity_source + - *unit_tests_path + defines: + prefix: '-D' + items: + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + object_files: + prefix: '-o' + extension: '.o' + destination: *build_path +linker: + path: gcc + options: + - -lm + - '-m32' + includes: + prefix: '-I' + object_files: + path: *build_path + extension: '.o' + bin_files: + prefix: '-o' + extension: '.exe' + destination: *build_path +colour: true +:unity: + :plugins: [] diff --git a/src/subprojects/unity/examples/example_3/test/TestProductionCode.c b/src/subprojects/unity/examples/example_3/test/TestProductionCode.c new file mode 100644 index 00000000..7f48ea76 --- /dev/null +++ b/src/subprojects/unity/examples/example_3/test/TestProductionCode.c @@ -0,0 +1,68 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode.h" +#include "unity.h" + +//sometimes you may want to get at local data in a module. +//for example: If you plan to pass by reference, this could be useful +//however, it should often be avoided +extern int Counter; + +void setUp(void) +{ + //This is run before EACH TEST + Counter = 0x5a5a; +} + +void tearDown(void) +{ +} + +void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void) +{ + //All of these should pass + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); +} + +void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) +{ + // You should see this line fail in your test summary + TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); + + // Notice the rest of these didn't get a chance to run because the line above failed. + // Unit tests abort each test function on the first sign of trouble. + // Then NEXT test function runs as normal. + TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void) +{ + //This should be true because setUp set this up for us before this test + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); + + //This should be true because we can still change our answer + Counter = 0x1234; + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void) +{ + //This should be true again because setup was rerun before this test (and after we changed it to 0x1234) + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void) +{ + //Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell + // you what actually happened...which in this case was a failure to setup the initial condition. + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} diff --git a/src/subprojects/unity/examples/example_3/test/TestProductionCode2.c b/src/subprojects/unity/examples/example_3/test/TestProductionCode2.c new file mode 100644 index 00000000..7ab3926e --- /dev/null +++ b/src/subprojects/unity/examples/example_3/test/TestProductionCode2.c @@ -0,0 +1,37 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode2.h" +#include "unity.h" + +/* These should be ignored because they are commented out in various ways: +#include "whatever.h" +*/ +//#include "somethingelse.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_IgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); +} + +void test_AnotherIgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); +} + +void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void) +{ + TEST_IGNORE(); //Like This +} diff --git a/src/subprojects/unity/examples/example_4/meson.build b/src/subprojects/unity/examples/example_4/meson.build new file mode 100644 index 00000000..b1c4e852 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/meson.build @@ -0,0 +1,12 @@ +# +# build script written by : Michael Brockus. +# github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams. +# +# license: MIT +# +project('example-4', 'c', meson_version: '>= 0.55.0') + +unity_dep = dependency('unity') + +subdir('src') +subdir('test') diff --git a/src/subprojects/unity/examples/example_4/readme.txt b/src/subprojects/unity/examples/example_4/readme.txt new file mode 100644 index 00000000..c8f45a81 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/readme.txt @@ -0,0 +1,15 @@ +Example 4 +========= + +Close to the simplest possible example of Unity, using only basic features. +to build this example run "meson setup ". + +Meson uses the Ninja build system to actually build the code. To start the +build, simply type the following command. + +"ninja -C " + +Meson provides native support for running tests. The command to do that is simple. + +"meson test -C ". + \ No newline at end of file diff --git a/src/subprojects/unity/examples/example_4/src/ProductionCode.c b/src/subprojects/unity/examples/example_4/src/ProductionCode.c new file mode 100644 index 00000000..8a52aff0 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/src/ProductionCode.c @@ -0,0 +1,30 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode.h" + +int Counter = 0; +int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */ + +/* This function is supposed to search through NumbersToFind and find a particular number. + * If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since + * NumbersToFind is indexed from 1. Unfortunately it's broken + * (and should therefore be caught by our tests) */ +int FindFunction_WhichIsBroken(int NumberToFind) +{ + int i = 0; + while (i < 8) /* Notice I should have been in braces */ + i++; + if (NumbersToFind[i] == NumberToFind) /* Yikes! I'm getting run after the loop finishes instead of during it! */ + return i; + return 0; +} + +int FunctionWhichReturnsLocalVariable(void) +{ + return Counter; +} diff --git a/src/subprojects/unity/examples/example_4/src/ProductionCode.h b/src/subprojects/unity/examples/example_4/src/ProductionCode.h new file mode 100644 index 00000000..d8929bfb --- /dev/null +++ b/src/subprojects/unity/examples/example_4/src/ProductionCode.h @@ -0,0 +1,9 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +int FindFunction_WhichIsBroken(int NumberToFind); +int FunctionWhichReturnsLocalVariable(void); diff --git a/src/subprojects/unity/examples/example_4/src/ProductionCode2.c b/src/subprojects/unity/examples/example_4/src/ProductionCode2.c new file mode 100644 index 00000000..ff8a537f --- /dev/null +++ b/src/subprojects/unity/examples/example_4/src/ProductionCode2.c @@ -0,0 +1,17 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode2.h" + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction) +{ + (void)Poor; + (void)LittleFunction; + /* Since There Are No Tests Yet, This Function Could Be Empty For All We Know. + * Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget */ + return (char*)0; +} diff --git a/src/subprojects/unity/examples/example_4/src/ProductionCode2.h b/src/subprojects/unity/examples/example_4/src/ProductionCode2.h new file mode 100644 index 00000000..5204543f --- /dev/null +++ b/src/subprojects/unity/examples/example_4/src/ProductionCode2.h @@ -0,0 +1,8 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction); diff --git a/src/subprojects/unity/examples/example_4/src/meson.build b/src/subprojects/unity/examples/example_4/src/meson.build new file mode 100644 index 00000000..10c5735b --- /dev/null +++ b/src/subprojects/unity/examples/example_4/src/meson.build @@ -0,0 +1,16 @@ +# +# build script written by : Michael Brockus. +# github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams. +# +# license: MIT +# +inc_dir = include_directories('.') +lib_list = {'a': ['ProductionCode.c' ], 'b': ['ProductionCode2.c']} + +foreach lib, src : lib_list + set_variable(lib + '_lib', + static_library(lib + '_lib', sources: src, include_directories: inc_dir)) +endforeach + +a_dep = declare_dependency(link_with: a_lib, include_directories: inc_dir) +b_dep = declare_dependency(link_with: b_lib, include_directories: inc_dir) diff --git a/src/subprojects/unity/examples/example_4/subprojects/unity.wrap b/src/subprojects/unity/examples/example_4/subprojects/unity.wrap new file mode 100755 index 00000000..8688475d --- /dev/null +++ b/src/subprojects/unity/examples/example_4/subprojects/unity.wrap @@ -0,0 +1,6 @@ +[wrap-git] +url = https://github.com/ThrowTheSwitch/Unity.git +revision = head + +[provide] +unity = unity_dep diff --git a/src/subprojects/unity/examples/example_4/test/TestProductionCode.c b/src/subprojects/unity/examples/example_4/test/TestProductionCode.c new file mode 100644 index 00000000..a7cf1449 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/test/TestProductionCode.c @@ -0,0 +1,69 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode.h" +#include "unity.h" + +/* sometimes you may want to get at local data in a module. + * for example: If you plan to pass by reference, this could be useful + * however, it should often be avoided */ +extern int Counter; + +void setUp(void) +{ + /* This is run before EACH TEST */ + Counter = 0x5a5a; +} + +void tearDown(void) +{ +} + + +void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void) +{ + /* All of these should pass */ + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(2)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999)); + TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1)); +} + +void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void) +{ + /* You should see this line fail in your test summary */ + TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34)); + + /* Notice the rest of these didn't get a chance to run because the line above failed. + * Unit tests abort each test function on the first sign of trouble. + * Then NEXT test function runs as normal. */ + TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888)); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void) +{ + /* This should be true because setUp set this up for us before this test */ + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); + + /* This should be true because we can still change our answer */ + Counter = 0x1234; + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void) +{ + /* This should be true again because setup was rerun before this test (and after we changed it to 0x1234) */ + TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable()); +} + +void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void) +{ + /* Sometimes you get the test wrong. When that happens, you get a failure too... and a quick look should tell + * you what actually happened...which in this case was a failure to setup the initial condition. */ + TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable()); +} diff --git a/src/subprojects/unity/examples/example_4/test/TestProductionCode2.c b/src/subprojects/unity/examples/example_4/test/TestProductionCode2.c new file mode 100644 index 00000000..168564e1 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/test/TestProductionCode2.c @@ -0,0 +1,41 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "ProductionCode2.h" +#include "unity.h" + +/* These should be ignored because they are commented out in various ways: +#include "whatever.h" +#include "somethingelse.h" +*/ + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_IgnoredTest(void); +void test_AnotherIgnoredTest(void); +void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void); + +void test_IgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose"); +} + +void test_AnotherIgnoredTest(void) +{ + TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet"); +} + +void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void) +{ + TEST_IGNORE(); /* Like This */ +} diff --git a/src/subprojects/unity/examples/example_4/test/meson.build b/src/subprojects/unity/examples/example_4/test/meson.build new file mode 100644 index 00000000..0e3c72f5 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/test/meson.build @@ -0,0 +1,7 @@ +# +# build script written by : Michael Brockus. +# github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams. +# +# license: MIT +# +subdir('test_runners') diff --git a/src/subprojects/unity/examples/example_4/test/test_runners/TestProductionCode2_Runner.c b/src/subprojects/unity/examples/example_4/test/test_runners/TestProductionCode2_Runner.c new file mode 100644 index 00000000..cf72c219 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/test/test_runners/TestProductionCode2_Runner.c @@ -0,0 +1,53 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT()) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "ProductionCode2.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_IgnoredTest(void); +extern void test_AnotherIgnoredTest(void); +extern void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("test/TestProductionCode2.c"); + RUN_TEST(test_IgnoredTest, 18); + RUN_TEST(test_AnotherIgnoredTest, 23); + RUN_TEST(test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented, 28); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/examples/example_4/test/test_runners/TestProductionCode_Runner.c b/src/subprojects/unity/examples/example_4/test/test_runners/TestProductionCode_Runner.c new file mode 100644 index 00000000..3b49af74 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/test/test_runners/TestProductionCode_Runner.c @@ -0,0 +1,57 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT()) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "ProductionCode.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void); +extern void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void); +extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("test/TestProductionCode.c"); + RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode, 20); + RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken, 30); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue, 41); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain, 51); + RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed, 57); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/examples/example_4/test/test_runners/meson.build b/src/subprojects/unity/examples/example_4/test/test_runners/meson.build new file mode 100644 index 00000000..1503c5f3 --- /dev/null +++ b/src/subprojects/unity/examples/example_4/test/test_runners/meson.build @@ -0,0 +1,13 @@ +# +# build script written by : Michael Brockus. +# github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams. +# +# license: MIT +# +cases = [ + ['TestProductionCode_Runner.c', join_paths('..' ,'TestProductionCode.c' )], + ['TestProductionCode2_Runner.c', join_paths('..' ,'TestProductionCode2.c')] + ] + +test('01-test-case', executable('01-test-case', cases[0], dependencies: [ a_dep, unity_dep ])) +test('02-test-case', executable('02-test-case', cases[1], dependencies: [ b_dep, unity_dep ])) diff --git a/src/subprojects/unity/examples/unity_config.h b/src/subprojects/unity/examples/unity_config.h new file mode 100644 index 00000000..efd91232 --- /dev/null +++ b/src/subprojects/unity/examples/unity_config.h @@ -0,0 +1,251 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +/* Unity Configuration + * As of May 11th, 2016 at ThrowTheSwitch/Unity commit 837c529 + * Update: December 29th, 2016 + * See Also: Unity/docs/UnityConfigurationGuide.pdf + * + * Unity is designed to run on almost anything that is targeted by a C compiler. + * It would be awesome if this could be done with zero configuration. While + * there are some targets that come close to this dream, it is sadly not + * universal. It is likely that you are going to need at least a couple of the + * configuration options described in this document. + * + * All of Unity's configuration options are `#defines`. Most of these are simple + * definitions. A couple are macros with arguments. They live inside the + * unity_internals.h header file. We don't necessarily recommend opening that + * file unless you really need to. That file is proof that a cross-platform + * library is challenging to build. From a more positive perspective, it is also + * proof that a great deal of complexity can be centralized primarily to one + * place in order to provide a more consistent and simple experience elsewhere. + * + * Using These Options + * It doesn't matter if you're using a target-specific compiler and a simulator + * or a native compiler. In either case, you've got a couple choices for + * configuring these options: + * + * 1. Because these options are specified via C defines, you can pass most of + * these options to your compiler through command line compiler flags. Even + * if you're using an embedded target that forces you to use their + * overbearing IDE for all configuration, there will be a place somewhere in + * your project to configure defines for your compiler. + * 2. You can create a custom `unity_config.h` configuration file (present in + * your toolchain's search paths). In this file, you will list definitions + * and macros specific to your target. All you must do is define + * `UNITY_INCLUDE_CONFIG_H` and Unity will rely on `unity_config.h` for any + * further definitions it may need. + */ + +#ifndef UNITY_CONFIG_H +#define UNITY_CONFIG_H + +/* ************************* AUTOMATIC INTEGER TYPES *************************** + * C's concept of an integer varies from target to target. The C Standard has + * rules about the `int` matching the register size of the target + * microprocessor. It has rules about the `int` and how its size relates to + * other integer types. An `int` on one target might be 16 bits while on another + * target it might be 64. There are more specific types in compilers compliant + * with C99 or later, but that's certainly not every compiler you are likely to + * encounter. Therefore, Unity has a number of features for helping to adjust + * itself to match your required integer sizes. It starts off by trying to do it + * automatically. + **************************************************************************** */ + +/* The first attempt to guess your types is to check `limits.h`. Some compilers + * that don't support `stdint.h` could include `limits.h`. If you don't + * want Unity to check this file, define this to make it skip the inclusion. + * Unity looks at UINT_MAX & ULONG_MAX, which were available since C89. + */ +/* #define UNITY_EXCLUDE_LIMITS_H */ + +/* The second thing that Unity does to guess your types is check `stdint.h`. + * This file defines `UINTPTR_MAX`, since C99, that Unity can make use of to + * learn about your system. It's possible you don't want it to do this or it's + * possible that your system doesn't support `stdint.h`. If that's the case, + * you're going to want to define this. That way, Unity will know to skip the + * inclusion of this file and you won't be left with a compiler error. + */ +/* #define UNITY_EXCLUDE_STDINT_H */ + +/* ********************** MANUAL INTEGER TYPE DEFINITION *********************** + * If you've disabled all of the automatic options above, you're going to have + * to do the configuration yourself. There are just a handful of defines that + * you are going to specify if you don't like the defaults. + **************************************************************************** */ + + /* Define this to be the number of bits an `int` takes up on your system. The + * default, if not auto-detected, is 32 bits. + * + * Example: + */ +/* #define UNITY_INT_WIDTH 16 */ + +/* Define this to be the number of bits a `long` takes up on your system. The + * default, if not autodetected, is 32 bits. This is used to figure out what + * kind of 64-bit support your system can handle. Does it need to specify a + * `long` or a `long long` to get a 64-bit value. On 16-bit systems, this option + * is going to be ignored. + * + * Example: + */ +/* #define UNITY_LONG_WIDTH 16 */ + +/* Define this to be the number of bits a pointer takes up on your system. The + * default, if not autodetected, is 32-bits. If you're getting ugly compiler + * warnings about casting from pointers, this is the one to look at. + * + * Example: + */ +/* #define UNITY_POINTER_WIDTH 64 */ + +/* Unity will automatically include 64-bit support if it auto-detects it, or if + * your `int`, `long`, or pointer widths are greater than 32-bits. Define this + * to enable 64-bit support if none of the other options already did it for you. + * There can be a significant size and speed impact to enabling 64-bit support + * on small targets, so don't define it if you don't need it. + */ +/* #define UNITY_SUPPORT_64 */ + + +/* *************************** FLOATING POINT TYPES **************************** + * In the embedded world, it's not uncommon for targets to have no support for + * floating point operations at all or to have support that is limited to only + * single precision. We are able to guess integer sizes on the fly because + * integers are always available in at least one size. Floating point, on the + * other hand, is sometimes not available at all. Trying to include `float.h` on + * these platforms would result in an error. This leaves manual configuration as + * the only option. + **************************************************************************** */ + + /* By default, Unity guesses that you will want single precision floating point + * support, but not double precision. It's easy to change either of these using + * the include and exclude options here. You may include neither, just float, + * or both, as suits your needs. + */ +/* #define UNITY_EXCLUDE_FLOAT */ +/* #define UNITY_INCLUDE_DOUBLE */ +/* #define UNITY_EXCLUDE_DOUBLE */ + +/* For features that are enabled, the following floating point options also + * become available. + */ + +/* Unity aims for as small of a footprint as possible and avoids most standard + * library calls (some embedded platforms don't have a standard library!). + * Because of this, its routines for printing integer values are minimalist and + * hand-coded. To keep Unity universal, though, we eventually chose to develop + * our own floating point print routines. Still, the display of floating point + * values during a failure are optional. By default, Unity will print the + * actual results of floating point assertion failures. So a failed assertion + * will produce a message like "Expected 4.0 Was 4.25". If you would like less + * verbose failure messages for floating point assertions, use this option to + * give a failure message `"Values Not Within Delta"` and trim the binary size. + */ +/* #define UNITY_EXCLUDE_FLOAT_PRINT */ + +/* If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C + * floats. If your compiler supports a specialty floating point type, you can + * always override this behavior by using this definition. + * + * Example: + */ +/* #define UNITY_FLOAT_TYPE float16_t */ + +/* If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard + * C doubles. If you would like to change this, you can specify something else + * by using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long + * double` could enable gargantuan floating point types on your 64-bit processor + * instead of the standard `double`. + * + * Example: + */ +/* #define UNITY_DOUBLE_TYPE long double */ + +/* If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as + * documented in the Unity Assertion Guide, you will learn that they are not + * really asserting that two values are equal but rather that two values are + * "close enough" to equal. "Close enough" is controlled by these precision + * configuration options. If you are working with 32-bit floats and/or 64-bit + * doubles (the normal on most processors), you should have no need to change + * these options. They are both set to give you approximately 1 significant bit + * in either direction. The float precision is 0.00001 while the double is + * 10^-12. For further details on how this works, see the appendix of the Unity + * Assertion Guide. + * + * Example: + */ +/* #define UNITY_FLOAT_PRECISION 0.001f */ +/* #define UNITY_DOUBLE_PRECISION 0.001f */ + + +/* *************************** MISCELLANEOUS *********************************** + * Miscellaneous configuration options for Unity + **************************************************************************** */ + +/* Unity uses the stddef.h header included in the C standard library for the + * "NULL" macro. Define this in order to disable the include of stddef.h. If you + * do this, you have to make sure to provide your own "NULL" definition. + */ +/* #define UNITY_EXCLUDE_STDDEF_H */ + +/* Define this to enable the unity formatted print macro: + * "TEST_PRINTF" + */ +/* #define UNITY_INCLUDE_PRINT_FORMATTED */ + + +/* *************************** TOOLSET CUSTOMIZATION *************************** + * In addition to the options listed above, there are a number of other options + * which will come in handy to customize Unity's behavior for your specific + * toolchain. It is possible that you may not need to touch any of these but + * certain platforms, particularly those running in simulators, may need to jump + * through extra hoops to operate properly. These macros will help in those + * situations. + **************************************************************************** */ + +/* By default, Unity prints its results to `stdout` as it runs. This works + * perfectly fine in most situations where you are using a native compiler for + * testing. It works on some simulators as well so long as they have `stdout` + * routed back to the command line. There are times, however, where the + * simulator will lack support for dumping results or you will want to route + * results elsewhere for other reasons. In these cases, you should define the + * `UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time + * (as an `int`, since this is the parameter type of the standard C `putchar` + * function most commonly used). You may replace this with whatever function + * call you like. + * + * Example: + * Say you are forced to run your test suite on an embedded processor with no + * `stdout` option. You decide to route your test result output to a custom + * serial `RS232_putc()` function you wrote like thus: + */ +/* #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) */ +/* #define UNITY_OUTPUT_CHAR_HEADER_DECLARATION RS232_putc(int) */ +/* #define UNITY_OUTPUT_FLUSH() RS232_flush() */ +/* #define UNITY_OUTPUT_FLUSH_HEADER_DECLARATION RS232_flush(void) */ +/* #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) */ +/* #define UNITY_OUTPUT_COMPLETE() RS232_close() */ + +/* Some compilers require a custom attribute to be assigned to pointers, like + * `near` or `far`. In these cases, you can give Unity a safe default for these + * by defining this option with the attribute you would like. + * + * Example: + */ +/* #define UNITY_PTR_ATTRIBUTE __attribute__((far)) */ +/* #define UNITY_PTR_ATTRIBUTE near */ + +/* Print execution time of each test when executed in verbose mode + * + * Example: + * + * TEST - PASS (10 ms) + */ +/* #define UNITY_INCLUDE_EXEC_TIME */ + +#endif /* UNITY_CONFIG_H */ diff --git a/src/subprojects/unity/extras/bdd/readme.md b/src/subprojects/unity/extras/bdd/readme.md new file mode 100644 index 00000000..e7035885 --- /dev/null +++ b/src/subprojects/unity/extras/bdd/readme.md @@ -0,0 +1,40 @@ +# Unity Project - BDD Feature + +Unity's Behavior-Driven Development (BDD) test feature. It allows developers to structure and describe various phases (Given, When, Then) of a test scenario in a BDD-style format. + +## Introduction + +This project is based on the Unity framework originally created by Mike Karlesky, Mark VanderVoord, and Greg Williams in 2007. The project extends Unity by providing macros to define BDD structures with descriptive elements. Feature added by Michael Gene Brockus (Dreamer). + +## License + +This project is distributed under the MIT License. See the [license.txt](license.txt) file for more information. + +## Usage + +### BDD Macros + +The provided BDD macros allow you to structure your test scenarios in a descriptive manner. These macros are for descriptive purposes only and do not have functional behavior. + +- `GIVEN(description)`: Describes the "Given" phase of a test scenario. +- `WHEN(description)`: Describes the "When" phase of a test scenario. +- `THEN(description)`: Describes the "Then" phase of a test scenario. + +Example usage: + +```c +GIVEN("a valid input") { + // Test setup and context + // ... + + WHEN("the input is processed") { + // Perform the action + // ... + + THEN("the expected outcome occurs") { + // Assert the outcome + // ... + } + } +} +``` diff --git a/src/subprojects/unity/extras/bdd/src/unity_bdd.h b/src/subprojects/unity/extras/bdd/src/unity_bdd.h new file mode 100644 index 00000000..feff492c --- /dev/null +++ b/src/subprojects/unity/extras/bdd/src/unity_bdd.h @@ -0,0 +1,44 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_BDD_TEST_H_ +#define UNITY_BDD_TEST_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** + * @brief Macros for defining a Behavior-Driven Development (BDD) structure with descriptions. + * + * These macros provide a way to structure and describe different phases (Given, When, Then) of a + * test scenario in a BDD-style format. However, they don't have functional behavior by themselves + * and are used for descriptive purposes. + */ +#define GIVEN(description) \ + if (0) { \ + printf("Given %s\n", description); \ + } else + +#define WHEN(description) \ + if (0) { \ + printf("When %s\n", description); \ + } else + +#define THEN(description) \ + if (0) { \ + printf("Then %s\n", description); \ + } else + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/subprojects/unity/extras/bdd/test/meson.build b/src/subprojects/unity/extras/bdd/test/meson.build new file mode 100644 index 00000000..fcdaffff --- /dev/null +++ b/src/subprojects/unity/extras/bdd/test/meson.build @@ -0,0 +1,9 @@ +project('BDD Tester', 'c') + +# Add Unity as a dependency +unity_dep = dependency('unity') + +# Define your source files +sources = files('test_bdd.c') + +executable('tester', sources, dependencies : unity_dep) diff --git a/src/subprojects/unity/extras/bdd/test/test_bdd.c b/src/subprojects/unity/extras/bdd/test/test_bdd.c new file mode 100644 index 00000000..f86e5abd --- /dev/null +++ b/src/subprojects/unity/extras/bdd/test/test_bdd.c @@ -0,0 +1,129 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "unity_bdd.h" + +void test_bdd_logic_test(void) { + GIVEN("a valid statement is passed") + { + // Set up the context + bool givenExecuted = true; + + WHEN("a statement is true") + { + // Perform the login action + bool whenExecuted = true; + + THEN("we validate everything was worked") + { + // Check the expected outcome + bool thenExecuted = true; + + TEST_ASSERT_TRUE(givenExecuted); + TEST_ASSERT_TRUE(whenExecuted); + TEST_ASSERT_TRUE(thenExecuted); + } + } + } +} // end of case + +void test_bdd_user_account(void) { + GIVEN("a user's account with sufficient balance") + { + // Set up the context + float accountBalance = 500.0; + float withdrawalAmount = 200.0; + + WHEN("the user requests a withdrawal of $200") + { + // Perform the withdrawal action + if (accountBalance >= withdrawalAmount) + { + accountBalance -= withdrawalAmount; + } // end if + THEN("the withdrawal amount should be deducted from the account balance") + { + // Check the expected outcome + + // Simulate the scenario + float compareBalance = 500.0; + TEST_ASSERT_LESS_THAN_FLOAT(accountBalance, compareBalance); + } + } + } +} // end of case + +void test_bdd_empty_cart(void) { + GIVEN("a user with an empty shopping cart") + { + // Set up the context + int cartItemCount = 0; + + WHEN("the user adds a product to the cart") + { + // Perform the action of adding a product + + THEN("the cart item count should increase by 1") + { + // Check the expected outcome + cartItemCount++; + + TEST_ASSERT_EQUAL_INT(cartItemCount, 1); + } + } + } +} // end of case + +void test_bdd_valid_login(void) { + GIVEN("a registered user with valid credentials") + { + // Set up the context + const char* validUsername = "user123"; + const char* validPassword = "pass456"; + + WHEN("the user provides correct username and password") + { + // Perform the action of user login + const char* inputUsername = "user123"; + const char* inputPassword = "pass456"; + + THEN("the login should be successful") + { + // Check the expected outcome + // Simulate login validation + TEST_ASSERT_EQUAL_STRING(inputUsername, validUsername); + TEST_ASSERT_EQUAL_STRING(inputPassword, validPassword); + } + } + + WHEN("the user provides incorrect password") + { + // Perform the action of user login + const char* inputUsername = "user123"; + const char* inputPassword = "wrongpass"; + + THEN("the login should fail with an error message") + { + // Check the expected outcome + // Simulate login validation + TEST_ASSERT_EQUAL_STRING(inputUsername, validUsername); + // TEST_ASSERT_NOT_EQUAL_STRING(inputPassword, validPassword); + } + } + } +} // end of case + +int main(void) +{ + UnityBegin("test_bdd.c"); + RUN_TEST(test_bdd_logic_test); + RUN_TEST(test_bdd_user_account); + RUN_TEST(test_bdd_empty_cart); + RUN_TEST(test_bdd_valid_login); + return UnityEnd(); +} diff --git a/src/subprojects/unity/extras/eclipse/error_parsers.txt b/src/subprojects/unity/extras/eclipse/error_parsers.txt new file mode 100644 index 00000000..94e34ff3 --- /dev/null +++ b/src/subprojects/unity/extras/eclipse/error_parsers.txt @@ -0,0 +1,26 @@ +Eclipse error parsers +===================== + +These are a godsend for extracting & quickly navigating to +warnings & error messages from console output. Unforunately +I don't know how to write an Eclipse plugin so you'll have +to add them manually. + +To add a console parser to Eclipse, go to Window --> Preferences +--> C/C++ --> Build --> Settings. Click on the 'Error Parsers' +tab and then click the 'Add...' button. See the table below for +the parser fields to add. + +Eclipse will only parse the console output during a build, so +running your unit tests must be part of your build process. +Either add this to your make/rakefile, or add it as a post- +build step in your Eclipse project settings. + + +Unity unit test error parsers +----------------------------- +Severity Pattern File Line Description +------------------------------------------------------------------------------- +Error (\.+)(.*?):(\d+):(.*?):FAIL: (.*) $2 $3 $5 +Warning (\.+)(.*?):(\d+):(.*?):IGNORE: (.*) $2 $3 $5 +Warning (\.+)(.*?):(\d+):(.*?):IGNORE\s*$ $2 $3 Ignored test diff --git a/src/subprojects/unity/extras/fixture/readme.md b/src/subprojects/unity/extras/fixture/readme.md new file mode 100644 index 00000000..e0c9e1b7 --- /dev/null +++ b/src/subprojects/unity/extras/fixture/readme.md @@ -0,0 +1,26 @@ +# Unity Fixtures + +This Framework is an optional add-on to Unity. +By including unity_fixture.h in place of unity.h, you may now work with Unity in a manner similar to CppUTest. +This framework adds the concepts of test groups and gives finer control of your tests over the command line. + +This framework is primarily supplied for those working through James Grenning's book on Embedded Test Driven Development, or those coming to Unity from CppUTest. +We should note that using this framework glosses over some of the features of Unity, and makes it more difficult to integrate with other testing tools like Ceedling and CMock. + +## Dependency Notification + +Fixtures, by default, uses the Memory addon as well. +This is to make it simple for those trying to follow along with James' book. +Using them together is completely optional. +You may choose to use Fixtures without Memory handling by defining `UNITY_FIXTURE_NO_EXTRAS`. +It will then stop automatically pulling in extras and leave you to do it as desired. + +## Usage information + +By default the test executables produced by Unity Fixtures run all tests once, but the behavior can be configured with command-line flags. +Run the test executable with the `--help` flag for more information. + +It's possible to add a custom line at the end of the help message, typically to point to project-specific or company-specific unit test documentation. +Define `UNITY_CUSTOM_HELP_MSG` to provide a custom message, e.g.: + + #define UNITY_CUSTOM_HELP_MSG "If any test fails see https://example.com/troubleshooting" diff --git a/src/subprojects/unity/extras/fixture/src/meson.build b/src/subprojects/unity/extras/fixture/src/meson.build new file mode 100644 index 00000000..224911de --- /dev/null +++ b/src/subprojects/unity/extras/fixture/src/meson.build @@ -0,0 +1,10 @@ +unity_inc += include_directories('.') +unity_src += files('unity_fixture.c') + +if not meson.is_subproject() + install_headers( + 'unity_fixture.h', + 'unity_fixture_internals.h', + subdir: meson.project_name() + ) +endif diff --git a/src/subprojects/unity/extras/fixture/src/unity_fixture.c b/src/subprojects/unity/extras/fixture/src/unity_fixture.c new file mode 100644 index 00000000..9b3fce27 --- /dev/null +++ b/src/subprojects/unity/extras/fixture/src/unity_fixture.c @@ -0,0 +1,310 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity_fixture.h" +#include "unity_internals.h" +#include + +struct UNITY_FIXTURE_T UnityFixture; + +/* If you decide to use the function pointer approach. + * Build with -D UNITY_OUTPUT_CHAR=outputChar and include + * int (*outputChar)(int) = putchar; */ + +void setUp(void) { /*does nothing*/ } +void tearDown(void) { /*does nothing*/ } + +static void announceTestRun(unsigned int runNumber) +{ + UnityPrint("Unity test run "); + UnityPrintNumberUnsigned(runNumber+1); + UnityPrint(" of "); + UnityPrintNumberUnsigned(UnityFixture.RepeatCount); + UNITY_PRINT_EOL(); +} + +int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)) +{ + int result = UnityGetCommandLineOptions(argc, argv); + unsigned int r; + if (result != 0) + return result; + + for (r = 0; r < UnityFixture.RepeatCount; r++) + { + UnityBegin(argv[0]); + announceTestRun(r); + runAllTests(); + if (!UnityFixture.Verbose) UNITY_PRINT_EOL(); + UnityEnd(); + } + + return (int)Unity.TestFailures; +} + +static int selected(const char* filter, const char* name) +{ + if (filter == 0) + return 1; + return strstr(name, filter) ? 1 : 0; +} + +static int testSelected(const char* test) +{ + return selected(UnityFixture.NameFilter, test); +} + +static int groupSelected(const char* group) +{ + return selected(UnityFixture.GroupFilter, group); +} + +void UnityTestRunner(unityfunction* setup, + unityfunction* testBody, + unityfunction* teardown, + const char* printableName, + const char* group, + const char* name, + const char* file, + unsigned int line) +{ + if (testSelected(name) && groupSelected(group)) + { + Unity.TestFile = file; + Unity.CurrentTestName = printableName; + Unity.CurrentTestLineNumber = line; + if (UnityFixture.Verbose) + { + UnityPrint(printableName); + #ifndef UNITY_REPEAT_TEST_NAME + Unity.CurrentTestName = NULL; + #endif + } + else if (UnityFixture.Silent) + { + /* Do Nothing */ + } + else + { + UNITY_OUTPUT_CHAR('.'); + } + + Unity.NumberOfTests++; + UnityPointer_Init(); + + UNITY_EXEC_TIME_START(); + + if (TEST_PROTECT()) + { + setup(); + testBody(); + } + if (TEST_PROTECT()) + { + teardown(); + } + if (TEST_PROTECT()) + { + UnityPointer_UndoAllSets(); + } + UnityConcludeFixtureTest(); + } +} + +void UnityIgnoreTest(const char* printableName, const char* group, const char* name) +{ + if (testSelected(name) && groupSelected(group)) + { + Unity.NumberOfTests++; + Unity.TestIgnores++; + if (UnityFixture.Verbose) + { + UnityPrint(printableName); + UNITY_PRINT_EOL(); + } + else if (UnityFixture.Silent) + { + /* Do Nothing */ + } + else + { + UNITY_OUTPUT_CHAR('!'); + } + } +} + +/*-------------------------------------------------------- */ +/*Automatic pointer restoration functions */ +struct PointerPair +{ + void** pointer; + void* old_value; +}; + +static struct PointerPair pointer_store[UNITY_MAX_POINTERS]; +static int pointer_index = 0; + +void UnityPointer_Init(void) +{ + pointer_index = 0; +} + +void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line) +{ + if (pointer_index >= UNITY_MAX_POINTERS) + { + UNITY_TEST_FAIL(line, "Too many pointers set"); + } + else + { + pointer_store[pointer_index].pointer = pointer; + pointer_store[pointer_index].old_value = *pointer; + *pointer = newValue; + pointer_index++; + } +} + +void UnityPointer_UndoAllSets(void) +{ + while (pointer_index > 0) + { + pointer_index--; + *(pointer_store[pointer_index].pointer) = + pointer_store[pointer_index].old_value; + } +} + +int UnityGetCommandLineOptions(int argc, const char* argv[]) +{ + int i; + UnityFixture.Verbose = 0; + UnityFixture.Silent = 0; + UnityFixture.GroupFilter = 0; + UnityFixture.NameFilter = 0; + UnityFixture.RepeatCount = 1; + + if (argc == 1) + return 0; + + for (i = 1; i < argc; ) + { + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) + { + /* Usage */ + UnityPrint("Runs a series of unit tests."); + UNITY_PRINT_EOL(); + UNITY_PRINT_EOL(); + UnityPrint("When no flag is specified, all tests are run."); + UNITY_PRINT_EOL(); + UNITY_PRINT_EOL(); + UnityPrint("Optional flags:"); + UNITY_PRINT_EOL(); + UnityPrint(" -v Verbose output: show all tests executed even if they pass"); + UNITY_PRINT_EOL(); + UnityPrint(" -s Silent mode: minimal output showing only test failures"); + UNITY_PRINT_EOL(); + UnityPrint(" -g NAME Only run tests in groups that contain the string NAME"); + UNITY_PRINT_EOL(); + UnityPrint(" -n NAME Only run tests whose name contains the string NAME"); + UNITY_PRINT_EOL(); + UnityPrint(" -r NUMBER Repeatedly run all tests NUMBER times"); + UNITY_PRINT_EOL(); + UnityPrint(" -h, --help Display this help message"); + UNITY_PRINT_EOL(); + UNITY_PRINT_EOL(); +#ifdef UNITY_CUSTOM_HELP_MSG + /* User-defined help message, e.g. to point to project-specific documentation */ + UnityPrint(UNITY_CUSTOM_HELP_MSG); + UNITY_PRINT_EOL(); +#else + /* Default help suffix if a custom one is not defined */ + UnityPrint("More information about Unity: https://www.throwtheswitch.org/unity"); + UNITY_PRINT_EOL(); +#endif + return 1; /* Exit without running the tests */ + } + else if (strcmp(argv[i], "-v") == 0) + { + UnityFixture.Verbose = 1; + i++; + } + else if (strcmp(argv[i], "-s") == 0) + { + UnityFixture.Silent = 1; + i++; + } + else if (strcmp(argv[i], "-g") == 0) + { + i++; + if (i >= argc) + return 1; + UnityFixture.GroupFilter = argv[i]; + i++; + } + else if (strcmp(argv[i], "-n") == 0) + { + i++; + if (i >= argc) + return 1; + UnityFixture.NameFilter = argv[i]; + i++; + } + else if (strcmp(argv[i], "-r") == 0) + { + UnityFixture.RepeatCount = 2; + i++; + if (i < argc) + { + if (*(argv[i]) >= '0' && *(argv[i]) <= '9') + { + unsigned int digit = 0; + UnityFixture.RepeatCount = 0; + while (argv[i][digit] >= '0' && argv[i][digit] <= '9') + { + UnityFixture.RepeatCount *= 10; + UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0'; + } + i++; + } + } + } + else + { + /* ignore unknown parameter */ + i++; + } + } + return 0; +} + +void UnityConcludeFixtureTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + UNITY_PRINT_EOL(); + } + else if (!Unity.CurrentTestFailed) + { + if (UnityFixture.Verbose) + { + UnityPrint(" "); + UnityPrint(UnityStrPass); + UNITY_EXEC_TIME_STOP(); + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + } + } + else /* Unity.CurrentTestFailed */ + { + Unity.TestFailures++; + UNITY_PRINT_EOL(); + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; +} diff --git a/src/subprojects/unity/extras/fixture/src/unity_fixture.h b/src/subprojects/unity/extras/fixture/src/unity_fixture.h new file mode 100644 index 00000000..ed6ff482 --- /dev/null +++ b/src/subprojects/unity/extras/fixture/src/unity_fixture.h @@ -0,0 +1,94 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FIXTURE_H_ +#define UNITY_FIXTURE_H_ + +#include "unity.h" +#include "unity_fixture_internals.h" + +#ifndef UNITY_FIXTURE_NO_EXTRAS +#include "unity_memory.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + + +int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)); + + +#define TEST_GROUP(group)\ + static const char* TEST_GROUP_##group = #group + +#define TEST_SETUP(group) void TEST_##group##_SETUP(void);\ + void TEST_##group##_SETUP(void) + +#define TEST_TEAR_DOWN(group) void TEST_##group##_TEAR_DOWN(void);\ + void TEST_##group##_TEAR_DOWN(void) + + +#define TEST(group, name) \ + void TEST_##group##_##name##_(void);\ + void TEST_##group##_##name##_run(void);\ + void TEST_##group##_##name##_run(void)\ + {\ + UnityTestRunner(TEST_##group##_SETUP,\ + TEST_##group##_##name##_,\ + TEST_##group##_TEAR_DOWN,\ + "TEST(" #group ", " #name ")",\ + TEST_GROUP_##group, #name,\ + __FILE__, __LINE__);\ + }\ + void TEST_##group##_##name##_(void) + +#define IGNORE_TEST(group, name) \ + void TEST_##group##_##name##_(void);\ + void TEST_##group##_##name##_run(void);\ + void TEST_##group##_##name##_run(void)\ + {\ + UnityIgnoreTest("IGNORE_TEST(" #group ", " #name ")", TEST_GROUP_##group, #name);\ + }\ + void TEST_##group##_##name##_(void) + +/* Call this for each test, insider the group runner */ +#define RUN_TEST_CASE(group, name) \ + { void TEST_##group##_##name##_run(void);\ + TEST_##group##_##name##_run(); } + +/* This goes at the bottom of each test file or in a separate c file */ +#define TEST_GROUP_RUNNER(group)\ + void TEST_##group##_GROUP_RUNNER(void);\ + void TEST_##group##_GROUP_RUNNER(void) + +/* Call this from main */ +#define RUN_TEST_GROUP(group)\ + { void TEST_##group##_GROUP_RUNNER(void);\ + TEST_##group##_GROUP_RUNNER(); } + +/* CppUTest Compatibility Macros */ +#ifndef UNITY_EXCLUDE_CPPUTEST_ASSERTS +/* Sets a pointer and automatically restores it to its old value after teardown */ +#define UT_PTR_SET(ptr, newPointerValue) UnityPointer_Set((void**)&(ptr), (void*)(newPointerValue), __LINE__) +#define TEST_ASSERT_POINTERS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_PTR((expected), (actual)) +#define TEST_ASSERT_BYTES_EQUAL(expected, actual) TEST_ASSERT_EQUAL_HEX8(0xff & (expected), 0xff & (actual)) +#define FAIL(message) TEST_FAIL_MESSAGE((message)) +#define CHECK(condition) TEST_ASSERT_TRUE((condition)) +#define LONGS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_INT((expected), (actual)) +#define STRCMP_EQUAL(expected, actual) TEST_ASSERT_EQUAL_STRING((expected), (actual)) +#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* UNITY_FIXTURE_H_ */ diff --git a/src/subprojects/unity/extras/fixture/src/unity_fixture_internals.h b/src/subprojects/unity/extras/fixture/src/unity_fixture_internals.h new file mode 100644 index 00000000..f8f83d2d --- /dev/null +++ b/src/subprojects/unity/extras/fixture/src/unity_fixture_internals.h @@ -0,0 +1,50 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FIXTURE_INTERNALS_H_ +#define UNITY_FIXTURE_INTERNALS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct UNITY_FIXTURE_T +{ + int Verbose; + int Silent; + unsigned int RepeatCount; + const char* NameFilter; + const char* GroupFilter; +}; +extern struct UNITY_FIXTURE_T UnityFixture; + +typedef void unityfunction(void); +void UnityTestRunner(unityfunction* setup, + unityfunction* testBody, + unityfunction* teardown, + const char* printableName, + const char* group, + const char* name, + const char* file, unsigned int line); + +void UnityIgnoreTest(const char* printableName, const char* group, const char* name); +int UnityGetCommandLineOptions(int argc, const char* argv[]); +void UnityConcludeFixtureTest(void); + +void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line); +void UnityPointer_UndoAllSets(void); +void UnityPointer_Init(void); +#ifndef UNITY_MAX_POINTERS +#define UNITY_MAX_POINTERS 5 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* UNITY_FIXTURE_INTERNALS_H_ */ diff --git a/src/subprojects/unity/extras/fixture/test/main/AllTests.c b/src/subprojects/unity/extras/fixture/test/main/AllTests.c new file mode 100644 index 00000000..d5eec4be --- /dev/null +++ b/src/subprojects/unity/extras/fixture/test/main/AllTests.c @@ -0,0 +1,20 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity_fixture.h" + +static void runAllTests(void) +{ + RUN_TEST_GROUP(UnityFixture); + RUN_TEST_GROUP(UnityCommandOptions); +} + +int main(int argc, const char* argv[]) +{ + return UnityMain(argc, argv, runAllTests); +} + diff --git a/src/subprojects/unity/extras/fixture/test/template_fixture_tests.c b/src/subprojects/unity/extras/fixture/test/template_fixture_tests.c new file mode 100644 index 00000000..2397f105 --- /dev/null +++ b/src/subprojects/unity/extras/fixture/test/template_fixture_tests.c @@ -0,0 +1,39 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity_fixture.h" + +static int data = -1; + +TEST_GROUP(mygroup); + +TEST_SETUP(mygroup) +{ + data = 0; +} + +TEST_TEAR_DOWN(mygroup) +{ + data = -1; +} + +TEST(mygroup, test1) +{ + TEST_ASSERT_EQUAL_INT(0, data); +} + +TEST(mygroup, test2) +{ + TEST_ASSERT_EQUAL_INT(0, data); + data = 5; +} + +TEST(mygroup, test3) +{ + data = 7; + TEST_ASSERT_EQUAL_INT(7, data); +} diff --git a/src/subprojects/unity/extras/fixture/test/unity_fixture_Test.c b/src/subprojects/unity/extras/fixture/test/unity_fixture_Test.c new file mode 100644 index 00000000..d2785d3c --- /dev/null +++ b/src/subprojects/unity/extras/fixture/test/unity_fixture_Test.c @@ -0,0 +1,245 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity_fixture.h" +#include +#include + +TEST_GROUP(UnityFixture); + +TEST_SETUP(UnityFixture) +{ +} + +TEST_TEAR_DOWN(UnityFixture) +{ +} + +static int* pointer1 = 0; +static int* pointer2 = (int*)2; +static int* pointer3 = (int*)3; +static int int1; +static int int2; +static int int3; +static int int4; + +TEST(UnityFixture, PointerSetting) +{ + TEST_ASSERT_POINTERS_EQUAL(pointer1, 0); + UT_PTR_SET(pointer1, &int1); + UT_PTR_SET(pointer2, &int2); + UT_PTR_SET(pointer3, &int3); + TEST_ASSERT_POINTERS_EQUAL(pointer1, &int1); + TEST_ASSERT_POINTERS_EQUAL(pointer2, &int2); + TEST_ASSERT_POINTERS_EQUAL(pointer3, &int3); + UT_PTR_SET(pointer1, &int4); + UnityPointer_UndoAllSets(); + TEST_ASSERT_POINTERS_EQUAL(pointer1, 0); + TEST_ASSERT_POINTERS_EQUAL(pointer2, (int*)2); + TEST_ASSERT_POINTERS_EQUAL(pointer3, (int*)3); +} + +static char *p1; +static char *p2; + +TEST(UnityFixture, PointerSet) +{ + char c1; + char c2; + char newC1; + char newC2; + p1 = &c1; + p2 = &c2; + + UnityPointer_Init(); + UT_PTR_SET(p1, &newC1); + UT_PTR_SET(p2, &newC2); + TEST_ASSERT_POINTERS_EQUAL(&newC1, p1); + TEST_ASSERT_POINTERS_EQUAL(&newC2, p2); + UnityPointer_UndoAllSets(); + TEST_ASSERT_POINTERS_EQUAL(&c1, p1); + TEST_ASSERT_POINTERS_EQUAL(&c2, p2); +} + +TEST(UnityFixture, FreeNULLSafety) +{ + free(NULL); +} + +TEST(UnityFixture, ConcludeTestIncrementsFailCount) +{ + UNITY_UINT savedFails = Unity.TestFailures; + UNITY_UINT savedIgnores = Unity.TestIgnores; + Unity.CurrentTestFailed = 1; + UnityConcludeFixtureTest(); /* Resets TestFailed for this test to pass */ + Unity.CurrentTestIgnored = 1; + UnityConcludeFixtureTest(); /* Resets TestIgnored */ + TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures); + TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores); + Unity.TestFailures = savedFails; + Unity.TestIgnores = savedIgnores; +} + +/*------------------------------------------------------------ */ + +TEST_GROUP(UnityCommandOptions); + +static int savedVerbose; +static unsigned int savedRepeat; +static const char* savedName; +static const char* savedGroup; + +TEST_SETUP(UnityCommandOptions) +{ + savedVerbose = UnityFixture.Verbose; + savedRepeat = UnityFixture.RepeatCount; + savedName = UnityFixture.NameFilter; + savedGroup = UnityFixture.GroupFilter; +} + +TEST_TEAR_DOWN(UnityCommandOptions) +{ + UnityFixture.Verbose = savedVerbose; + UnityFixture.RepeatCount= savedRepeat; + UnityFixture.NameFilter = savedName; + UnityFixture.GroupFilter = savedGroup; +} + + +static const char* noOptions[] = { + "testrunner.exe" +}; + +TEST(UnityCommandOptions, DefaultOptions) +{ + UnityGetCommandLineOptions(1, noOptions); + TEST_ASSERT_EQUAL(0, UnityFixture.Verbose); + TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.GroupFilter); + TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.NameFilter); + TEST_ASSERT_EQUAL(1, UnityFixture.RepeatCount); +} + +static const char* verbose[] = { + "testrunner.exe", + "-v" +}; + +TEST(UnityCommandOptions, OptionVerbose) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, verbose)); + TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); +} + +static const char* group[] = { + "testrunner.exe", + "-g", "groupname" +}; + +TEST(UnityCommandOptions, OptionSelectTestByGroup) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, group)); + STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); +} + +static const char* name[] = { + "testrunner.exe", + "-n", "testname" +}; + +TEST(UnityCommandOptions, OptionSelectTestByName) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, name)); + STRCMP_EQUAL("testname", UnityFixture.NameFilter); +} + +static const char* repeat[] = { + "testrunner.exe", + "-r", "99" +}; + +TEST(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, repeat)); + TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount); +} + +TEST(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, repeat)); + TEST_ASSERT_EQUAL(99, UnityFixture.RepeatCount); +} + +static const char* multiple[] = { + "testrunner.exe", + "-v", + "-g", "groupname", + "-n", "testname", + "-r", "98" +}; + +TEST(UnityCommandOptions, MultipleOptions) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(8, multiple)); + TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); + STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); + STRCMP_EQUAL("testname", UnityFixture.NameFilter); + TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount); +} + +static const char* dashRNotLast[] = { + "testrunner.exe", + "-v", + "-g", "gggg", + "-r", + "-n", "tttt", +}; + +TEST(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(7, dashRNotLast)); + TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); + STRCMP_EQUAL("gggg", UnityFixture.GroupFilter); + STRCMP_EQUAL("tttt", UnityFixture.NameFilter); + TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount); +} + +static const char* unknownCommand[] = { + "testrunner.exe", + "-v", + "-g", "groupname", + "-n", "testname", + "-r", "98", + "-z" +}; +TEST(UnityCommandOptions, UnknownCommandIsIgnored) +{ + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(9, unknownCommand)); + TEST_ASSERT_EQUAL(1, UnityFixture.Verbose); + STRCMP_EQUAL("groupname", UnityFixture.GroupFilter); + STRCMP_EQUAL("testname", UnityFixture.NameFilter); + TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount); +} + +TEST(UnityCommandOptions, GroupOrNameFilterWithoutStringFails) +{ + TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(3, unknownCommand)); + TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(5, unknownCommand)); + TEST_ASSERT_EQUAL(1, UnityMain(3, unknownCommand, NULL)); +} + +TEST(UnityCommandOptions, GroupFilterReallyFilters) +{ + UNITY_UINT saved = Unity.NumberOfTests; + TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(4, unknownCommand)); + UnityIgnoreTest(NULL, "non-matching", NULL); + TEST_ASSERT_EQUAL(saved, Unity.NumberOfTests); +} + +IGNORE_TEST(UnityCommandOptions, TestShouldBeIgnored) +{ + TEST_FAIL_MESSAGE("This test should not run!"); +} diff --git a/src/subprojects/unity/extras/fixture/test/unity_fixture_TestRunner.c b/src/subprojects/unity/extras/fixture/test/unity_fixture_TestRunner.c new file mode 100644 index 00000000..ec92663f --- /dev/null +++ b/src/subprojects/unity/extras/fixture/test/unity_fixture_TestRunner.c @@ -0,0 +1,32 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity_fixture.h" + +TEST_GROUP_RUNNER(UnityFixture) +{ + RUN_TEST_CASE(UnityFixture, PointerSetting); + RUN_TEST_CASE(UnityFixture, PointerSet); + RUN_TEST_CASE(UnityFixture, FreeNULLSafety); + RUN_TEST_CASE(UnityFixture, ConcludeTestIncrementsFailCount); +} + +TEST_GROUP_RUNNER(UnityCommandOptions) +{ + RUN_TEST_CASE(UnityCommandOptions, DefaultOptions); + RUN_TEST_CASE(UnityCommandOptions, OptionVerbose); + RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByGroup); + RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByName); + RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount); + RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount); + RUN_TEST_CASE(UnityCommandOptions, MultipleOptions); + RUN_TEST_CASE(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified); + RUN_TEST_CASE(UnityCommandOptions, UnknownCommandIsIgnored); + RUN_TEST_CASE(UnityCommandOptions, GroupOrNameFilterWithoutStringFails); + RUN_TEST_CASE(UnityCommandOptions, GroupFilterReallyFilters); + RUN_TEST_CASE(UnityCommandOptions, TestShouldBeIgnored); +} diff --git a/src/subprojects/unity/extras/memory/readme.md b/src/subprojects/unity/extras/memory/readme.md new file mode 100644 index 00000000..ea8b9cf7 --- /dev/null +++ b/src/subprojects/unity/extras/memory/readme.md @@ -0,0 +1,42 @@ +# Unity Memory + +This Framework is an optional add-on to Unity. +By including unity.h and then unity_memory.h, you have the added ability to track malloc and free calls. +This addon requires that the stdlib functions be overridden by its own defines. +These defines will still malloc / realloc / free etc, but will also track the calls in order to ensure that you don't have any memory leaks in your programs. + +Note that this is only useful in situations where a unit is in charge of both the allocation and deallocation of memory. +When it is not symmetric, unit testing can report a number of false failures. +A more advanced runtime tool is required to track complete system memory handling. + +## Module API + +### `UnityMalloc_StartTest` and `UnityMalloc_EndTest` + +These must be called at the beginning and end of each test. +For simplicity, they can be added to `setUp` and `tearDown` in order to do their job. +When using the test runner generator scripts, these will be automatically added to the runner whenever unity_memory.h is included. + +### `UnityMalloc_MakeMallocFailAfterCount` + +This can be called from the tests themselves. +Passing this function a number will force the reference counter to start keeping track of malloc calls. +During that test, if the number of malloc calls exceeds the number given, malloc will immediately start returning `NULL`. +This allows you to test error conditions. +Think of it as a simplified mock. + +## Configuration + +### `UNITY_MALLOC` and `UNITY_FREE` + +By default, this module tries to use the real stdlib `malloc` and `free` internally. +If you would prefer it to use something else, like FreeRTOS's `pvPortMalloc` and `pvPortFree`, then you can use these defines to make it so. + +### `UNITY_EXCLUDE_STDLIB_MALLOC` + +If you would like this library to ignore stdlib or other heap engines completely, and manage the memory on its own, then define this. All memory will be handled internally (and at likely lower overhead). +Note that this is not a very featureful memory manager, but is sufficient for most testing purposes. + +### `UNITY_INTERNAL_HEAP_SIZE_BYTES` + +When using the built-in memory manager (see `UNITY_EXCLUDE_STDLIB_MALLOC`) this define allows you to set the heap size this library will use to manage the memory. diff --git a/src/subprojects/unity/extras/memory/src/meson.build b/src/subprojects/unity/extras/memory/src/meson.build new file mode 100644 index 00000000..650ba32d --- /dev/null +++ b/src/subprojects/unity/extras/memory/src/meson.build @@ -0,0 +1,9 @@ +unity_inc += include_directories('.') +unity_src += files('unity_memory.c') + +if not meson.is_subproject() + install_headers( + 'unity_memory.h', + subdir: meson.project_name() + ) +endif diff --git a/src/subprojects/unity/extras/memory/src/unity_memory.c b/src/subprojects/unity/extras/memory/src/unity_memory.c new file mode 100644 index 00000000..e9eaae35 --- /dev/null +++ b/src/subprojects/unity/extras/memory/src/unity_memory.c @@ -0,0 +1,203 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "unity_memory.h" +#include + +#define MALLOC_DONT_FAIL -1 +static int malloc_count; +static int malloc_fail_countdown = MALLOC_DONT_FAIL; + +void UnityMalloc_StartTest(void) +{ + malloc_count = 0; + malloc_fail_countdown = MALLOC_DONT_FAIL; +} + +void UnityMalloc_EndTest(void) +{ + malloc_fail_countdown = MALLOC_DONT_FAIL; + if (malloc_count != 0) + { + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!"); + } +} + +void UnityMalloc_MakeMallocFailAfterCount(int countdown) +{ + malloc_fail_countdown = countdown; +} + +/* These definitions are always included from unity_fixture_malloc_overrides.h */ +/* We undef to use them or avoid conflict with per the C standard */ +#undef malloc +#undef free +#undef calloc +#undef realloc + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC +static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES]; +static size_t heap_index; +#else +#include +#endif + +typedef struct GuardBytes +{ + size_t size; + size_t guard_space; +} Guard; + +#define UNITY_MALLOC_ALIGNMENT (UNITY_POINTER_WIDTH / 8) +static const char end[] = "END"; + +static size_t unity_size_round_up(size_t size) +{ + size_t rounded_size; + + rounded_size = ((size + UNITY_MALLOC_ALIGNMENT - 1) / UNITY_MALLOC_ALIGNMENT) * UNITY_MALLOC_ALIGNMENT; + + return rounded_size; +} + +void* unity_malloc(size_t size) +{ + char* mem; + Guard* guard; + size_t total_size; + + total_size = sizeof(Guard) + unity_size_round_up(size + sizeof(end)); + + if (malloc_fail_countdown != MALLOC_DONT_FAIL) + { + if (malloc_fail_countdown == 0) + return NULL; + malloc_fail_countdown--; + } + + if (size == 0) return NULL; +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES) + { + guard = NULL; + } + else + { + /* We know we can get away with this cast because we aligned memory already */ + guard = (Guard*)(void*)(&unity_heap[heap_index]); + heap_index += total_size; + } +#else + guard = (Guard*)UNITY_MALLOC(total_size); +#endif + if (guard == NULL) return NULL; + malloc_count++; + guard->size = size; + guard->guard_space = 0; + mem = (char*)&(guard[1]); + memcpy(&mem[size], end, sizeof(end)); + + return (void*)mem; +} + +static int isOverrun(void* mem) +{ + Guard* guard = (Guard*)mem; + char* memAsChar = (char*)mem; + guard--; + + return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0; +} + +static void release_memory(void* mem) +{ + Guard* guard = (Guard*)mem; + guard--; + + malloc_count--; +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + { + size_t block_size; + + block_size = unity_size_round_up(guard->size + sizeof(end)); + + if (mem == unity_heap + heap_index - block_size) + { + heap_index -= (sizeof(Guard) + block_size); + } + } +#else + UNITY_FREE(guard); +#endif +} + +void unity_free(void* mem) +{ + int overrun; + + if (mem == NULL) + { + return; + } + + overrun = isOverrun(mem); + release_memory(mem); + if (overrun) + { + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()"); + } +} + +void* unity_calloc(size_t num, size_t size) +{ + void* mem = unity_malloc(num * size); + if (mem == NULL) return NULL; + memset(mem, 0, num * size); + return mem; +} + +void* unity_realloc(void* oldMem, size_t size) +{ + Guard* guard = (Guard*)oldMem; + void* newMem; + + if (oldMem == NULL) return unity_malloc(size); + + guard--; + if (isOverrun(oldMem)) + { + release_memory(oldMem); + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()"); + } + + if (size == 0) + { + release_memory(oldMem); + return NULL; + } + + if (guard->size >= size) return oldMem; + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */ + { + size_t old_total_size = unity_size_round_up(guard->size + sizeof(end)); + + if ((oldMem == unity_heap + heap_index - old_total_size) && + ((heap_index - old_total_size + unity_size_round_up(size + sizeof(end))) <= UNITY_INTERNAL_HEAP_SIZE_BYTES)) + { + release_memory(oldMem); /* Not thread-safe, like unity_heap generally */ + return unity_malloc(size); /* No memcpy since data is in place */ + } + } +#endif + newMem = unity_malloc(size); + if (newMem == NULL) return NULL; /* Do not release old memory */ + memcpy(newMem, oldMem, guard->size); + release_memory(oldMem); + return newMem; +} diff --git a/src/subprojects/unity/extras/memory/src/unity_memory.h b/src/subprojects/unity/extras/memory/src/unity_memory.h new file mode 100644 index 00000000..70a7f25f --- /dev/null +++ b/src/subprojects/unity/extras/memory/src/unity_memory.h @@ -0,0 +1,61 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_MEMORY_OVERRIDES_H_ +#define UNITY_MEMORY_OVERRIDES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC +/* Define this macro to remove the use of stdlib.h, malloc, and free. + * Many embedded systems do not have a heap or malloc/free by default. + * This internal unity_malloc() provides allocated memory deterministically from + * the end of an array only, unity_free() only releases from end-of-array, + * blocks are not coalesced, and memory not freed in LIFO order is stranded. */ + #ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES + #define UNITY_INTERNAL_HEAP_SIZE_BYTES 256 + #endif +#endif + +/* These functions are used by Unity to allocate and release memory + * on the heap and can be overridden with platform-specific implementations. + * For example, when using FreeRTOS UNITY_MALLOC becomes pvPortMalloc() + * and UNITY_FREE becomes vPortFree(). */ +#if !defined(UNITY_MALLOC) || !defined(UNITY_FREE) + #include + #define UNITY_MALLOC(size) malloc(size) + #define UNITY_FREE(ptr) free(ptr) +#else + extern void* UNITY_MALLOC(size_t size); + extern void UNITY_FREE(void* ptr); +#endif + +#define malloc unity_malloc +#define calloc unity_calloc +#define realloc unity_realloc +#define free unity_free + +void* unity_malloc(size_t size); +void* unity_calloc(size_t num, size_t size); +void* unity_realloc(void * oldMem, size_t size); +void unity_free(void * mem); + +/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */ +void UnityMalloc_StartTest(void); +void UnityMalloc_EndTest(void); +void UnityMalloc_MakeMallocFailAfterCount(int countdown); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/subprojects/unity/extras/memory/test/unity_memory_Test.c b/src/subprojects/unity/extras/memory/test/unity_memory_Test.c new file mode 100644 index 00000000..b66e6deb --- /dev/null +++ b/src/subprojects/unity/extras/memory/test/unity_memory_Test.c @@ -0,0 +1,326 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "unity_memory.h" +#include "unity_output_Spy.h" +#include +#include + +/* This test module includes the following tests: */ + +void test_ForceMallocFail(void); +void test_ReallocSmallerIsUnchanged(void); +void test_ReallocSameIsUnchanged(void); +void test_ReallocLargerNeeded(void); +void test_ReallocNullPointerIsLikeMalloc(void); +void test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void); +void test_CallocFillsWithZero(void); +void test_FreeNULLSafety(void); +void test_DetectsLeak(void); +void test_BufferOverrunFoundDuringFree(void); +void test_BufferOverrunFoundDuringRealloc(void); +void test_BufferGuardWriteFoundDuringFree(void); +void test_BufferGuardWriteFoundDuringRealloc(void); +void test_MallocPastBufferFails(void); +void test_CallocPastBufferFails(void); +void test_MallocThenReallocGrowsMemoryInPlace(void); +void test_ReallocFailDoesNotFreeMem(void); + +/* It makes use of the following features */ +void setUp(void); +void tearDown(void); + +/* Let's Go! */ +void setUp(void) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + UnityOutputCharSpy_Create(200); +#else + UnityOutputCharSpy_Create(1000); +#endif + UnityMalloc_StartTest(); +} + +void tearDown(void) +{ + UnityMalloc_EndTest(); + UnityOutputCharSpy_Destroy(); +} + +void test_ForceMallocFail(void) +{ + void* m; + void* mfails; + UnityMalloc_MakeMallocFailAfterCount(1); + m = malloc(10); + TEST_ASSERT_NOT_NULL(m); + mfails = malloc(10); + TEST_ASSERT_EQUAL_PTR(0, mfails); + free(m); +} + +void test_ReallocSmallerIsUnchanged(void) +{ + void* m1 = malloc(10); + void* m2 = realloc(m1, 5); + TEST_ASSERT_NOT_NULL(m1); + TEST_ASSERT_EQUAL_PTR(m1, m2); + free(m2); +} + +void test_ReallocSameIsUnchanged(void) +{ + void* m1 = malloc(10); + void* m2 = realloc(m1, 10); + TEST_ASSERT_NOT_NULL(m1); + TEST_ASSERT_EQUAL_PTR(m1, m2); + free(m2); +} + +void test_ReallocLargerNeeded(void) +{ + void* m2; + void* m1 = malloc(10); + TEST_ASSERT_NOT_NULL(m1); + strcpy((char*)m1, "123456789"); + m2 = realloc(m1, 15); + TEST_ASSERT_EQUAL_STRING("123456789", m2); + free(m2); +} + +void test_ReallocNullPointerIsLikeMalloc(void) +{ + void* m = realloc(0, 15); + TEST_ASSERT_NOT_NULL(m); + free(m); +} + +void test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void) +{ + void* m1 = malloc(10); + void* m2 = realloc(m1, 0); + TEST_ASSERT_EQUAL_PTR(0, m2); +} + +void test_CallocFillsWithZero(void) +{ + void* m = calloc(3, sizeof(char)); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + TEST_ASSERT_EQUAL_HEX8(0, s[0]); + TEST_ASSERT_EQUAL_HEX8(0, s[1]); + TEST_ASSERT_EQUAL_HEX8(0, s[2]); + free(m); +} + +void test_FreeNULLSafety(void) +{ + free(NULL); +} + +/*------------------------------------------------------------ */ + +#define EXPECT_ABORT_BEGIN \ + { \ + jmp_buf TestAbortFrame; \ + memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \ + if (TEST_PROTECT()) \ + { + +#define EXPECT_ABORT_END \ + } \ + memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \ + } + +/* This tricky set of defines lets us see if we are using the Spy, returns 1 if true */ +#ifdef __STDC_VERSION__ + +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0) +#define ASSIGN_VALUE(a) VAL_##a +#define VAL_UnityOutputCharSpy_OutputChar 0, 1 +#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway) +#define SECOND_PARAM(a, b, ...) b +#if USING_SPY_AS(UNITY_OUTPUT_CHAR) + #define USING_OUTPUT_SPY /* UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar */ +#endif +#endif /* UNITY_SUPPORT_VARIADIC_MACROS */ + +#else /* __STDC_VERSION__ else */ + +#define UnityOutputCharSpy_OutputChar 42 +#if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar /* Works if no -Wundef -Werror */ + #define USING_OUTPUT_SPY +#endif +#undef UnityOutputCharSpy_OutputChar + +#endif /* __STDC_VERSION__ */ + +void test_DetectsLeak(void) +{ +#ifdef USING_OUTPUT_SPY + void* m = malloc(10); + TEST_ASSERT_NOT_NULL(m); + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + UnityMalloc_EndTest(); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "This test leaks!")); + free(m); +#else + TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test"); +#endif +} + +void test_BufferOverrunFoundDuringFree(void) +{ +#ifdef USING_OUTPUT_SPY + void* m = malloc(10); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + s[10] = (char)0xFF; + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + free(m); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()")); +#else + TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test"); +#endif +} + +void test_BufferOverrunFoundDuringRealloc(void) +{ +#ifdef USING_OUTPUT_SPY + void* m = malloc(10); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + s[10] = (char)0xFF; + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + m = realloc(m, 100); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()")); +#else + TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test"); +#endif +} + +void test_BufferGuardWriteFoundDuringFree(void) +{ +#ifdef USING_OUTPUT_SPY + void* m = malloc(10); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + s[-1] = (char)0x00; /* Will not detect 0 */ + s[-2] = (char)0x01; + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + free(m); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()")); +#else + TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test"); +#endif +} + +void test_BufferGuardWriteFoundDuringRealloc(void) +{ +#ifdef USING_OUTPUT_SPY + void* m = malloc(10); + char* s = (char*)m; + TEST_ASSERT_NOT_NULL(m); + s[-1] = (char)0x0A; + UnityOutputCharSpy_Enable(1); + EXPECT_ABORT_BEGIN + m = realloc(m, 100); + EXPECT_ABORT_END + UnityOutputCharSpy_Enable(0); + Unity.CurrentTestFailed = 0; + TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()")); +#else + TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test"); +#endif +} + +/*------------------------------------------------------------ */ + +#define TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(first_mem_ptr, ptr) \ + ptr = malloc(10); free(ptr); \ + TEST_ASSERT_EQUAL_PTR_MESSAGE(first_mem_ptr, ptr, "Memory was stranded, free in LIFO order"); + +void test_MallocPastBufferFails(void) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); + void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2); + free(m); + TEST_ASSERT_NOT_NULL(m); + TEST_ASSERT_NULL(n); + TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); +#else + TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test"); +#endif +} + +void test_CallocPastBufferFails(void) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); + void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2); + free(m); + TEST_ASSERT_NOT_NULL(m); + TEST_ASSERT_NULL(n); + TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); +#else + TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test"); +#endif +} + +void test_MallocThenReallocGrowsMemoryInPlace(void) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); + void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9); + free(n); + TEST_ASSERT_NOT_NULL(m); + TEST_ASSERT_EQUAL(m, n); + TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n); +#else + TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test"); +#endif +} + +void test_ReallocFailDoesNotFreeMem(void) +{ +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2); + void* n1 = malloc(10); + void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1); + void* n2 = malloc(10); + + free(n2); + if (out_of_mem == NULL) free(n1); + free(m); + + TEST_ASSERT_NOT_NULL(m); /* Got a real memory location */ + TEST_ASSERT_NULL(out_of_mem); /* The realloc should have failed */ + TEST_ASSERT_NOT_EQUAL(n2, n1); /* If n1 != n2 then realloc did not free n1 */ + TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n2); +#else + TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test"); +#endif +} diff --git a/src/subprojects/unity/extras/memory/test/unity_memory_TestRunner.c b/src/subprojects/unity/extras/memory/test/unity_memory_TestRunner.c new file mode 100644 index 00000000..0a8ed3da --- /dev/null +++ b/src/subprojects/unity/extras/memory/test/unity_memory_TestRunner.c @@ -0,0 +1,50 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "unity_memory.h" + +extern void test_ForceMallocFail(void); +extern void test_ReallocSmallerIsUnchanged(void); +extern void test_ReallocSameIsUnchanged(void); +extern void test_ReallocLargerNeeded(void); +extern void test_ReallocNullPointerIsLikeMalloc(void); +extern void test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void); +extern void test_CallocFillsWithZero(void); +extern void test_FreeNULLSafety(void); +extern void test_DetectsLeak(void); +extern void test_BufferOverrunFoundDuringFree(void); +extern void test_BufferOverrunFoundDuringRealloc(void); +extern void test_BufferGuardWriteFoundDuringFree(void); +extern void test_BufferGuardWriteFoundDuringRealloc(void); +extern void test_MallocPastBufferFails(void); +extern void test_CallocPastBufferFails(void); +extern void test_MallocThenReallocGrowsMemoryInPlace(void); +extern void test_ReallocFailDoesNotFreeMem(void); + +int main(void) +{ + UnityBegin("unity_memory_Test.c"); + RUN_TEST(test_ForceMallocFail); + RUN_TEST(test_ReallocSmallerIsUnchanged); + RUN_TEST(test_ReallocSameIsUnchanged); + RUN_TEST(test_ReallocLargerNeeded); + RUN_TEST(test_ReallocNullPointerIsLikeMalloc); + RUN_TEST(test_ReallocSizeZeroFreesMemAndReturnsNullPointer); + RUN_TEST(test_CallocFillsWithZero); + RUN_TEST(test_FreeNULLSafety); + RUN_TEST(test_DetectsLeak); + RUN_TEST(test_BufferOverrunFoundDuringFree); + RUN_TEST(test_BufferOverrunFoundDuringRealloc); + RUN_TEST(test_BufferGuardWriteFoundDuringFree); + RUN_TEST(test_BufferGuardWriteFoundDuringRealloc); + RUN_TEST(test_MallocPastBufferFails); + RUN_TEST(test_CallocPastBufferFails); + RUN_TEST(test_MallocThenReallocGrowsMemoryInPlace); + RUN_TEST(test_ReallocFailDoesNotFreeMem); + return UnityEnd(); +} diff --git a/src/subprojects/unity/extras/memory/test/unity_output_Spy.c b/src/subprojects/unity/extras/memory/test/unity_output_Spy.c new file mode 100644 index 00000000..044c5def --- /dev/null +++ b/src/subprojects/unity/extras/memory/test/unity_output_Spy.c @@ -0,0 +1,57 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "unity_output_Spy.h" + +#include +#include +#include + +static int size; +static int count; +static char* buffer; +static int spy_enable; + +void UnityOutputCharSpy_Create(int s) +{ + size = (s > 0) ? s : 0; + count = 0; + spy_enable = 0; + buffer = malloc((size_t)size); + TEST_ASSERT_NOT_NULL_MESSAGE(buffer, "Internal malloc failed in Spy Create():" __FILE__); + memset(buffer, 0, (size_t)size); +} + +void UnityOutputCharSpy_Destroy(void) +{ + size = 0; + free(buffer); +} + +void UnityOutputCharSpy_OutputChar(int c) +{ + if (spy_enable) + { + if (count < (size-1)) + buffer[count++] = (char)c; + } + else + { + putchar(c); + } +} + +const char * UnityOutputCharSpy_Get(void) +{ + return buffer; +} + +void UnityOutputCharSpy_Enable(int enable) +{ + spy_enable = enable; +} diff --git a/src/subprojects/unity/extras/memory/test/unity_output_Spy.h b/src/subprojects/unity/extras/memory/test/unity_output_Spy.h new file mode 100644 index 00000000..3c2e9b97 --- /dev/null +++ b/src/subprojects/unity/extras/memory/test/unity_output_Spy.h @@ -0,0 +1,17 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_OUTPUT_SPY_H +#define UNITY_OUTPUT_SPY_H + +void UnityOutputCharSpy_Create(int s); +void UnityOutputCharSpy_Destroy(void); +void UnityOutputCharSpy_OutputChar(int c); +const char * UnityOutputCharSpy_Get(void); +void UnityOutputCharSpy_Enable(int enable); + +#endif diff --git a/src/subprojects/unity/library.json b/src/subprojects/unity/library.json new file mode 100644 index 00000000..839b5abd --- /dev/null +++ b/src/subprojects/unity/library.json @@ -0,0 +1,25 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +{ + "name": "Unity", + "version": "2.6.0", + "keywords": "unit-testing, testing, tdd, testing-framework", + "description": "Simple Unit Testing for C", + "homepage": "http://www.throwtheswitch.org/unity", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/ThrowTheSwitch/Unity.git" + }, + "frameworks": "*", + "platforms": "*", + "headers": "unity.h", + "build": { + "extraScript": "platformio-build.py" + } +} diff --git a/src/subprojects/unity/meson.build b/src/subprojects/unity/meson.build new file mode 100644 index 00000000..4e2eac6c --- /dev/null +++ b/src/subprojects/unity/meson.build @@ -0,0 +1,89 @@ +# +# build script written by : Michael Gene Brockus. +# github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams. +# +# license: MIT +# +project('unity', 'c', + license: 'MIT', + + # Set project version to value extracted from unity.h header + version: run_command( + [ + 'auto/extract_version.py', + 'src/unity.h' + ], + check: true + ).stdout().strip(), + + meson_version: '>=0.47.0', + default_options: [ + 'werror=false', + 'c_std=c11' + ] +) + +build_fixture = get_option('extension_fixture') +build_memory = get_option('extension_memory') +support_double = get_option('support_double') + +unity_args = [] +unity_src = [] +unity_inc = [] + +subdir('src') + +if build_fixture + # Building the fixture extension implies building the memory + # extension. + build_memory = true + subdir('extras/fixture/src') +endif + +if build_memory + subdir('extras/memory/src') +endif + +if support_double + unity_args += '-DUNITY_INCLUDE_DOUBLE' +endif + +unity_lib = static_library(meson.project_name(), + sources: unity_src, + c_args: unity_args + ['-DUNITY_OUTPUT_COLOR=1'], + include_directories: unity_inc, + install: not meson.is_subproject(), +) + +unity_dep = declare_dependency( + link_with: unity_lib, + include_directories: unity_inc +) + +# Wrap-fallback plumbing (see file header): register the parent's +# dependency('unity') resolution and reproduce the nix header layout -- +# includedir variable points at the source tree root, which contains a +# unity/ dir holding the two headers (shipped by this wrap's +# patch_directory). include_directories('src') covers bare-include +# consumers, mirroring the nix pc's -I${includedir}/unity. +unity_sdep = declare_dependency( + link_with: unity_lib, + include_directories: [unity_inc, include_directories('.')], + variables: {'includedir': meson.current_source_dir()}, + version: meson.project_version()) +meson.override_dependency('unity', unity_sdep) + +# XCE does not consume the ruby-generated test runner (its suites use +# unity's built-in RUN_TEST macro) and the build environment has no ruby, +# so the upstream generator block is not registered. + +# Generate pkg-config file. +if not meson.is_subproject() + pkg = import('pkgconfig') + pkg.generate( + name: meson.project_name(), + version: meson.project_version(), + libraries: [ unity_lib ], + description: 'C Unit testing framework.' + ) +endif diff --git a/src/subprojects/unity/meson_options.txt b/src/subprojects/unity/meson_options.txt new file mode 100644 index 00000000..8e66784b --- /dev/null +++ b/src/subprojects/unity/meson_options.txt @@ -0,0 +1,3 @@ +option('extension_fixture', type: 'boolean', value: 'false', description: 'Whether to enable the fixture extension.') +option('extension_memory', type: 'boolean', value: 'false', description: 'Whether to enable the memory extension.') +option('support_double', type: 'boolean', value: 'false', description: 'Whether to enable double precision floating point assertions.') diff --git a/src/subprojects/unity/platformio-build.py b/src/subprojects/unity/platformio-build.py new file mode 100644 index 00000000..51251ddd --- /dev/null +++ b/src/subprojects/unity/platformio-build.py @@ -0,0 +1,24 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +import os + +Import("env") + +env.Append(CPPDEFINES=["UNITY_INCLUDE_CONFIG_H"]) + +# import "unity_config.h" folder to the library builder +try: + Import("projenv") + + projenv.Append(CPPDEFINES=["UNITY_INCLUDE_CONFIG_H"]) + for p in projenv["CPPPATH"]: + p = projenv.subst(p) + if os.path.isfile(os.path.join(p, "unity_config.h")): + env.Prepend(CPPPATH=[p]) +except: + pass diff --git a/src/subprojects/unity/src/meson.build b/src/subprojects/unity/src/meson.build new file mode 100644 index 00000000..5365227f --- /dev/null +++ b/src/subprojects/unity/src/meson.build @@ -0,0 +1,17 @@ +# +# build script written by : Michael Gene Brockus. +# github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams. +# +# license: MIT +# + +unity_inc += include_directories('.') +unity_src += files('unity.c') + +if not meson.is_subproject() + install_headers( + 'unity.h', + 'unity_internals.h', + subdir: meson.project_name() + ) +endif diff --git a/src/subprojects/unity/src/unity.c b/src/subprojects/unity/src/unity.c new file mode 100644 index 00000000..7fa2dc63 --- /dev/null +++ b/src/subprojects/unity/src/unity.c @@ -0,0 +1,2501 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" + +#ifndef UNITY_PROGMEM +#define UNITY_PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL do { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define UNITY_IGNORE_AND_BAIL do { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define RETURN_IF_FAIL_OR_IGNORE do { if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) { TEST_ABORT(); } } while (0) + +struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m"; +const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m"; +const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m"; +const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m"; +#else +const char UNITY_PROGMEM UnityStrOk[] = "OK"; +const char UNITY_PROGMEM UnityStrPass[] = "PASS"; +const char UNITY_PROGMEM UnityStrFail[] = "FAIL"; +const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE"; +#endif +static const char UNITY_PROGMEM UnityStrNull[] = "NULL"; +static const char UNITY_PROGMEM UnityStrSpacer[] = ". "; +static const char UNITY_PROGMEM UnityStrExpected[] = " Expected "; +static const char UNITY_PROGMEM UnityStrWas[] = " Was "; +static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than "; +static const char UNITY_PROGMEM UnityStrLt[] = " to be less than "; +static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to "; +static const char UNITY_PROGMEM UnityStrElement[] = " Element "; +static const char UNITY_PROGMEM UnityStrByte[] = " Byte "; +static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char UNITY_PROGMEM UnityStrNot[] = "Not "; +static const char UNITY_PROGMEM UnityStrInf[] = "Infinity"; +static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char UNITY_PROGMEM UnityStrNaN[] = "NaN"; +static const char UNITY_PROGMEM UnityStrDet[] = "Determinate"; +static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests "; +static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored "; +#ifndef UNITY_EXCLUDE_DETAILS +static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; +#endif +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char* pch) +{ + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char* string) +{ + const char* pch = string; + UNITY_UINT count = 0; + + while (*pch && (*pch != 'm')) + { + UNITY_OUTPUT_CHAR(*pch); + pch++; + count++; + } + UNITY_OUTPUT_CHAR('m'); + count++; + + return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch) + { +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + UnityPrintChar(pch); + pch++; + } + } +} +/*-----------------------------------------------*/ +void UnityPrintLen(const char* string, const UNITY_UINT32 length) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch && ((UNITY_UINT32)(pch - string) < length)) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (style == UNITY_DISPLAY_STYLE_CHAR) + { + /* printable characters plus CR & LF are printed */ + UNITY_OUTPUT_CHAR('\''); + if ((number <= 126) && (number >= 32)) + { + UNITY_OUTPUT_CHAR((int)number); + } + /* write escaped carriage returns */ + else if (number == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (number == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 2); + } + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrintNumber(number); + } + } + else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned((UNITY_UINT)number); + } + else + { + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ + UNITY_UINT number = (UNITY_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (~number) + 1; + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ + UNITY_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ + int nibble; + char nibbles = nibbles_to_print; + + if ((unsigned)nibbles > UNITY_MAX_NIBBLES) + { + nibbles = UNITY_MAX_NIBBLES; + } + + while (nibbles > 0) + { + nibbles--; + nibble = (int)(number >> (nibbles * 4)) & 0x0F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ + UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); + UNITY_INT32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + + UNITY_DOUBLE number = input_number; + + /* print minus sign (does not handle negative zero) */ + if (number < 0.0f) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + /* handle zero, NaN, and +/- infinity */ + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (UNITY_IS_NAN(number)) + { + UnityPrint("nan"); + } + else if (UNITY_IS_INF(number)) + { + UnityPrint("inf"); + } + else + { + UNITY_INT32 n_int = 0; + UNITY_INT32 n; + int exponent = 0; + int decimals; + int digits; + char buf[16] = {0}; + + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if (number < 1.0f) + { + UNITY_DOUBLE factor = 1.0f; + + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; } + while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } + + number *= factor; + } + else if (number > (UNITY_DOUBLE)max_scaled) + { + UNITY_DOUBLE divisor = 1.0f; + + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; } + while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } + + number /= divisor; + } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; + + while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } + + number *= factor; + } + + /* round to nearest integer */ + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) + n--; +#endif + + n += n_int; + + if (n >= max_scaled) + { + n = min_scaled; + exponent++; + } + + /* determine where to place decimal point */ + decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); + exponent += decimals; + + /* truncate trailing zeroes after decimal point */ + while ((decimals > 0) && ((n % 10) == 0)) + { + n /= 10; + decimals--; + } + + /* build up buffer in reverse order */ + digits = 0; + while ((n != 0) || (digits <= decimals)) + { + buf[digits++] = (char)('0' + n % 10); + n /= 10; + } + + /* print out buffer (backwards) */ + while (digits > 0) + { + if (digits == decimals) + { + UNITY_OUTPUT_CHAR('.'); + } + UNITY_OUTPUT_CHAR(buf[--digits]); + } + + /* print exponent if needed */ + if (exponent != 0) + { + UNITY_OUTPUT_CHAR('e'); + + if (exponent < 0) + { + UNITY_OUTPUT_CHAR('-'); + exponent = -exponent; + } + else + { + UNITY_OUTPUT_CHAR('+'); + } + + digits = 0; + while ((exponent != 0) || (digits < 2)) + { + buf[digits++] = (char)('0' + exponent % 10); + exponent /= 10; + } + while (digits > 0) + { + UNITY_OUTPUT_CHAR(buf[--digits]); + } + } + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ +#ifdef UNITY_OUTPUT_FOR_ECLIPSE + UNITY_OUTPUT_CHAR('('); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(')'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else +#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH + UnityPrint("'); + UnityPrint(Unity.CurrentTestName); + UnityPrint(" "); +#else +#ifdef UNITY_OUTPUT_FOR_QT_CREATOR + UnityPrint("file://"); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#endif +#endif +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg) +{ +#ifdef UNITY_PRINT_TEST_CONTEXT + UnityPrint(UnityStrSpacer); + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + } +#endif + if (msg) + { + UnityPrint(UnityStrSpacer); + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, + const char* actual, + const UNITY_UINT32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_LINE_TYPE lineNumber, + const char* msg) +{ + /* Both are NULL or same pointer */ + if (expected == actual) { return 0; } + + /* print and return true if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + return 1; + } + + /* print and return true if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + return 1; + } + + return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; } + if ((threshold == actual)) { failed = 1; } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + else /* UINT or HEX */ + { + if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + if (compare == UNITY_NOT_EQUAL) { UnityPrint(UnityStrNotEqual); } + UnityPrintNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ +do { \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; \ +} while (0) + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x000000FF; + actual_val &= 0x000000FF; + } + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x0000FFFF; + actual_val &= 0x0000FFFF; + } + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +#ifdef UNITY_SUPPORT_64 + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x00000000FFFFFFFF; + actual_val &= 0x00000000FFFFFFFF; + } +#endif + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if (expect_val != actual_val) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (UNITY_IS_INF(expected) && UNITY_IS_INF(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \ + if (UNITY_NAN_CHECK) return 1; \ + (diff) = (actual) - (expected); \ + if ((diff) < 0) (diff) = -(diff); \ + if ((delta) < 0) (delta) = -(delta); \ + return !(UNITY_IS_NAN(diff) || UNITY_IS_INF(diff) || ((diff) > (delta))) + /* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN + #define UNITY_NAN_CHECK UNITY_IS_NAN(expected) && UNITY_IS_NAN(actual) +#else + #define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + do { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); \ + } while (0) +#else + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ + UNITY_FLOAT diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + UNITY_FLOAT in_delta = delta; + UNITY_FLOAT current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + + if (!UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat((UNITY_DOUBLE)actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ + UNITY_DOUBLE diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + UNITY_DOUBLE in_delta = delta; + UNITY_DOUBLE current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat(actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual > expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + else + { + if ((UNITY_UINT)actual > (UNITY_UINT)expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)actual; + increment = sizeof(UNITY_UINT8); + } + break; + + case 2: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)actual; + increment = sizeof(UNITY_UINT16); + } + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)actual; + increment = sizeof(UNITY_UINT64); + } + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)actual; + increment = sizeof(UNITY_UINT32); + } + length = 4; + break; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual_val > expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + else + { + if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (i < length) && (expected[i] || actual[i]); i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char* expd = NULL; + const char* act = NULL; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if ((const void*)expected == (const void*)actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + expd = (const char*)expected; + } + + do + { + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expd = ((const char* const*)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (expd && act) + { + for (i = 0; expd[i] || act[i]; i++) + { + if (expd[i] != act[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expd != act) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings(expd, act); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; + UNITY_UINT32 elements = num_elements; + UNITY_UINT32 bytes; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + if (length == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp++; + ptr_act++; + } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + } + } +} + +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch(size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED + +/*----------------------------------------------- + * printf length modifier helpers + *-----------------------------------------------*/ + +enum UnityLengthModifier { + UNITY_LENGTH_MODIFIER_NONE, + UNITY_LENGTH_MODIFIER_LONG_LONG, + UNITY_LENGTH_MODIFIER_LONG, +}; + +#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \ +do { \ + switch (LENGTH_MOD) \ + { \ + case UNITY_LENGTH_MODIFIER_LONG_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_NONE: \ + default: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \ + break; \ + } \ + } \ +} while (0) + +static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length) +{ + enum UnityLengthModifier length_mod; + switch (pch[0]) + { + case 'l': + { + if (pch[1] == 'l') + { + *length = 2; + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + } + else + { + *length = 1; + length_mod = UNITY_LENGTH_MODIFIER_LONG; + } + break; + } + case 'h': + { + // short and char are converted to int + length_mod = UNITY_LENGTH_MODIFIER_NONE; + if (pch[1] == 'h') + { + *length = 2; + } + else + { + *length = 1; + } + break; + } + case 'j': + case 'z': + case 't': + case 'L': + { + // Not supported, but should gobble up the length specifier anyway + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 1; + break; + } + default: + { + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 0; + } + } + return length_mod; +} + +/*----------------------------------------------- + * printf helper function + *-----------------------------------------------*/ +static void UnityPrintFVA(const char* format, va_list va) +{ + const char* pch = format; + if (pch != NULL) + { + while (*pch) + { + /* format identification character */ + if (*pch == '%') + { + pch++; + + if (pch != NULL) + { + int length_mod_size; + enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size); + pch += length_mod_size; + + switch (*pch) + { + case 'd': + case 'i': + { + UNITY_INT number; + UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int); + UnityPrintNumber((UNITY_INT)number); + break; + } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + case 'f': + case 'g': + { + const double number = va_arg(va, double); + UnityPrintFloat((UNITY_DOUBLE)number); + break; + } +#endif + case 'u': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UnityPrintNumberUnsigned(number); + break; + } + case 'b': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('b'); + UnityPrintMask(mask, number); + break; + } + case 'x': + case 'X': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex(number, UNITY_MAX_NIBBLES); + break; + } + case 'p': + { + UNITY_UINT number; + char nibbles_to_print = 8; + if (UNITY_POINTER_WIDTH == 64) + { + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + nibbles_to_print = 16; + } + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, nibbles_to_print); + break; + } + case 'c': + { + const int ch = va_arg(va, int); + UnityPrintChar((const char *)&ch); + break; + } + case 's': + { + const char * string = va_arg(va, const char *); + UnityPrint(string); + break; + } + case '%': + { + UnityPrintChar(pch); + break; + } + default: + { + /* print the unknown format character */ + UNITY_OUTPUT_CHAR('%'); + UnityPrintChar(pch); + break; + } + } + } + } +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + else if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + else if (*pch == '\n') + { + UNITY_PRINT_EOL(); + } + else + { + UnityPrintChar(pch); + } + + pch++; + } + } +} + +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if(format != NULL) + { + UnityPrint(": "); + va_list va; + va_start(va, format); + UnityPrintFVA(format, va); + va_end(va); + } + UNITY_PRINT_EOL(); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + +#ifdef UNITY_PRINT_TEST_CONTEXT + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + if (msg[0] != ' ') + { + UNITY_OUTPUT_CHAR(' '); + } + UnityPrint(msg); + } + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char* msg, const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +/* If we have not defined our own test runner, then include our default test runner to make life easier */ +#ifndef UNITY_SKIP_DEFAULT_RUNNER +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + UNITY_EXEC_TIME_START(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} +#endif + +/*-----------------------------------------------*/ +void UnitySetTestFile(const char* filename) +{ + Unity.TestFile = filename; +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrint(UnityStrOk); + } + else + { + UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; +int UnityStrictMatch = 0; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char** argv) +{ + int i; + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + UnityStrictMatch = 0; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'l': /* list tests */ + return -1; + case 'n': /* include tests with name including this string */ + case 'f': /* an alias for -n */ + UnityStrictMatch = (argv[i][1] == 'n'); /* strictly match this string if -n */ + if (argv[i][2] == '=') + { + UnityOptionIncludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionIncludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + if (argv[i][2] == '=') + { + UnityOptionExcludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionExcludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_OUTPUT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + /* Now display help */ + /* FALLTHRU */ + case 'h': + UnityPrint("Options: "); UNITY_PRINT_EOL(); + UnityPrint("-l List all tests and exit"); UNITY_PRINT_EOL(); + UnityPrint("-f NAME Filter to run only tests whose name includes NAME"); UNITY_PRINT_EOL(); + UnityPrint("-n NAME Run only the test named NAME"); UNITY_PRINT_EOL(); + UnityPrint("-h show this Help menu"); UNITY_PRINT_EOL(); + UnityPrint("-q Quiet/decrease verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-v increase Verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-x NAME eXclude tests whose name includes NAME"); UNITY_PRINT_EOL(); + UNITY_OUTPUT_FLUSH(); + return 1; + } + } + } + + return 0; +} + +/*-----------------------------------------------*/ +static int IsStringInBiggerString(const char* longstring, const char* shortstring) +{ + const char* lptr = longstring; + const char* sptr = shortstring; + const char* lnext = lptr; + + if (*sptr == '*') + { + return UnityStrictMatch ? 0 : 1; + } + + while (*lptr) + { + lnext = lptr + 1; + + /* If they current bytes match, go on to the next bytes */ + while (*lptr && *sptr && (*lptr == *sptr)) + { + lptr++; + sptr++; + + switch (*sptr) + { + case '*': /* we encountered a wild-card */ + return UnityStrictMatch ? 0 : 1; + + case ',': /* we encountered the end of match string */ + case '"': + case '\'': + case 0: + return (!UnityStrictMatch || (*lptr == 0)) ? 1 : 0; + + case ':': /* we encountered the end of a partial match */ + return 2; + + default: + break; + } + } + + // If we didn't match and we're on strict matching, we already know we failed + if (UnityStrictMatch) + { + return 0; + } + + /* Otherwise we start in the long pointer 1 character further and try again */ + lptr = lnext; + sptr = shortstring; + } + + return 0; +} + +/*-----------------------------------------------*/ +static int UnityStringArgumentMatches(const char* str) +{ + int retval; + const char* ptr1; + const char* ptr2; + const char* ptrf; + + /* Go through the options and get the substrings for matching one at a time */ + ptr1 = str; + while (ptr1[0] != 0) + { + if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { + ptr1++; + } + + /* look for the start of the next partial */ + ptr2 = ptr1; + ptrf = 0; + do + { + ptr2++; + if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { + ptrf = &ptr2[1]; + } + } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { + ptr2++; + } + + /* done if complete filename match */ + retval = IsStringInBiggerString(Unity.TestFile, ptr1); + if (retval == 1) + { + return retval; + } + + /* done if testname match after filename partial match */ + if ((retval == 2) && (ptrf != 0)) + { + if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { + return 1; + } + } + + /* done if complete testname match */ + if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { + return 1; + } + + ptr1 = ptr2; + } + + /* we couldn't find a match for any substrings */ + return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + int retval; + if (UnityOptionIncludeNamed) + { + retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); + } + else + { + retval = 1; + } + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionExcludeNamed) + { + if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { + retval = 0; + } + } + + return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ diff --git a/src/subprojects/unity/src/unity.h b/src/subprojects/unity/src/unity.h new file mode 100644 index 00000000..9e2a97b7 --- /dev/null +++ b/src/subprojects/unity/src/unity.h @@ -0,0 +1,698 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 6 +#define UNITY_VERSION_BUILD 1 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/*------------------------------------------------------- + * Build Directives + *------------------------------------------------------- + + * These macros do nothing, but they are useful for additional build context. + * Tools (like Ceedling) can scan for these directives and make use of them for + * per-test-executable #include search paths and linking. */ + +/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ +#define TEST_SOURCE_FILE(a) + +/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ +#define TEST_INCLUDE_PATH(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/subprojects/unity/src/unity_internals.h b/src/subprojects/unity/src/unity_internals.h new file mode 100644 index 00000000..562f5b6d --- /dev/null +++ b/src/subprojects/unity/src/unity_internals.h @@ -0,0 +1,1183 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else + #define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +/* UNITY_NORETURN is only required if we have setjmp.h. */ +#ifndef UNITY_EXCLUDE_SETJMP_H + #ifndef UNITY_NORETURN + #if defined(__cplusplus) + #if __cplusplus >= 201103L + #define UNITY_NORETURN [[ noreturn ]] + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L + /* _Noreturn keyword is used from C11 but deprecated in C23. */ + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #if defined(__GNUC__) + /* The header collides with __attribute(noreturn)__ from GCC. */ + #define UNITY_NORETURN _Noreturn + #else + #include + #define UNITY_NORETURN noreturn + #endif + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L + /* Since C23, the keyword _Noreturn has been replaced by the attribute noreturn, based on: */ + /* https://en.cppreference.com/w/c/language/attributes/noreturn */ + #define UNITY_NORETURN [[ noreturn ]] + #endif + #endif + #ifndef UNITY_NORETURN + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) + #endif +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isnan macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_NAN +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define UNITY_IS_NAN(n) ((n != n) ? 1 : 0) +#else +#define UNITY_IS_NAN(n) isnan(n) +#endif +#endif + +/* isinf macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_INF +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define UNITY_IS_INF(n) (UNITY_IS_NAN((n) - (n)) && !UNITY_IS_NAN(n)) +#else +#define UNITY_IS_INF(n) isinf(n) +#endif +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() (void)0 + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) || defined(__APPLE__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x0, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifdef UNITY_TEST_PROTECT +#define TEST_PROTECT() UNITY_TEST_PROTECT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#else +#define TEST_PROTECT() 1 +#endif +#endif + +#ifdef UNITY_TEST_ABORT +#define TEST_ABORT() UNITY_TEST_ABORT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_ABORT() return +#endif +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX) + #define TEST_MATRIX(...) + #endif + #endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((line), (message)); } } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/src/subprojects/unity/test/.rubocop.yml b/src/subprojects/unity/test/.rubocop.yml new file mode 100644 index 00000000..a11c2461 --- /dev/null +++ b/src/subprojects/unity/test/.rubocop.yml @@ -0,0 +1,83 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +#inherit_from: .rubocop_todo.yml + +AllCops: + TargetRubyVersion: 3.0 + +# These are areas where ThrowTheSwitch's coding style diverges from the Ruby standard +Style/SpecialGlobalVars: + EnforcedStyle: use_perl_names +Style/FormatString: + Enabled: false +Style/GlobalVars: + Enabled: false +Style/FrozenStringLiteralComment: + Enabled: false +Style/RegexpLiteral: + AllowInnerSlashes: true +Style/HashSyntax: + EnforcedStyle: no_mixed_keys +Style/NumericPredicate: + Enabled: false +Style/MultilineBlockChain: + Enabled: false +Style/Alias: + Enabled: false +Style/EvalWithLocation: + Enabled: false +Style/MixinUsage: + Enabled: false +Style/OptionalBooleanParameter: + Enabled: false + +# These are also places we diverge... but we will likely comply down the road +Style/IfUnlessModifier: + Enabled: false +Style/FormatStringToken: + Enabled: false + +# This is disabled because it seems to get confused over nested hashes +Layout/HashAlignment: + Enabled: false + EnforcedHashRocketStyle: table + EnforcedColonStyle: table +Layout/LineLength: + Enabled: false + +# We purposefully use these insecure features because they're what makes Ruby awesome +Security/Eval: + Enabled: false +Security/YAMLLoad: + Enabled: false + +# At this point, we're not ready to enforce inline documentation requirements +Style/Documentation: + Enabled: false +Style/DocumentationMethod: + Enabled: false + +# At this point, we're not ready to enforce any metrics +Metrics/AbcSize: + Enabled: false +Metrics/BlockLength: + Enabled: false +Metrics/BlockNesting: + Enabled: false +Metrics/ClassLength: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/ModuleLength: + Enabled: false +Metrics/ParameterLists: + Enabled: false +Metrics/PerceivedComplexity: + Enabled: false diff --git a/src/subprojects/unity/test/expectdata/testsample_cmd.c b/src/subprojects/unity/test/expectdata/testsample_cmd.c new file mode 100644 index 00000000..7bcf8e10 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_cmd.c @@ -0,0 +1,61 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "CException.h" +#include "funky.h" +#include "stanky.h" +#include + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_def.c b/src/subprojects/unity/test/expectdata/testsample_def.c new file mode 100644 index 00000000..b8ad559f --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_def.c @@ -0,0 +1,57 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "funky.h" +#include "stanky.h" +#include + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_head1.c b/src/subprojects/unity/test/expectdata/testsample_head1.c new file mode 100644 index 00000000..1d01551e --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_head1.c @@ -0,0 +1,55 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "testsample_head1.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_head1.h b/src/subprojects/unity/test/expectdata/testsample_head1.h new file mode 100644 index 00000000..da6b7ab2 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_head1.h @@ -0,0 +1,15 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ +#ifndef _TESTSAMPLE_HEAD1_H +#define _TESTSAMPLE_HEAD1_H + +#include "unity.h" +#include "funky.h" +#include "stanky.h" +#include + +void test_TheFirstThingToTest(void); +void test_TheSecondThingToTest(void); +void test_TheThirdThingToTest(void); +void test_TheFourthThingToTest(void); +#endif + diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_cmd.c b/src/subprojects/unity/test/expectdata/testsample_mock_cmd.c new file mode 100644 index 00000000..45a09af2 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_cmd.c @@ -0,0 +1,80 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "CException.h" +#include "funky.h" +#include +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_def.c b/src/subprojects/unity/test/expectdata/testsample_mock_def.c new file mode 100644 index 00000000..a7a26078 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_def.c @@ -0,0 +1,76 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "funky.h" +#include +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_head1.c b/src/subprojects/unity/test/expectdata/testsample_mock_head1.c new file mode 100644 index 00000000..45829fe7 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_head1.c @@ -0,0 +1,75 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "testsample_mock_head1.h" +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_head1.h b/src/subprojects/unity/test/expectdata/testsample_mock_head1.h new file mode 100644 index 00000000..30c509ad --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_head1.h @@ -0,0 +1,13 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ +#ifndef _TESTSAMPLE_MOCK_HEAD1_H +#define _TESTSAMPLE_MOCK_HEAD1_H + +#include "unity.h" +#include "cmock.h" +#include "funky.h" +#include + +void test_TheFirstThingToTest(void); +void test_TheSecondThingToTest(void); +#endif + diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_new1.c b/src/subprojects/unity/test/expectdata/testsample_mock_new1.c new file mode 100644 index 00000000..0061822e --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_new1.c @@ -0,0 +1,89 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "CException.h" +#include "one.h" +#include "two.h" +#include "funky.h" +#include +#include "Mockstanky.h" + +int GlobalExpectCount; +int GlobalVerifyOrder; +char* GlobalOrderError; + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + GlobalExpectCount = 0; + GlobalVerifyOrder = 0; + GlobalOrderError = NULL; + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_new2.c b/src/subprojects/unity/test/expectdata/testsample_mock_new2.c new file mode 100644 index 00000000..ee63cdc0 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_new2.c @@ -0,0 +1,89 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "funky.h" +#include +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_custom_setup(); +} + +/*=======Suite Teardown=====*/ +static int suite_teardown(int num_failures) +{ +a_custom_teardown(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return suite_teardown(UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_param.c b/src/subprojects/unity/test/expectdata/testsample_mock_param.c new file mode 100644 index 00000000..a42b7dea --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_param.c @@ -0,0 +1,77 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST_NO_ARGS +#define RUN_TEST(TestFunc, TestLineNum, ...) \ +{ \ + Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(__VA_ARGS__); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "funky.h" +#include +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS); + RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_run1.c b/src/subprojects/unity/test/expectdata/testsample_mock_run1.c new file mode 100644 index 00000000..0061822e --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_run1.c @@ -0,0 +1,89 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "CException.h" +#include "one.h" +#include "two.h" +#include "funky.h" +#include +#include "Mockstanky.h" + +int GlobalExpectCount; +int GlobalVerifyOrder; +char* GlobalOrderError; + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + GlobalExpectCount = 0; + GlobalVerifyOrder = 0; + GlobalOrderError = NULL; + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_run2.c b/src/subprojects/unity/test/expectdata/testsample_mock_run2.c new file mode 100644 index 00000000..ee63cdc0 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_run2.c @@ -0,0 +1,89 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "funky.h" +#include +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_custom_setup(); +} + +/*=======Suite Teardown=====*/ +static int suite_teardown(int num_failures) +{ +a_custom_teardown(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return suite_teardown(UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_mock_yaml.c b/src/subprojects/unity/test/expectdata/testsample_mock_yaml.c new file mode 100644 index 00000000..a24bb5a5 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_mock_yaml.c @@ -0,0 +1,90 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + CMock_Init(); \ + UNITY_CLR_DETAILS(); \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + CMock_Verify(); \ + } \ + CMock_Destroy(); \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include "cmock.h" +#include +#include +#include "CException.h" +#include "two.h" +#include "three.h" +#include +#include "funky.h" +#include +#include "Mockstanky.h" + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); + + +/*=======Mock Management=====*/ +static void CMock_Init(void) +{ + Mockstanky_Init(); +} +static void CMock_Verify(void) +{ + Mockstanky_Verify(); +} +static void CMock_Destroy(void) +{ + Mockstanky_Destroy(); +} + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_yaml_setup(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + CMock_Verify(); + CMock_Destroy(); + tearDown(); + CMock_Init(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/mocksample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + + CMock_Guts_MemFreeFinal(); + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_new1.c b/src/subprojects/unity/test/expectdata/testsample_new1.c new file mode 100644 index 00000000..7dcd3fdf --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_new1.c @@ -0,0 +1,67 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "CException.h" +#include "one.h" +#include "two.h" +#include "funky.h" +#include "stanky.h" +#include + +int GlobalExpectCount; +int GlobalVerifyOrder; +char* GlobalOrderError; + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_new2.c b/src/subprojects/unity/test/expectdata/testsample_new2.c new file mode 100644 index 00000000..c98c697f --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_new2.c @@ -0,0 +1,70 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "funky.h" +#include "stanky.h" +#include + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_custom_setup(); +} + +/*=======Suite Teardown=====*/ +static int suite_teardown(int num_failures) +{ +a_custom_teardown(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return suite_teardown(UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_param.c b/src/subprojects/unity/test/expectdata/testsample_param.c new file mode 100644 index 00000000..adf6c262 --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_param.c @@ -0,0 +1,58 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST_NO_ARGS +#define RUN_TEST(TestFunc, TestLineNum, ...) \ +{ \ + Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(__VA_ARGS__); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "funky.h" +#include "stanky.h" +#include + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS); + RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS); + RUN_TEST(test_TheThirdThingToTest, 53, RUN_TEST_NO_ARGS); + RUN_TEST(test_TheFourthThingToTest, 58, RUN_TEST_NO_ARGS); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_run1.c b/src/subprojects/unity/test/expectdata/testsample_run1.c new file mode 100644 index 00000000..7dcd3fdf --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_run1.c @@ -0,0 +1,67 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "CException.h" +#include "one.h" +#include "two.h" +#include "funky.h" +#include "stanky.h" +#include + +int GlobalExpectCount; +int GlobalVerifyOrder; +char* GlobalOrderError; + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_run2.c b/src/subprojects/unity/test/expectdata/testsample_run2.c new file mode 100644 index 00000000..c98c697f --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_run2.c @@ -0,0 +1,70 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + setUp(); \ + TestFunc(); \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "funky.h" +#include "stanky.h" +#include + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_custom_setup(); +} + +/*=======Suite Teardown=====*/ +static int suite_teardown(int num_failures) +{ +a_custom_teardown(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return suite_teardown(UnityEnd()); +} diff --git a/src/subprojects/unity/test/expectdata/testsample_yaml.c b/src/subprojects/unity/test/expectdata/testsample_yaml.c new file mode 100644 index 00000000..3316024d --- /dev/null +++ b/src/subprojects/unity/test/expectdata/testsample_yaml.c @@ -0,0 +1,71 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ + +/*=======Test Runner Used To Run Each Test Below=====*/ +#define RUN_TEST(TestFunc, TestLineNum) \ +{ \ + Unity.CurrentTestName = #TestFunc; \ + Unity.CurrentTestLineNumber = TestLineNum; \ + Unity.NumberOfTests++; \ + if (TEST_PROTECT()) \ + { \ + CEXCEPTION_T e; \ + Try { \ + setUp(); \ + TestFunc(); \ + } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \ + } \ + if (TEST_PROTECT() && !TEST_IS_IGNORED) \ + { \ + tearDown(); \ + } \ + UnityConcludeTest(); \ +} + +/*=======Automagically Detected Files To Include=====*/ +#include "unity.h" +#include +#include +#include "CException.h" +#include "two.h" +#include "three.h" +#include +#include "funky.h" +#include "stanky.h" +#include + +/*=======External Functions This Runner Calls=====*/ +extern void setUp(void); +extern void tearDown(void); +extern void test_TheFirstThingToTest(void); +extern void test_TheSecondThingToTest(void); +extern void test_TheThirdThingToTest(void); +extern void test_TheFourthThingToTest(void); + + +/*=======Suite Setup=====*/ +static int suite_setup(void) +{ +a_yaml_setup(); +} + +/*=======Test Reset Option=====*/ +void resetTest(void); +void resetTest(void) +{ + tearDown(); + setUp(); +} + + +/*=======MAIN=====*/ +int main(void) +{ + suite_setup(); + UnityBegin("testdata/testsample.c"); + RUN_TEST(test_TheFirstThingToTest, 21); + RUN_TEST(test_TheSecondThingToTest, 43); + RUN_TEST(test_TheThirdThingToTest, 53); + RUN_TEST(test_TheFourthThingToTest, 58); + + return (UnityEnd()); +} diff --git a/src/subprojects/unity/test/rakefile b/src/subprojects/unity/test/rakefile new file mode 100644 index 00000000..7747f305 --- /dev/null +++ b/src/subprojects/unity/test/rakefile @@ -0,0 +1,164 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +$verbose = false +$extra_paths = [] + +require 'rake' +require 'rake/clean' +require_relative 'rakefile_helper' +require 'rspec/core/rake_task' + +TEMP_DIRS = [ + File.join(__dir__, 'build'), + File.join(__dir__, 'sandbox') +] + +TEMP_DIRS.each do |dir| + directory(dir) + CLOBBER.include(dir) +end + +task :prepare_for_tests => TEMP_DIRS + +include RakefileHelpers + +# Load proper GCC as defult configuration +DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml' +configure_toolchain(DEFAULT_CONFIG_FILE) + +############# ALL THE SELF-TESTS WE CAN PERFORM +namespace :test do + desc "Build and test Unity" + task :all => [:clean, :prepare_for_tests, 'test:scripts', 'test:unit', :style, 'test:fixture', 'test:memory', 'test:summary'] + task :ci => [:clean, :prepare_for_tests, 'test:scripts', 'test:unit', :style, 'test:make', 'test:fixture', 'test:memory', 'test:summary'] + + desc "Test unity with its own unit tests" + task :unit => [:prepare_for_tests] do + run_tests unit_test_files + end + + namespace :unit do + unit_test_files.each do |f| + desc "test this unit only" + task File.basename(f,'.c').sub('test_unity_','') => [:prepare_for_tests] do + run_tests [f] + end + end + end + + desc "Test unity's helper scripts" + task :scripts => [:prepare_for_tests] do + Dir['tests/test_*.rb'].each do |scriptfile| + require "./"+scriptfile + end + end + + desc "Test unity triggered from make" + task :make => [:prepare_for_tests] do + run_make_tests() + end + + desc "Test unity fixture addon" + task :fixture => [:prepare_for_tests] do + test_fixtures() + end + + desc "Test unity memory addon" + task :memory => [:prepare_for_tests] do + test_memory() + end + + desc "Test unity examples" + task :examples => [:prepare_for_tests] do + execute("cd ../examples/example_1 && make -s ci", false) + execute("cd ../examples/example_2 && make -s ci", false) + execute("cd ../examples/example_3 && rake", false) + end + + desc "Run all rspecs" + RSpec::Core::RakeTask.new(:spec) do |t| + t.pattern = 'spec/**/*_spec.rb' + end + + desc "Generate test summary" + task :summary do + report_summary + end +end + +###################### Shorthand for many common tasks +task :ci => ['test:ci'] +task :all => ['test:all'] +task :default => [:clobber, :all] + +desc "Load configuration" +task :config, :config_file do |t, args| + configure_toolchain(args[:config_file]) +end + +task :no_color do + $colour_output = false +end + +task :verbose do + $verbose = true +end + +################### CODING STYLE VALIDATION +namespace :style do + desc "Check style" + task :check do + report "\nVERIFYING RUBY STYLE" + report execute("rubocop ../auto ../examples ../extras --config .rubocop.yml", true) + report "Styling Ruby:PASS" + end + + namespace :check do + Dir['../**/*.rb'].each do |f| + filename = File.basename(f, '.rb') + #desc "Check Style of #{filename}" + task filename.to_sym => ['style:clean'] do + report execute("rubocop #{f} --color --config .rubocop.yml", true) + report "Style Checked for #{f}" + end + end + end + + desc "Fix Style of all C Code" + task :c do + run_astyle("../src/*.* ../extras/fixture/src/*.*") + end + + namespace :c do + Dir['../{src,extras/**}/*.{c,h}'].each do |f| + filename = File.basename(f)[0..-3] + #desc "Check Style of #{filename}" + task filename.to_sym do + run_astyle f + end + end + end + + desc "Attempt to Autocorrect style" + task :auto => ['style:clean'] do + execute("rubocop ../auto ../examples ../extras --auto-correct --config .rubocop.yml") + report "Autocorrected What We Could." + end + + desc "Update style todo list" + task :todo => ['style:clean'] do + execute("rubocop ../auto ../examples ../extras --auto-gen-config --config .rubocop.yml") + report "Updated Style TODO List." + end + + task :clean do + File.delete(".rubocop_todo.yml") if File.exists?(".rubocop_todo.yml") + end +end + +task :style => ['style:check'] diff --git a/src/subprojects/unity/test/rakefile_helper.rb b/src/subprojects/unity/test/rakefile_helper.rb new file mode 100644 index 00000000..80a4976d --- /dev/null +++ b/src/subprojects/unity/test/rakefile_helper.rb @@ -0,0 +1,316 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require 'fileutils' +require_relative '../auto/unity_test_summary' +require_relative '../auto/generate_test_runner' +require_relative '../auto/colour_reporter' +require_relative '../auto/yaml_helper' + +module RakefileHelpers + C_EXTENSION = '.c'.freeze + def load_configuration(config_file) + return if $configured + + $cfg_file = "targets/#{config_file}" unless config_file =~ /[\\|\/]/ + $cfg = YamlHelper.load_file($cfg_file) + $colour_output = false unless $cfg['colour'] + $configured = true if config_file != DEFAULT_CONFIG_FILE + end + + def configure_clean + CLEAN.include('build/*.*') + end + + def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) + config_file += '.yml' unless config_file =~ /\.yml$/ + config_file = config_file unless config_file =~ /[\\|\/]/ + load_configuration(config_file) + configure_clean + end + + def unit_test_files + path = 'tests/test*' + C_EXTENSION + path.tr!('\\', '/') + FileList.new(path) + end + + def local_include_dirs + include_dirs = $cfg[:paths][:includes] || [] + include_dirs += $cfg[:paths][:source] || [] + include_dirs += $cfg[:paths][:test] || [] + include_dirs += $cfg[:paths][:support] || [] + include_dirs.delete_if { |dir| dir.is_a?(Array) } + include_dirs + end + + def extract_headers(filename) + includes = [] + lines = File.readlines(filename) + lines.each do |line| + m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/) + includes << m[1] unless m.nil? + end + includes + end + + def find_source_file(header, paths) + paths.each do |dir| + src_file = dir + header.ext(C_EXTENSION) + return src_file if File.exist?(src_file) + end + nil + end + + def tackit(strings) + result = if strings.is_a?(Array) + "\"#{strings.join}\"" + else + strings + end + result + end + + def squash(prefix, items) + result = '' + items.each { |item| result += " #{prefix}#{tackit(item)}" } + result + end + + def should(behave, &block) + if block + puts 'Should ' + behave + yield block + else + puts "UNIMPLEMENTED CASE: Should #{behave}" + end + end + + def build_command_string(hash, values, defines = nil) + + # Replace named and numbered slots + args = [] + hash[:arguments].each do |arg| + if arg.include? '$' + if arg.include? ': COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + pattern = arg.gsub(': COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE','') + [ File.join('..','src') ].each do |f| + args << pattern.gsub(/\$/,f) + end + + elsif arg.include? ': COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + pattern = arg.gsub(': COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR','') + [ $extra_paths, 'src', File.join('tests'), File.join('testdata'), $cfg[:paths][:support] ].flatten.uniq.compact.each do |f| + args << pattern.gsub(/\$/,f) + end + + elsif arg.include? ': COLLECTION_DEFINES_TEST_AND_VENDOR' + pattern = arg.gsub(': COLLECTION_DEFINES_TEST_AND_VENDOR','') + [ $cfg[:defines][:test], defines ].flatten.uniq.compact.each do |f| + args << pattern.gsub(/\$/,f) + end + + elsif arg =~ /\$\{(\d+)\}/ + i = $1.to_i - 1 + if (values[i].is_a?(Array)) + values[i].each {|v| args << arg.gsub(/\$\{\d+\}/, v)} + else + args << arg.gsub(/\$\{(\d)+\}/, values[i] || '') + end + + else + args << arg + + end + else + args << arg + end + end + + # Build Command + return tackit(hash[:executable]) + squash('', args) + end + + def compile(file, defines = []) + out_file = File.join('build', File.basename(file, C_EXTENSION)) + $cfg[:extension][:object] + cmd_str = build_command_string( $cfg[:tools][:test_compiler], [ file, out_file ], defines ) + execute(cmd_str) + out_file + end + + def link_it(exe_name, obj_list) + exe_name = File.join('build', File.basename(exe_name)) + cmd_str = build_command_string( $cfg[:tools][:test_linker], [ obj_list, exe_name ] ) + execute(cmd_str) + end + + def runtest(bin_name, ok_to_fail = false, extra_args = nil) + bin_name = File.join('build', File.basename(bin_name)) + extra_args = extra_args.nil? ? "" : " " + extra_args + if $cfg[:tools][:test_fixture] + cmd_str = build_command_string( $cfg[:tools][:test_fixture], [ bin_name, extra_args ] ) + else + cmd_str = bin_name + extra_args + end + execute(cmd_str, ok_to_fail) + end + + def run_astyle(style_what) + report "Styling C Code..." + command = "AStyle " \ + "--style=allman --indent=spaces=4 --indent-switches --indent-preproc-define --indent-preproc-block " \ + "--pad-oper --pad-comma --unpad-paren --pad-header " \ + "--align-pointer=type --align-reference=name " \ + "--add-brackets --mode=c --suffix=none " \ + "#{style_what}" + execute(command, false) + report "Styling C:PASS" + end + + def execute(command_string, ok_to_fail = false) + report command_string if $verbose + output = `#{command_string}`.chomp + report(output) if ($verbose && !output.nil? && !output.empty?) || (!$?.nil? && !$?.exitstatus.zero? && !ok_to_fail) + raise "Command failed. (Returned #{$?.exitstatus})" if !$?.nil? && !$?.exitstatus.zero? && !ok_to_fail + output + end + + def report_summary + summary = UnityTestSummary.new + summary.root = __dir__ + results_glob = File.join('build','*.test*') + results_glob.tr!('\\', '/') + results = Dir[results_glob] + summary.targets = results + report summary.run + end + + def save_test_results(test_base, output) + test_results = File.join('build',test_base) + if output.match(/OK$/m).nil? + test_results += '.testfail' + else + report output unless $verbose # Verbose already prints this line, as does a failure + test_results += '.testpass' + end + File.open(test_results, 'w') { |f| f.print output } + end + + def test_fixtures() + report "\nRunning Fixture Addon" + + # Get a list of all source files needed + src_files = Dir[File.join('..','extras','fixture','src','*.c')] + src_files += Dir[File.join('..','extras','fixture','test','*.c')] + src_files += Dir[File.join('..','extras','fixture','test','main','*.c')] + src_files += Dir[File.join('..','extras','memory','src','*.c')] + src_files << File.join('..','src','unity.c') + + # Build object files + $extra_paths = [File.join('..','extras','fixture','src'), File.join('..','extras','memory','src')] + obj_list = src_files.map { |f| compile(f, ['UNITY_SKIP_DEFAULT_RUNNER', 'UNITY_FIXTURE_NO_EXTRAS']) } + + # Link the test executable + test_base = File.basename('framework_test', C_EXTENSION) + link_it(test_base, obj_list) + + # Run and collect output + output = runtest(test_base + " -v -r") + save_test_results(test_base, output) + end + + def test_memory() + { 'w_malloc' => [], + 'wo_malloc' => ['UNITY_EXCLUDE_STDLIB_MALLOC'] + }.each_pair do |name, defs| + report "\nRunning Memory Addon #{name}" + + # Get a list of all source files needed + src_files = Dir[File.join('..','extras','memory','src','*.c')] + src_files += Dir[File.join('..','extras','memory','test','*.c')] + src_files += Dir[File.join('..','extras','memory','test','main','*.c')] + src_files << File.join('..','src','unity.c') + + # Build object files + $extra_paths = [File.join('..','extras','memory','src')] + obj_list = src_files.map { |f| compile(f, defs) } + + # Link the test executable + test_base = File.basename("memory_test_#{name}", C_EXTENSION) + link_it(test_base, obj_list) + + # Run and collect output + output = runtest(test_base) + save_test_results(test_base, output) + end + end + + def run_tests(test_files) + report "\nRunning Unity system tests" + + include_dirs = local_include_dirs + + # Build and execute each unit test + test_files.each do |test| + + # Drop Out if we're skipping this type of test + if $cfg[:skip_tests] + if $cfg[:skip_tests].include?(:parameterized) && test.match(/parameterized/) + report("Skipping Parameterized Tests for this Target:IGNORE") + next + end + end + + report "\nRunning Tests in #{test}" + obj_list = [] + test_defines = [] + + # Detect dependencies and build required modules + extract_headers(test).each do |header| + # Compile corresponding source file if it exists + src_file = find_source_file(header, include_dirs) + + obj_list << compile(src_file, test_defines) unless src_file.nil? + end + + # Build the test runner (generate if configured to do so) + test_base = File.basename(test, C_EXTENSION) + runner_name = test_base + '_Runner.c' + runner_path = File.join('build',runner_name) + + options = $cfg[:unity] + options[:use_param_tests] = test =~ /parameterized/ ? true : false + UnityTestRunnerGenerator.new(options).run(test, runner_path) + obj_list << compile(runner_path, test_defines) + + # Build the test module + obj_list << compile(test, test_defines) + + # Link the test executable + link_it(test_base, obj_list) + + # Execute unit test and generate results file + output = runtest(test_base) + save_test_results(test_base, output) + end + end + + def run_make_tests() + [ "make -s", # test with all defaults + #"make -s DEBUG=-m32", # test 32-bit architecture with 64-bit support + #"make -s DEBUG=-m32 UNITY_SUPPORT_64=", # test 32-bit build without 64-bit types + "make -s UNITY_INCLUDE_DOUBLE= ", # test without double + "cd #{File.join("..","extras","fixture",'test')} && make -s default noStdlibMalloc", + "cd #{File.join("..","extras","fixture",'test')} && make -s C89", + "cd #{File.join("..","extras","memory",'test')} && make -s default noStdlibMalloc", + "cd #{File.join("..","extras","memory",'test')} && make -s C89", + ].each do |cmd| + report "Testing '#{cmd}'" + execute(cmd, false) + end + end +end diff --git a/src/subprojects/unity/test/spec/generate_module_existing_file_spec.rb b/src/subprojects/unity/test/spec/generate_module_existing_file_spec.rb new file mode 100644 index 00000000..f4dd13e3 --- /dev/null +++ b/src/subprojects/unity/test/spec/generate_module_existing_file_spec.rb @@ -0,0 +1,164 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require '../auto/generate_module.rb' +require 'fileutils' + +def touch_src(file) + FileUtils.touch "sandbox/src/#{file}" +end + +def touch_test(file) + FileUtils.touch "sandbox/test/#{file}" +end + +def create_src_with_known_content(file) + File.open("sandbox/src/#{file}", "w") {|f| f.write("the original #{file}")} +end + +def create_test_with_known_content(file) + File.open("sandbox/test/#{file}", "w") {|f| f.write("the original #{file}")} +end + +def expect_src_content_didnt_change(file) + expect(File.read("sandbox/src/#{file}")).to eq("the original #{file}") +end + +def expect_test_content_didnt_change(file) + expect(File.read("sandbox/test/#{file}")).to eq("the original #{file}") +end + +def expect_src_file_to_exist(file) + expect(File.exist?("sandbox/src/#{file}")).to be true +end + +def expect_test_file_to_exist(file) + expect(File.exist?("sandbox/test/#{file}")).to be true +end + +describe "UnityModuleGenerator" do + + before do + # clean sandbox and setup our "project" folders + FileUtils.rm_rf "sandbox" + FileUtils.mkdir_p "sandbox" + FileUtils.mkdir_p "sandbox/src" + FileUtils.mkdir_p "sandbox/test" + + @options = { + :path_src => "sandbox/src", + :path_tst => "sandbox/test", + } + end + + context "with src pattern" do + before do + @options[:pattern] = "src" + end + + it "fails when all files already exist" do + # create an existing triad of files + touch_src "meh.c" + touch_src "meh.h" + touch_test "Testmeh.c" + expect { + UnityModuleGenerator.new(@options).generate("meh") + }.to raise_error("ERROR: File meh already exists. Exiting.") + end + + it "creates the test file if the source and header files exist" do + # Create the existing files. + touch_src "meh.c" + touch_src "meh.h" + + UnityModuleGenerator.new(@options).generate("meh") + + expect_test_file_to_exist "Testmeh.c" + end + + it "does not alter existing files" do + # Create some files with known content. + create_src_with_known_content "meh.c" + create_src_with_known_content "meh.h" + + UnityModuleGenerator.new(@options).generate("meh") + + expect_src_content_didnt_change "meh.c" + expect_src_content_didnt_change "meh.c" + end + + it "does not alter existing test files" do + # Create some files with known content. + create_test_with_known_content "Testmeh.c" + + UnityModuleGenerator.new(@options).generate("meh") + + expect_test_content_didnt_change "Testmeh.c" + end + + end + + context "with mch pattern" do + before do + @options[:pattern] = "mch" + end + + it "fails when all files exist" do + touch_src "meh_model.c" + touch_src "meh_conductor.c" + touch_src "meh_hardware.c" + touch_src "meh_model.h" + touch_src "meh_conductor.h" + touch_src "meh_hardware.h" + touch_test "Testmeh_model.c" + touch_test "Testmeh_conductor.c" + touch_test "Testmeh_hardware.c" + expect { + UnityModuleGenerator.new(@options).generate("meh") + }.to raise_error("ERROR: File meh_model already exists. Exiting.") + end + + it "creates files that don't exist" do + touch_src "meh_model.c" + touch_src "meh_conductor.c" + touch_src "meh_hardware.c" + touch_src "meh_model.h" + touch_src "meh_conductor.h" + + UnityModuleGenerator.new(@options).generate("meh") + + expect_src_file_to_exist "meh_hardware.h" + expect_test_file_to_exist "Testmeh_model.c" + expect_test_file_to_exist "Testmeh_conductor.c" + expect_test_file_to_exist "Testmeh_hardware.c" + end + + it "does not alter existing source files" do + create_src_with_known_content "meh_model.c" + create_src_with_known_content "meh_model.c" + create_src_with_known_content "meh_model.c" + create_src_with_known_content "meh_model.h" + create_src_with_known_content "meh_model.c" + + UnityModuleGenerator.new(@options).generate("meh") + + expect_src_content_didnt_change "meh_model.c" + expect_src_content_didnt_change "meh_model.c" + expect_src_content_didnt_change "meh_model.c" + expect_src_content_didnt_change "meh_model.c" + end + + it "does not alter existing test files" do + create_test_with_known_content "Testmeh_model.c" + + UnityModuleGenerator.new(@options).generate("meh") + + expect_test_content_didnt_change "Testmeh_model.c" + end + + end +end diff --git a/src/subprojects/unity/test/targets/ansi.yml b/src/subprojects/unity/test/targets/ansi.yml new file mode 100644 index 00000000..fcc24557 --- /dev/null +++ b/src/subprojects/unity/test/targets/ansi.yml @@ -0,0 +1,51 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +colour: true +:unity: + :plugins: [] +:skip_tests: +- :parameterized +:tools: + :test_compiler: + :name: compiler + :executable: gcc + :arguments: + - "-c" + - "-m64" + - "-Wall" + - "-Wno-address" + - "-ansi" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: gcc + :arguments: + - "${1}" + - "-lm" + - "-m64" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:paths: + :test: + - src/ + - "../src/" + - testdata/ + - tests/ +:defines: + :test: + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + - UNITY_EXCLUDE_TESTING_NEW_COMMENTS + - UNITY_SUPPORT_64 diff --git a/src/subprojects/unity/test/targets/clang_file.yml b/src/subprojects/unity/test/targets/clang_file.yml new file mode 100644 index 00000000..f962ced3 --- /dev/null +++ b/src/subprojects/unity/test/targets/clang_file.yml @@ -0,0 +1,79 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: clang + :arguments: + - "-c" + - "-Wall" + - "-Wextra" + - "-Werror" + - "-Wcast-qual" + - "-Wconversion" + - "-Wdisabled-optimization" + - "-Wformat=2" + - "-Winit-self" + - "-Winline" + - "-Winvalid-pch" + - "-Wmissing-include-dirs" + - "-Wnonnull" + - "-Wpacked" + - "-Wpointer-arith" + - "-Wswitch-default" + - "-Wstrict-aliasing" + - "-Wstrict-overflow=5" + - "-Wuninitialized" + - "-Wunused" + - "-Wreturn-type" + - "-Wshadow" + - "-Wundef" + - "-Wwrite-strings" + - "-Wno-nested-externs" + - "-Wno-unused-parameter" + - "-Wno-variadic-macros" + - "-Wbad-function-cast" + - "-fms-extensions" + - "-fno-omit-frame-pointer" + - "-ffloat-store" + - "-fno-common" + - "-fstrict-aliasing" + - "-std=gnu99" + - "-pedantic" + - "-O0" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: clang + :arguments: + - "${1}" + - "-lm" + - "-m64" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:paths: + :test: + - src/ + - "../src/" + - testdata/ + - tests/ +:defines: + :test: + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_64 + - UNITY_OUTPUT_RESULTS_FILE diff --git a/src/subprojects/unity/test/targets/clang_strict.yml b/src/subprojects/unity/test/targets/clang_strict.yml new file mode 100644 index 00000000..1c82f624 --- /dev/null +++ b/src/subprojects/unity/test/targets/clang_strict.yml @@ -0,0 +1,79 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: clang + :arguments: + - "-c" + - "-Wall" + - "-Wextra" + - "-Werror" + - "-Wcast-qual" + - "-Wconversion" + - "-Wdisabled-optimization" + - "-Wformat=2" + - "-Winit-self" + - "-Winline" + - "-Winvalid-pch" + - "-Wmissing-include-dirs" + - "-Wnonnull" + - "-Wpacked" + - "-Wpointer-arith" + - "-Wswitch-default" + - "-Wstrict-aliasing" + - "-Wstrict-overflow=5" + - "-Wuninitialized" + - "-Wunused" + - "-Wreturn-type" + - "-Wshadow" + - "-Wundef" + - "-Wwrite-strings" + - "-Wno-nested-externs" + - "-Wno-unused-parameter" + - "-Wno-variadic-macros" + - "-Wbad-function-cast" + - "-fms-extensions" + - "-fno-omit-frame-pointer" + - "-fno-common" + - "-fstrict-aliasing" + - "-std=gnu99" + - "-pedantic" + - "-O0" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: clang + :arguments: + - "${1}" + - "-lm" + - "-m64" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:paths: + :test: + - src/ + - "../src/" + - testdata/ + - tests/ +:defines: + :test: + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + - UNITY_SUPPORT_64 + - UNITY_COMPARE_PTRS_ON_ZERO_ARRAY diff --git a/src/subprojects/unity/test/targets/gcc_32.yml b/src/subprojects/unity/test/targets/gcc_32.yml new file mode 100644 index 00000000..3375e4ee --- /dev/null +++ b/src/subprojects/unity/test/targets/gcc_32.yml @@ -0,0 +1,52 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: gcc + :arguments: + - "-c" + - "-m32" + - "-Wall" + - "-Wno-address" + - "-std=c99" + - "-pedantic" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: gcc + :arguments: + - "${1}" + - "-lm" + - "-m32" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:paths: + :test: + - src/ + - "../src/" + - testdata/ + - tests/ +:defines: + :test: + - UNITY_EXCLUDE_STDINT_H + - UNITY_EXCLUDE_LIMITS_H + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + - UNITY_INT_WIDTH=32 + - UNITY_LONG_WIDTH=32 diff --git a/src/subprojects/unity/test/targets/gcc_64.yml b/src/subprojects/unity/test/targets/gcc_64.yml new file mode 100644 index 00000000..55223ceb --- /dev/null +++ b/src/subprojects/unity/test/targets/gcc_64.yml @@ -0,0 +1,53 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: gcc + :arguments: + - "-c" + - "-m64" + - "-Wall" + - "-Wno-address" + - "-std=c99" + - "-pedantic" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: gcc + :arguments: + - "${1}" + - "-lm" + - "-m64" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:paths: + :test: + - src/ + - "../src/" + - testdata/ + - tests/ +:defines: + :test: + - UNITY_EXCLUDE_STDINT_H + - UNITY_EXCLUDE_LIMITS_H + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + - UNITY_SUPPORT_64 + - UNITY_INT_WIDTH=32 + - UNITY_LONG_WIDTH=64 diff --git a/src/subprojects/unity/test/targets/gcc_auto_limits.yml b/src/subprojects/unity/test/targets/gcc_auto_limits.yml new file mode 100644 index 00000000..9159b385 --- /dev/null +++ b/src/subprojects/unity/test/targets/gcc_auto_limits.yml @@ -0,0 +1,50 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: gcc + :arguments: + - "-c" + - "-m64" + - "-Wall" + - "-Wno-address" + - "-std=c99" + - "-pedantic" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: gcc + :arguments: + - "${1}" + - "-lm" + - "-m64" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:paths: + :test: + - src/ + - "../src/" + - testdata/ + - tests/ +:defines: + :test: + - UNITY_EXCLUDE_STDINT_H + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + - UNITY_SUPPORT_64 diff --git a/src/subprojects/unity/test/targets/gcc_auto_stdint.yml b/src/subprojects/unity/test/targets/gcc_auto_stdint.yml new file mode 100644 index 00000000..18221609 --- /dev/null +++ b/src/subprojects/unity/test/targets/gcc_auto_stdint.yml @@ -0,0 +1,62 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: gcc + :arguments: + - "-c" + - "-m64" + - "-Wall" + - "-Wno-address" + - "-std=c99" + - "-pedantic" + - "-Wextra" + - "-Werror" + - "-Wpointer-arith" + - "-Wcast-align" + - "-Wwrite-strings" + - "-Wswitch-default" + - "-Wunreachable-code" + - "-Winit-self" + - "-Wmissing-field-initializers" + - "-Wno-unknown-pragmas" + - "-Wstrict-prototypes" + - "-Wundef" + - "-Wold-style-definition" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: gcc + :arguments: + - "${1}" + - "-lm" + - "-m64" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:paths: + :test: + - src/ + - "../src/" + - testdata/ + - tests/ +:defines: + :test: + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + - UNITY_SUPPORT_64 diff --git a/src/subprojects/unity/test/targets/gcc_manual_math.yml b/src/subprojects/unity/test/targets/gcc_manual_math.yml new file mode 100644 index 00000000..22e69aa6 --- /dev/null +++ b/src/subprojects/unity/test/targets/gcc_manual_math.yml @@ -0,0 +1,50 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: gcc + :arguments: + - "-c" + - "-m64" + - "-Wall" + - "-Wno-address" + - "-std=c99" + - "-pedantic" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: gcc + :arguments: + - "${1}" + - "-lm" + - "-m64" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:paths: + :test: + - src/ + - "../src/" + - testdata/ + - tests/ +:defines: + :test: + - UNITY_EXCLUDE_MATH_H + - UNITY_INCLUDE_DOUBLE + - UNITY_SUPPORT_TEST_CASES + - UNITY_SUPPORT_64 diff --git a/src/subprojects/unity/test/targets/hitech_picc18.yml b/src/subprojects/unity/test/targets/hitech_picc18.yml new file mode 100644 index 00000000..547cb2b5 --- /dev/null +++ b/src/subprojects/unity/test/targets/hitech_picc18.yml @@ -0,0 +1,98 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +:cmock: + :plugins: [] + :includes: + - Types.h + :suite_teardown: | + if (num_failures) + _FAILED_TEST(); + else + _PASSED_TESTS(); + return 0; +colour: true +:tools: + :test_compiler: + :name: compiler + :executable: cd build && picc18 + :arguments: + - "--chip=18F87J10" + - "--ide=hitide" + - "--q" + - "--asmlist" + - "--codeoffset=0" + - "--emi=wordwrite" + - "--warn=0" + - "--errors=10" + - "--char=unsigned" + - "-Bl" + - "-G" + - "--cp=16" + - "--double=24" + - "-N255" + - "--opt=none" + - "-c" + - "-M" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - " ${2}" + :test_linker: + :name: linker + :executable: cd build && picc18 + :arguments: + - "${1}" + - "--chip=18F87J10" + - "--ide=hitide" + - "--cp=24" + - "--double=24" + - "-Lw" + - "--summary=mem,file" + - "--summary=+psect" + - "--summary=+hex" + - "--output=+intel" + - "--output=+mcof" + - "--runtime=+init" + - "--runtime=+clear" + - "--runtime=+clib" + - "--runtime=+keep" + - "-G" + - "-MIWasTheLastToBuild.map" + - "--warn=0" + - "-Bl" + - "-O ${2}" + :test_fixture: + :name: simulator + :executable: 'java -client -jar ' + :arguments: + - - C:\Program Files\HI-TECH Software\HI-TIDE\3.15\lib\ + - simpic18.jar + - 18F87J10 + - "${1}" +:extension: + :object: ".obj" + :executable: ".hex" +:paths: + :test: + - c:/Projects/NexGen/Prototypes/CMockTest/src/ + - c:/Projects/NexGen/Prototypes/CMockTest/mocks/ + - c:/CMock/src/ + - c:/CMock/examples/src/ + - c:/CMock/vendor/unity/src/ + - c:/CMock/vendor/unity/examples/helper/ + - tests\ +:defines: + :test: + - UNITY_INT_WIDTH=16 + - UNITY_POINTER_WIDTH=16 + - CMOCK_MEM_STATIC + - CMOCK_MEM_SIZE=3000 + - UNITY_SUPPORT_TEST_CASES + - _PICC18 diff --git a/src/subprojects/unity/test/targets/iar_arm_v4.yml b/src/subprojects/unity/test/targets/iar_arm_v4.yml new file mode 100644 index 00000000..26a0f462 --- /dev/null +++ b/src/subprojects/unity/test/targets/iar_arm_v4.yml @@ -0,0 +1,105 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +tools_root: C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - arm\bin\iccarm.exe + :arguments: + - "--dlib_config" + - - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - arm\lib\dl4tptinl8n.h + - "-z3" + - "--no_cse" + - "--no_unroll" + - "--no_inline" + - "--no_code_motion" + - "--no_tbaa" + - "--no_clustering" + - "--no_scheduling" + - "--debug" + - "--cpu_mode thumb" + - "--endian little" + - "--cpu ARM7TDMI" + - "--stack_align 4" + - "--interwork" + - "-e" + - "--silent" + - "--warnings_are_errors" + - "--fpu None" + - "--diag_suppress Pa050" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - common\bin\xlink.exe + :arguments: + - "${1}" + - "-rt" + - - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - arm\lib\dl4tptinl8n.r79 + - "-D_L_EXTMEM_START=0" + - "-D_L_EXTMEM_SIZE=0" + - "-D_L_HEAP_SIZE=120" + - "-D_L_STACK_SIZE=32" + - "-e_small_write=_formatted_write" + - "-s" + - __program_start + - "-f" + - - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - "\\arm\\config\\lnkarm.xcl" + - "-o ${2}" + :test_fixture: + :name: simulator + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - common\bin\CSpyBat.exe + :arguments: + - "--silent" + - - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - arm\bin\armproc.dll + - - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - arm\bin\armsim.dll + - "${1}" + - "--plugin" + - - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - arm\bin\armbat.dll + - "--backend" + - "-B" + - "-p" + - - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - arm\config\ioat91sam7X256.ddf + - "-d" + - sim +:extension: + :object: ".r79" + :executable: ".d79" +:paths: + :test: + - - C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\ + - arm\inc\ + - src\ + - "..\\src\\" + - testdata/ + - tests\ + - vendor\unity\src\ +:defines: + :test: + - UNITY_SUPPORT_64 + - UNITY_SUPPORT_TEST_CASES diff --git a/src/subprojects/unity/test/targets/iar_arm_v5.yml b/src/subprojects/unity/test/targets/iar_arm_v5.yml new file mode 100644 index 00000000..afd51775 --- /dev/null +++ b/src/subprojects/unity/test/targets/iar_arm_v5.yml @@ -0,0 +1,99 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +tools_root: C:\Program Files\IAR Systems\Embedded Workbench 5.3\ +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\iccarm.exe + :arguments: + - "--dlib_config" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\inc\DLib_Config_Normal.h + - "--no_cse" + - "--no_unroll" + - "--no_inline" + - "--no_code_motion" + - "--no_tbaa" + - "--no_clustering" + - "--no_scheduling" + - "--debug" + - "--cpu_mode thumb" + - "--endian=little" + - "--cpu=ARM7TDMI" + - "--interwork" + - "--warnings_are_errors" + - "--fpu=None" + - "--diag_suppress=Pa050" + - "--diag_suppress=Pe111" + - "-e" + - "-On" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\ilinkarm.exe + :arguments: + - "${1}" + - "--redirect _Printf=_PrintfLarge" + - "--redirect _Scanf=_ScanfSmall" + - "--semihosting" + - "--entry __iar_program_start" + - "--config" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\config\generic.icf + - "-o ${2}" + :test_fixture: + :name: simulator + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - common\bin\CSpyBat.exe + :arguments: + - "--silent" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\armproc.dll + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\armsim.dll + - "${1}" + - "--plugin" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\armbat.dll + - "--backend" + - "-B" + - "-p" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\config\debugger\atmel\ioat91sam7X256.ddf + - "-d" + - sim +:extension: + :object: ".r79" + :executable: ".out" +:paths: + :test: + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\inc\ + - src\ + - "..\\src\\" + - testdata/ + - tests\ + - vendor\unity\src\ + - iar\iar_v5\incIAR\ +:defines: + :test: + - UNITY_SUPPORT_64 + - UNITY_SUPPORT_TEST_CASES diff --git a/src/subprojects/unity/test/targets/iar_arm_v5_3.yml b/src/subprojects/unity/test/targets/iar_arm_v5_3.yml new file mode 100644 index 00000000..afd51775 --- /dev/null +++ b/src/subprojects/unity/test/targets/iar_arm_v5_3.yml @@ -0,0 +1,99 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +tools_root: C:\Program Files\IAR Systems\Embedded Workbench 5.3\ +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\iccarm.exe + :arguments: + - "--dlib_config" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\inc\DLib_Config_Normal.h + - "--no_cse" + - "--no_unroll" + - "--no_inline" + - "--no_code_motion" + - "--no_tbaa" + - "--no_clustering" + - "--no_scheduling" + - "--debug" + - "--cpu_mode thumb" + - "--endian=little" + - "--cpu=ARM7TDMI" + - "--interwork" + - "--warnings_are_errors" + - "--fpu=None" + - "--diag_suppress=Pa050" + - "--diag_suppress=Pe111" + - "-e" + - "-On" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\ilinkarm.exe + :arguments: + - "${1}" + - "--redirect _Printf=_PrintfLarge" + - "--redirect _Scanf=_ScanfSmall" + - "--semihosting" + - "--entry __iar_program_start" + - "--config" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\config\generic.icf + - "-o ${2}" + :test_fixture: + :name: simulator + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - common\bin\CSpyBat.exe + :arguments: + - "--silent" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\armproc.dll + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\armsim.dll + - "${1}" + - "--plugin" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\bin\armbat.dll + - "--backend" + - "-B" + - "-p" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\config\debugger\atmel\ioat91sam7X256.ddf + - "-d" + - sim +:extension: + :object: ".r79" + :executable: ".out" +:paths: + :test: + - - C:\Program Files\IAR Systems\Embedded Workbench 5.3\ + - arm\inc\ + - src\ + - "..\\src\\" + - testdata/ + - tests\ + - vendor\unity\src\ + - iar\iar_v5\incIAR\ +:defines: + :test: + - UNITY_SUPPORT_64 + - UNITY_SUPPORT_TEST_CASES diff --git a/src/subprojects/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml b/src/subprojects/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml new file mode 100644 index 00000000..b4aa5d8e --- /dev/null +++ b/src/subprojects/unity/test/targets/iar_armcortex_LM3S9B92_v5_4.yml @@ -0,0 +1,97 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +tools_root: C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: + - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\bin\iccarm.exe + :arguments: + - "--diag_suppress=Pa050" + - "--debug" + - "--endian=little" + - "--cpu=Cortex-M3" + - "--no_path_in_file_macros" + - "-e" + - "--fpu=None" + - "--dlib_config" + - - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\inc\DLib_Config_Normal.h + - "--interwork" + - "--warnings_are_errors" + - "-Oh" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: + - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\bin\ilinkarm.exe + :arguments: + - "${1}" + - "--redirect _Printf=_PrintfLarge" + - "--redirect _Scanf=_ScanfSmall" + - "--semihosting" + - "--entry __iar_program_start" + - "--config" + - - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\config\generic.icf + - "-o ${2}" + :test_fixture: + :name: simulator + :executable: + - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - common\bin\CSpyBat.exe + :arguments: + - - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\bin\armproc.dll + - - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\bin\armsim2.dll + - "${1}" + - "--plugin" + - - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\bin\armbat.dll + - "--backend" + - "-B" + - "--endian=little" + - "--cpu=Cortex-M3" + - "--fpu=None" + - "-p" + - - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\config\debugger\TexasInstruments\iolm3sxxxx.ddf + - "--semihosting" + - "--device=LM3SxBxx" +:extension: + :object: ".r79" + :executable: ".out" +:paths: + :test: + - - C:\Program Files (x86)\IAR Systems\Embedded Workbench 5.4 Kickstart\ + - arm\inc\ + - src\ + - "..\\src\\" + - testdata/ + - tests\ + - vendor\unity\src\ + - iar\iar_v5\incIAR\ +:defines: + :test: + - ewarm + - PART_LM3S9B92 + - TARGET_IS_TEMPEST_RB1 + - USE_ROM_DRIVERS + - UART_BUFFERED + - UNITY_SUPPORT_64 diff --git a/src/subprojects/unity/test/targets/iar_cortexm3_v5.yml b/src/subprojects/unity/test/targets/iar_cortexm3_v5.yml new file mode 100644 index 00000000..e27b0f6b --- /dev/null +++ b/src/subprojects/unity/test/targets/iar_cortexm3_v5.yml @@ -0,0 +1,101 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +tools_root: C:\Program Files\IAR Systems\Embedded Workbench 5.4\ +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\bin\iccarm.exe + :arguments: + - "--dlib_config" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\inc\DLib_Config_Normal.h + - "--no_cse" + - "--no_unroll" + - "--no_inline" + - "--no_code_motion" + - "--no_tbaa" + - "--no_clustering" + - "--no_scheduling" + - "--debug" + - "--cpu_mode thumb" + - "--endian=little" + - "--cpu=Cortex-M3" + - "--interwork" + - "--warnings_are_errors" + - "--fpu=None" + - "--diag_suppress=Pa050" + - "--diag_suppress=Pe111" + - "-e" + - "-On" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\bin\ilinkarm.exe + :arguments: + - "${1}" + - "--redirect _Printf=_PrintfLarge" + - "--redirect _Scanf=_ScanfSmall" + - "--semihosting" + - "--entry __iar_program_start" + - "--config" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\config\generic_cortex.icf + - "-o ${2}" + :test_fixture: + :name: simulator + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - common\bin\CSpyBat.exe + :arguments: + - "--silent" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\bin\armproc.dll + - - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\bin\armsim.dll + - "${1}" + - "--plugin" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\bin\armbat.dll + - "--backend" + - "-B" + - "-p" + - - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\config\debugger\ST\iostm32f107xx.ddf + - "--cpu=Cortex-M3" + - "-d" + - sim +:extension: + :object: ".r79" + :executable: ".out" +:paths: + :test: + - - C:\Program Files\IAR Systems\Embedded Workbench 5.4\ + - arm\inc\ + - src\ + - "..\\src\\" + - testdata/ + - tests\ + - vendor\unity\src\ + - iar\iar_v5\incIAR\ +:defines: + :test: + - IAR + - UNITY_SUPPORT_64 + - UNITY_SUPPORT_TEST_CASES diff --git a/src/subprojects/unity/test/targets/iar_msp430.yml b/src/subprojects/unity/test/targets/iar_msp430.yml new file mode 100644 index 00000000..041ebdaf --- /dev/null +++ b/src/subprojects/unity/test/targets/iar_msp430.yml @@ -0,0 +1,119 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +tools_root: C:\Program Files\IAR Systems\Embedded Workbench 5.3 MSP430\ +core_root: &1 +- C:\Program Files\IAR Systems\Embedded Workbench 5.3 MSP430\ +- 430\ +core_bin: &2 +- *1 +- bin\ +core_config: &4 +- *1 +- config\ +core_lib: &3 +- *1 +- lib\ +core_inc: &5 +- *1 +- inc\ +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: + - *2 + - icc430.exe + :arguments: + - "--dlib_config" + - - *3 + - dlib\dl430fn.h + - "--no_cse" + - "--no_unroll" + - "--no_inline" + - "--no_code_motion" + - "--no_tbaa" + - "--debug" + - "-e" + - "-Ol" + - "--multiplier=16" + - "--double=32" + - "--diag_suppress Pa050" + - "--diag_suppress Pe111" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: + - *2 + - xlink.exe + :arguments: + - "${1}" + - "-rt" + - - *3 + - dlib\dl430fn.r43 + - "-e_PrintfTiny=_Printf" + - "-e_ScanfSmall=_Scanf" + - "-s __program_start" + - "-D_STACK_SIZE=50" + - "-D_DATA16_HEAP_SIZE=50" + - "-D_DATA20_HEAP_SIZE=50" + - "-f" + - - *4 + - lnk430f5438.xcl + - "-f" + - - *4 + - multiplier.xcl + - "-o ${2}" + :test_fixture: + :name: simulator + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 5.3 MSP430\ + - common\bin\CSpyBat.exe + :arguments: + - "--silent" + - - *2 + - 430proc.dll + - - *2 + - 430sim.dll + - "${1}" + - "--plugin" + - - *2 + - 430bat.dll + - "--backend -B" + - "--cpu MSP430F5438" + - "-p" + - - *4 + - MSP430F5438.ddf + - "-d sim" +:extension: + :object: ".r43" + :executable: ".d79" +:paths: + :test: + - *5 + - - *5 + - dlib + - - *3 + - dlib + - src\ + - "../src/" + - testdata/ + - tests\ + - vendor\unity\src +:defines: + :test: + - __MSP430F149__ + - INT_WIDTH=16 + - UNITY_EXCLUDE_FLOAT + - UNITY_SUPPORT_TEST_CASES diff --git a/src/subprojects/unity/test/targets/iar_sh2a_v6.yml b/src/subprojects/unity/test/targets/iar_sh2a_v6.yml new file mode 100644 index 00000000..21761d4b --- /dev/null +++ b/src/subprojects/unity/test/targets/iar_sh2a_v6.yml @@ -0,0 +1,106 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +--- +tools_root: C:\Program Files\IAR Systems\Embedded Workbench 6.0\ +colour: true +:unity: + :plugins: [] +:tools: + :test_compiler: + :name: compiler + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\bin\iccsh.exe + :arguments: + - "-e" + - "--char_is_signed" + - "-Ol" + - "--no_cse" + - "--no_unroll" + - "--no_inline" + - "--no_code_motion" + - "--no_tbaa" + - "--no_scheduling" + - "--no_clustering" + - "--debug" + - "--dlib_config" + - - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\inc\DLib_Product.h + - "--double=32" + - "--code_model=huge" + - "--data_model=huge" + - "--core=sh2afpu" + - "--warnings_affect_exit_code" + - "--warnings_are_errors" + - "--mfc" + - "--use_unix_directory_separators" + - "--diag_suppress=Pe161" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\bin\ilinksh.exe + :arguments: + - "${1}" + - "--redirect __Printf=__PrintfSmall" + - "--redirect __Scanf=__ScanfSmall" + - "--config" + - - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\config\generic.icf + - "--config_def _CSTACK_SIZE=0x800" + - "--config_def _HEAP_SIZE=0x800" + - "--config_def _INT_TABLE=0x10" + - "--entry __iar_program_start" + - "--debug_lib" + - "-o ${2}" + :test_fixture: + :name: simulator + :executable: + - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - common\bin\CSpyBat.exe + :arguments: + - "--silent" + - - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\bin\shproc.dll + - - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\bin\shsim.dll + - "${1}" + - "--plugin" + - - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\bin\shbat.dll + - "--backend" + - "-B" + - "--core sh2afpu" + - "-p" + - - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\config\debugger\io7264.ddf + - "-d" + - sim +:extension: + :object: ".o" + :executable: ".out" +:paths: + :test: + - - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\inc\ + - - C:\Program Files\IAR Systems\Embedded Workbench 6.0\ + - sh\inc\c + - src\ + - "..\\src\\" + - testdata/ + - tests\ + - vendor\unity\src\ +:defines: + :test: + - UNITY_SUPPORT_64 + - UNITY_SUPPORT_TEST_CASES diff --git a/src/subprojects/unity/test/testdata/CException.h b/src/subprojects/unity/test/testdata/CException.h new file mode 100644 index 00000000..0c11eaaa --- /dev/null +++ b/src/subprojects/unity/test/testdata/CException.h @@ -0,0 +1,18 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef CEXCEPTION_H +#define CEXCEPTION_H + +#define CEXCEPTION_BEING_USED 1 + +#define CEXCEPTION_NONE 0 +#define CEXCEPTION_T int e = 1; (void) +#define Try if (e) +#define Catch(a) if (!a) + +#endif diff --git a/src/subprojects/unity/test/testdata/Defs.h b/src/subprojects/unity/test/testdata/Defs.h new file mode 100644 index 00000000..aa5ed670 --- /dev/null +++ b/src/subprojects/unity/test/testdata/Defs.h @@ -0,0 +1,16 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef DEF_H +#define DEF_H + +#define EXTERN_DECL + +extern int CounterSuiteSetup; +extern int isArgumentOne(int i); + +#endif diff --git a/src/subprojects/unity/test/testdata/cmock.h b/src/subprojects/unity/test/testdata/cmock.h new file mode 100644 index 00000000..440220d0 --- /dev/null +++ b/src/subprojects/unity/test/testdata/cmock.h @@ -0,0 +1,21 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef CMOCK_H +#define CMOCK_H + +int CMockMemFreeFinalCounter = 0; +int mockMock_Init_Counter = 0; +int mockMock_Verify_Counter = 0; +int mockMock_Destroy_Counter = 0; + +void CMock_Guts_MemFreeFinal(void) { CMockMemFreeFinalCounter++; } +void mockMock_Init(void) { mockMock_Init_Counter++; } +void mockMock_Verify(void) { mockMock_Verify_Counter++; } +void mockMock_Destroy(void) { mockMock_Destroy_Counter++; } + +#endif diff --git a/src/subprojects/unity/test/testdata/mockMock.h b/src/subprojects/unity/test/testdata/mockMock.h new file mode 100644 index 00000000..ca65fc93 --- /dev/null +++ b/src/subprojects/unity/test/testdata/mockMock.h @@ -0,0 +1,20 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef MOCK_MOCK_H +#define MOCK_MOCK_H + +extern int mockMock_Init_Counter; +extern int mockMock_Verify_Counter; +extern int mockMock_Destroy_Counter; +extern int CMockMemFreeFinalCounter; + +void mockMock_Init(void); +void mockMock_Verify(void); +void mockMock_Destroy(void); + +#endif diff --git a/src/subprojects/unity/test/testdata/testRunnerGenerator.c b/src/subprojects/unity/test/testdata/testRunnerGenerator.c new file mode 100644 index 00000000..c10a96e6 --- /dev/null +++ b/src/subprojects/unity/test/testdata/testRunnerGenerator.c @@ -0,0 +1,204 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */ + +#include +#include "unity.h" +#include "Defs.h" + +#ifdef USE_CEXCEPTION +#include "CException.h" +#endif + +/* Notes about prefixes: + test - normal default prefix. these are "always run" tests for this procedure + spec - normal default prefix. required to run default setup/teardown calls. + should - normal default prefix. + qwiktest - custom prefix for when tests skip all setup/teardown calls. + custtest - custom prefix for when tests use custom setup/teardown calls. + paratest - custom prefix for when we want to verify parameterized tests. + extest - custom prefix only used during cexception + suitetest- custom prefix for when we want to use custom suite setup/teardown +*/ + +/* Include Passthroughs for Linking Tests */ +void putcharSpy(int c) { (void)putchar(c);} +void flushSpy(void) {} + +/* Global Variables Used During These Tests */ +int CounterSetup = 0; +int CounterTeardown = 0; +int CounterSuiteSetup = 0; + +void setUp(void) +{ + CounterSetup = 1; +} + +void tearDown(void) +{ + CounterTeardown = 1; +} + +void custom_setup(void) +{ + CounterSetup = 2; +} + +void custom_teardown(void) +{ + CounterTeardown = 2; +} + +/* +void test_OldSchoolCommentsShouldBeIgnored(void) +{ + TEST_ASSERT_FAIL("Old-School Comments Should Be Ignored"); +} +*/ + +void test_ThisTestAlwaysPasses(void) +{ + TEST_PASS(); +} + +void test_ThisTestAlwaysFails(void) +{ + TEST_FAIL_MESSAGE("This Test Should Fail"); +} + +void test_ThisTestAlwaysIgnored(void) +{ + TEST_IGNORE_MESSAGE("This Test Should Be Ignored"); +} + +void qwiktest_ThisTestPassesWhenNoSetupRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(0, CounterSetup, "Setup Was Unexpectedly Run"); +} + +void qwiktest_ThisTestPassesWhenNoTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(0, CounterTeardown, "Teardown Was Unexpectedly Run"); +} + +void spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(0, CounterSuiteSetup, "Suite Setup Was Unexpectedly Run"); +} + +void spec_ThisTestPassesWhenNormalSetupRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run"); +} + +void spec_ThisTestPassesWhenNormalTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run"); +} + +void custtest_ThisTestPassesWhenCustomSetupRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(2, CounterSetup, "Custom Setup Wasn't Run"); +} + +void custtest_ThisTestPassesWhenCustomTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(2, CounterTeardown, "Custom Teardown Wasn't Run"); +} + +#ifndef UNITY_EXCLUDE_TESTING_NEW_COMMENTS +//void test_NewStyleCommentsShouldBeIgnored(void) +//{ +// TEST_ASSERT_FAIL("New Style Comments Should Be Ignored"); +//} +#endif + +void test_NotBeConfusedByLongComplicatedStrings(void) +{ + const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n"; + + TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are The Same"); +} + +/* The next test should still appear even though we have this confusing nested comment thing going on http://looks_like_comments.com */ +void test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings(void) +{ + TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True"); + /* still should not break anything */ +} +/* nor should this */ + +void test_StillNotBeConfusedByLongComplicatedStrings(void) +{ + const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n"; + + TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are Still The Same"); +} + +void should_RunTestsStartingWithShouldByDefault(void) +{ + TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True"); +} + +TEST_CASE(25) +TEST_CASE(125) +TEST_CASE(5) +void paratest_ShouldHandleParameterizedTests(int Num) +{ + TEST_ASSERT_EQUAL_MESSAGE(0, (Num % 5), "All The Values Are Divisible By 5"); +} + +TEST_CASE(7) +void paratest_ShouldHandleParameterizedTests2(int Num) +{ + TEST_ASSERT_EQUAL_MESSAGE(7, Num, "The Only Call To This Passes"); +} + +void paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid(void) +{ + TEST_PASS(); +} + +TEST_CASE(17) +void paratest_ShouldHandleParameterizedTestsThatFail(int Num) +{ + TEST_ASSERT_EQUAL_MESSAGE(3, Num, "This call should fail"); +} + +int isArgumentOne(int i) +{ + return i == 1; +} + +TEST_CASE(isArgumentOne) +void paratest_WorksWithFunctionPointers(int function(int)) +{ + TEST_ASSERT_TRUE_MESSAGE(function(1), "Function should return True"); +} + +#ifdef USE_CEXCEPTION +void extest_ShouldHandleCExceptionInTest(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CEXCEPTION_BEING_USED, "Should be pulling in CException"); +} +#endif + +#ifdef USE_ANOTHER_MAIN +int custom_main(void); + +int main(void) +{ + return custom_main(); +} +#endif + +void suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CounterSuiteSetup, "Suite Setup Should Have Run"); +} diff --git a/src/subprojects/unity/test/testdata/testRunnerGeneratorSmall.c b/src/subprojects/unity/test/testdata/testRunnerGeneratorSmall.c new file mode 100644 index 00000000..bc9f7fcf --- /dev/null +++ b/src/subprojects/unity/test/testdata/testRunnerGeneratorSmall.c @@ -0,0 +1,73 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */ + +#include +#include "unity.h" +#include "Defs.h" + +TEST_SOURCE_FILE("some_file.c") + +/* Notes about prefixes: + test - normal default prefix. these are "always run" tests for this procedure + spec - normal default prefix. required to run default setup/teardown calls. +*/ + +/* Include Passthroughs for Linking Tests */ +void putcharSpy(int c) { (void)putchar(c);} +void flushSpy(void) {} + +/* Global Variables Used During These Tests */ +int CounterSetup = 0; +int CounterTeardown = 0; +int CounterSuiteSetup = 0; + +void setUp(void) +{ + CounterSetup = 1; +} + +void tearDown(void) +{ + CounterTeardown = 1; +} + +void custom_setup(void) +{ + CounterSetup = 2; +} + +void custom_teardown(void) +{ + CounterTeardown = 2; +} + +void test_ThisTestAlwaysPasses(void) +{ + TEST_PASS(); +} + +void test_ThisTestAlwaysFails(void) +{ + TEST_FAIL_MESSAGE("This Test Should Fail"); +} + +void test_ThisTestAlwaysIgnored(void) +{ + TEST_IGNORE_MESSAGE("This Test Should Be Ignored"); +} + +void spec_ThisTestPassesWhenNormalSetupRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run"); +} + +void spec_ThisTestPassesWhenNormalTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run"); +} diff --git a/src/subprojects/unity/test/testdata/testRunnerGeneratorWithMocks.c b/src/subprojects/unity/test/testdata/testRunnerGeneratorWithMocks.c new file mode 100644 index 00000000..adc2a295 --- /dev/null +++ b/src/subprojects/unity/test/testdata/testRunnerGeneratorWithMocks.c @@ -0,0 +1,200 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +/* This Test File Is Used To Verify Many Combinations Of Using the Generate Test Runner Script */ + +#include +#include "unity.h" +#include "Defs.h" +#include "mockMock.h" + +#ifdef USE_CEXCEPTION +#include "CException.h" +#endif + +/* Notes about prefixes: + test - normal default prefix. these are "always run" tests for this procedure + spec - normal default prefix. required to run default setup/teardown calls. + should - normal default prefix. + qwiktest - custom prefix for when tests skip all setup/teardown calls. + custtest - custom prefix for when tests use custom setup/teardown calls. + paratest - custom prefix for when we want to verify parameterized tests. + extest - custom prefix only used during cexception + suitetest- custom prefix for when we want to use custom suite setup/teardown +*/ + +/* Include Passthroughs for Linking Tests */ +void putcharSpy(int c) { (void)putchar(c);} +void flushSpy(void) {} + +/* Global Variables Used During These Tests */ +int CounterSetup = 0; +int CounterTeardown = 0; +int CounterSuiteSetup = 0; + +void setUp(void) +{ + CounterSetup = 1; +} + +void tearDown(void) +{ + CounterTeardown = 1; +} + +void custom_setup(void) +{ + CounterSetup = 2; +} + +void custom_teardown(void) +{ + CounterTeardown = 2; +} + +/* +void test_OldSchoolCommentsShouldBeIgnored(void) +{ + TEST_ASSERT_FAIL("Old-School Comments Should Be Ignored"); +} +*/ + +void test_ThisTestAlwaysPasses(void) +{ + TEST_PASS(); +} + +void test_ThisTestAlwaysFails(void) +{ + TEST_FAIL_MESSAGE("This Test Should Fail"); +} + +void test_ThisTestAlwaysIgnored(void) +{ + TEST_IGNORE_MESSAGE("This Test Should Be Ignored"); +} + +void qwiktest_ThisTestPassesWhenNoSetupRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(0, CounterSetup, "Setup Was Unexpectedly Run"); +} + +void qwiktest_ThisTestPassesWhenNoTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(0, CounterTeardown, "Teardown Was Unexpectedly Run"); +} + +void spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(0, CounterSuiteSetup, "Suite Setup Was Unexpectedly Run"); +} + +void spec_ThisTestPassesWhenNormalSetupRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CounterSetup, "Normal Setup Wasn't Run"); +} + +void spec_ThisTestPassesWhenNormalTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CounterTeardown, "Normal Teardown Wasn't Run"); +} + +void custtest_ThisTestPassesWhenCustomSetupRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(2, CounterSetup, "Custom Setup Wasn't Run"); +} + +void custtest_ThisTestPassesWhenCustomTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(2, CounterTeardown, "Custom Teardown Wasn't Run"); +} + +#ifndef UNITY_EXCLUDE_TESTING_NEW_COMMENTS +//void test_NewStyleCommentsShouldBeIgnored(void) +//{ +// TEST_ASSERT_FAIL("New Style Comments Should Be Ignored"); +//} +#endif + +void test_NotBeConfusedByLongComplicatedStrings(void) +{ + const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n"; + + TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are The Same"); +} + +void test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings(void) +{ + TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True"); +} + +void test_StillNotBeConfusedByLongComplicatedStrings(void) +{ + const char* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n"; + + TEST_ASSERT_EQUAL_STRING_MESSAGE(crazyString, crazyString, "These Strings Are Still The Same"); +} + +void should_RunTestsStartingWithShouldByDefault(void) +{ + TEST_ASSERT_TRUE_MESSAGE(1, "1 Should be True"); +} + +TEST_CASE(25) +TEST_CASE(125) +TEST_CASE(5) +void paratest_ShouldHandleParameterizedTests(int Num) +{ + TEST_ASSERT_EQUAL_MESSAGE(0, (Num % 5), "All The Values Are Divisible By 5"); +} + +TEST_CASE(7) +void paratest_ShouldHandleParameterizedTests2(int Num) +{ + TEST_ASSERT_EQUAL_MESSAGE(7, Num, "The Only Call To This Passes"); +} + +void paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid(void) +{ + TEST_PASS(); +} + +TEST_CASE(17) +void paratest_ShouldHandleParameterizedTestsThatFail(int Num) +{ + TEST_ASSERT_EQUAL_MESSAGE(3, Num, "This call should fail"); +} + +#ifdef USE_CEXCEPTION +void extest_ShouldHandleCExceptionInTest(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CEXCEPTION_BEING_USED, "Should be pulling in CException"); +} +#endif + +#ifdef USE_ANOTHER_MAIN +int custom_main(void); + +int main(void) +{ + return custom_main(); +} +#endif + +void suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan(void) +{ + TEST_ASSERT_EQUAL_MESSAGE(1, CounterSuiteSetup, "Suite Setup Should Have Run"); +} + +void test_ShouldCallMockInitAndVerifyFunctionsForEachTest(void) +{ + int passesOrIgnores = (int)(Unity.NumberOfTests - Unity.TestFailures); + TEST_ASSERT_EQUAL_MESSAGE(Unity.NumberOfTests, mockMock_Init_Counter, "Mock Init Should Be Called Once Per Test Started"); + TEST_ASSERT_EQUAL_MESSAGE(passesOrIgnores, mockMock_Verify_Counter, "Mock Verify Should Be Called Once Per Test Passed"); + TEST_ASSERT_EQUAL_MESSAGE(Unity.NumberOfTests - 1, mockMock_Destroy_Counter, "Mock Destroy Should Be Called Once Per Test Completed"); + TEST_ASSERT_EQUAL_MESSAGE(0, CMockMemFreeFinalCounter, "Mock MemFreeFinal Should Not Be Called Until End"); +} diff --git a/src/subprojects/unity/test/tests/self_assessment_utils.h b/src/subprojects/unity/test/tests/self_assessment_utils.h new file mode 100644 index 00000000..6051bda8 --- /dev/null +++ b/src/subprojects/unity/test/tests/self_assessment_utils.h @@ -0,0 +1,151 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifdef TEST_INSTANCES + +#include +#include + +/* Dividing by these constants produces +/- infinity. + * The rationale is given in UnityAssertFloatIsInf's body. + */ +#ifndef UNITY_EXCLUDE_FLOAT +static const UNITY_FLOAT f_zero = 0.0f; +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +static const UNITY_DOUBLE d_zero = 0.0; +#endif + +/* Macros for Catching An Expected Failure or Ignore */ +#define EXPECT_ABORT_BEGIN \ + startPutcharSpy(); \ + if (TEST_PROTECT()) \ + { + +#define VERIFY_FAILS_END \ + } \ + endPutcharSpy(); /* start/end Spy to suppress output of failure message */ \ + Unity.CurrentTestFailed = (Unity.CurrentTestFailed == 1) ? 0 : 1; \ + if (Unity.CurrentTestFailed == 1) { \ + SetToOneMeanWeAlreadyCheckedThisGuy = 1; \ + UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \ + UNITY_OUTPUT_CHAR(':'); \ + UnityPrint(Unity.CurrentTestName); \ + UnityPrint(":FAIL: [[[[ Test Should Have Failed But Did Not ]]]]"); \ + UNITY_OUTPUT_CHAR('\n'); \ + } + +#define VERIFY_IGNORES_END \ + } \ + endPutcharSpy(); /* start/end Spy to suppress output of ignore message */ \ + Unity.CurrentTestFailed = (Unity.CurrentTestIgnored == 1) ? 0 : 1; \ + Unity.CurrentTestIgnored = 0; \ + if (Unity.CurrentTestFailed == 1) { \ + SetToOneMeanWeAlreadyCheckedThisGuy = 1; \ + UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \ + UNITY_OUTPUT_CHAR(':'); \ + UnityPrint(Unity.CurrentTestName); \ + UnityPrint(":FAIL: [[[[ Test Should Have Ignored But Did Not ]]]]"); \ + UNITY_OUTPUT_CHAR('\n'); \ + } + +/* Tricky series of macros to set USING_OUTPUT_SPY */ +#define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0) +#define ASSIGN_VALUE(a) VAL_##a +#define VAL_putcharSpy 0, 1 +#define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway) +#define SECOND_PARAM(a, b, ...) b +#if USING_SPY_AS(UNITY_OUTPUT_CHAR) + #define USING_OUTPUT_SPY /* true only if UNITY_OUTPUT_CHAR = putcharSpy */ +#endif + +#ifdef USING_OUTPUT_SPY +#include +#define SPY_BUFFER_MAX 40 +static char putcharSpyBuffer[SPY_BUFFER_MAX]; +#endif +static UNITY_COUNTER_TYPE indexSpyBuffer; +static UNITY_COUNTER_TYPE putcharSpyEnabled; + +void startPutcharSpy(void) +{ + indexSpyBuffer = 0; + putcharSpyEnabled = 1; +} + +void endPutcharSpy(void) +{ + putcharSpyEnabled = 0; +} + +char* getBufferPutcharSpy(void) +{ +#ifdef USING_OUTPUT_SPY + putcharSpyBuffer[indexSpyBuffer] = '\0'; + return putcharSpyBuffer; +#else + return NULL; +#endif +} + +void putcharSpy(int c) +{ +#ifdef USING_OUTPUT_SPY + if (putcharSpyEnabled) + { + if (indexSpyBuffer < SPY_BUFFER_MAX - 1) + putcharSpyBuffer[indexSpyBuffer++] = (char)c; + } else + putchar((char)c); +#else + (void)c; +#endif +} + +/* This is for counting the calls to the flushSpy */ +static UNITY_COUNTER_TYPE flushSpyEnabled; +static UNITY_COUNTER_TYPE flushSpyCalls = 0; + +void startFlushSpy(void) +{ + flushSpyCalls = 0; + flushSpyEnabled = 1; +} + +void endFlushSpy(void) +{ + flushSpyCalls = 0; + flushSpyEnabled = 0; +} + +UNITY_COUNTER_TYPE getFlushSpyCalls(void) +{ + return flushSpyCalls; +} + +void flushSpy(void) +{ + if (flushSpyEnabled){ flushSpyCalls++; } +} + +#define TEST_ASSERT_EQUAL_PRINT_NUMBERS(expected, actual) { \ + startPutcharSpy(); UnityPrintNumber((actual)); endPutcharSpy(); \ + TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \ + } + +#define TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS(expected, actual) { \ + startPutcharSpy(); UnityPrintNumberUnsigned((actual)); endPutcharSpy(); \ + TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \ + } + +#define TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, actual) { \ + startPutcharSpy(); UnityPrintFloat((actual)); endPutcharSpy(); \ + TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \ + } + +#endif diff --git a/src/subprojects/unity/test/tests/test_generate_test_runner.rb b/src/subprojects/unity/test/tests/test_generate_test_runner.rb new file mode 100644 index 00000000..79a2e48e --- /dev/null +++ b/src/subprojects/unity/test/tests/test_generate_test_runner.rb @@ -0,0 +1,1341 @@ +# ========================================================================= +# Unity - A Test Framework for C +# ThrowTheSwitch.org +# Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams +# SPDX-License-Identifier: MIT +# ========================================================================= + +require '../auto/generate_test_runner.rb' + +$generate_test_runner_tests = 0 +$generate_test_runner_failures = 0 + +OUT_FILE = 'build/testsample_' + +RUNNER_TESTS = [ + { :name => 'DefaultsThroughOptions', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :options => nil, #defaults + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'DefaultsThroughCommandLine', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :cmdline => "", #defaults + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'DefaultsThroughYAMLFile', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :cmdline => "", #defaults + :yaml => {}, #defaults + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ShorterFilterOfJustTest', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "test", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ShorterFilterOfJustShould', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "should", + }, + :expected => { + :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ShorterFilterOfJustSpec', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "spec", + }, + :expected => { + :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'InjectIncludes', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :options => { + :includes => ['Defs.h'], + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ParameterizedThroughOptions', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "paratest", + :use_param_tests => true, + }, + :features => [ :parameterized ], + :expected => { + :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', + 'paratest_ShouldHandleParameterizedTests\(125\)', + 'paratest_ShouldHandleParameterizedTests\(5\)', + 'paratest_ShouldHandleParameterizedTests2\(7\)', + 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid', + 'paratest_WorksWithFunctionPointers\(isArgumentOne\)', + ], + :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], + :to_ignore => [ ], + } + }, + + { :name => 'ParameterizedThroughCommandLine', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :cmdline => " --test_prefix=\"paratest\" --use_param_tests=1", + :features => [ :parameterized ], + :expected => { + :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', + 'paratest_ShouldHandleParameterizedTests\(125\)', + 'paratest_ShouldHandleParameterizedTests\(5\)', + 'paratest_ShouldHandleParameterizedTests2\(7\)', + 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid', + 'paratest_WorksWithFunctionPointers\(isArgumentOne\)', + ], + :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], + :to_ignore => [ ], + } + }, + + { :name => 'ParameterizedThroughCommandLineAndYaml', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :cmdline => "--use_param_tests=1", + :yaml => { + :test_prefix => "paratest" + }, + :features => [ :parameterized ], + :expected => { + :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', + 'paratest_ShouldHandleParameterizedTests\(125\)', + 'paratest_ShouldHandleParameterizedTests\(5\)', + 'paratest_ShouldHandleParameterizedTests2\(7\)', + 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid', + 'paratest_WorksWithFunctionPointers\(isArgumentOne\)', + ], + :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], + :to_ignore => [ ], + } + }, + + { :name => 'CException', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'USE_CEXCEPTION'], + :options => { + :test_prefix => "extest", + :plugins => [ :cexception ], + }, + :expected => { + :to_pass => [ 'extest_ShouldHandleCExceptionInTest' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'CustomSetupAndTeardownThroughOptions', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "custtest|test", + :setup_name => "custom_setup", + :teardown_name => "custom_teardown", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'custtest_ThisTestPassesWhenCustomSetupRan', + 'custtest_ThisTestPassesWhenCustomTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'CustomSetupAndTeardownThroughCommandLine', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :cmdline => " --test_prefix=\"custtest|test\" --setup_name=\"custom_setup\" --teardown_name=\"custom_teardown\"", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'custtest_ThisTestPassesWhenCustomSetupRan', + 'custtest_ThisTestPassesWhenCustomTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'CustomSetupAndTeardownThroughYaml', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :cmdline => " --test_prefix=\"custtest|test\"", + :yaml => { + :setup_name => "custom_setup", + :teardown_name => "custom_teardown", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'custtest_ThisTestPassesWhenCustomSetupRan', + 'custtest_ThisTestPassesWhenCustomTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'CustomMain', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', "USE_ANOTHER_MAIN"], + :options => { + :main_name => "custom_main", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'CustomSuiteSetupAndTeardown', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :includes => ['Defs.h'], + :options => { + :test_prefix => "suitetest|test", + :suite_setup => " CounterSuiteSetup = 1;", + :suite_teardown => " return num_failures;", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'MainExternDeclaration', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST'], + :includes => ['Defs.h'], + :options => { + :main_export_decl => "EXTERN_DECL", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + + #### WITH MOCKS ########################################## + + { :name => 'DefaultsThroughOptions', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :options => nil, #defaults + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'DefaultsThroughCommandLine', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :cmdline => "", #defaults + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'DefaultsThroughYAMLFile', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :cmdline => "", #defaults + :yaml => {}, #defaults + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ShorterFilterOfJustTest', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "test", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ShorterFilterOfJustShould', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "should", + }, + :expected => { + :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ShorterFilterOfJustSpec', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "spec", + }, + :expected => { + :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'InjectIncludes', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :options => { + :includes => ['Defs.h'], + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ParameterizedThroughOptions', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "paratest", + :use_param_tests => true, + }, + :features => [ :parameterized ], + :expected => { + :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', + 'paratest_ShouldHandleParameterizedTests\(125\)', + 'paratest_ShouldHandleParameterizedTests\(5\)', + 'paratest_ShouldHandleParameterizedTests2\(7\)', + 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid', + ], + :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], + :to_ignore => [ ], + } + }, + + { :name => 'ParameterizedThroughCommandLine', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :cmdline => " --test_prefix=\"paratest\" --use_param_tests=1", + :features => [ :parameterized ], + :expected => { + :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', + 'paratest_ShouldHandleParameterizedTests\(125\)', + 'paratest_ShouldHandleParameterizedTests\(5\)', + 'paratest_ShouldHandleParameterizedTests2\(7\)', + 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid', + ], + :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], + :to_ignore => [ ], + } + }, + + { :name => 'ParameterizedThroughCommandLineAndYaml', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :cmdline => "--use_param_tests=1", + :yaml => { + :test_prefix => "paratest" + }, + :features => [ :parameterized ], + :expected => { + :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', + 'paratest_ShouldHandleParameterizedTests\(125\)', + 'paratest_ShouldHandleParameterizedTests\(5\)', + 'paratest_ShouldHandleParameterizedTests2\(7\)', + 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid', + ], + :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], + :to_ignore => [ ], + } + }, + + { :name => 'CException', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST', 'USE_CEXCEPTION'], + :options => { + :test_prefix => "extest", + :plugins => [ :cexception ], + }, + :expected => { + :to_pass => [ 'extest_ShouldHandleCExceptionInTest' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'CustomSetupAndTeardownThroughOptions', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :options => { + :test_prefix => "custtest|test", + :setup_name => "custom_setup", + :teardown_name => "custom_teardown", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'custtest_ThisTestPassesWhenCustomSetupRan', + 'custtest_ThisTestPassesWhenCustomTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'CustomSetupAndTeardownThroughCommandLine', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :cmdline => " --test_prefix=\"custtest|test\" --setup_name=\"custom_setup\" --teardown_name=\"custom_teardown\"", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'custtest_ThisTestPassesWhenCustomSetupRan', + 'custtest_ThisTestPassesWhenCustomTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'CustomSetupAndTeardownThroughYaml', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :cmdline => " --test_prefix=\"custtest|test\"", + :yaml => { + :setup_name => "custom_setup", + :teardown_name => "custom_teardown", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'custtest_ThisTestPassesWhenCustomSetupRan', + 'custtest_ThisTestPassesWhenCustomTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'CustomMain', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST', "USE_ANOTHER_MAIN"], + :options => { + :main_name => "custom_main", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'CustomSuiteSetupAndTeardown', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :includes => ['Defs.h'], + :options => { + :test_prefix => "suitetest|test", + :suite_setup => " CounterSuiteSetup = 1;", + :suite_teardown => " return num_failures;", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'suitetest_ThisTestPassesWhenCustomSuiteSetupAndTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'MainExternDeclaration', + :testfile => 'testdata/testRunnerGeneratorWithMocks.c', + :testdefines => ['TEST'], + :includes => ['Defs.h'], + :options => { + :main_export_decl => "EXTERN_DECL", + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + 'test_ShouldCallMockInitAndVerifyFunctionsForEachTest', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + + + #### WITH ARGS ########################################## + + { :name => 'ArgsThroughOptions', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsThroughCommandLine', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :cmdline => "--cmdline_args=1", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsThroughYAMLFile', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :cmdline => "", + :yaml => { + :cmdline_args => true, + }, + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsNameFilterJustTest', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f test_", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsNameFilterJustShould', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f should_", + :expected => { + :to_pass => [ 'should_RunTestsStartingWithShouldByDefault' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsNameFilterTestAndShould', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f should_,test_", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsNameFilterWithWildcardOnFile', + :testfile => 'testdata/testRunnerGeneratorSmall.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f=testRunnerGeneratorSma*", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsNameFilterWithWildcardAsName', + :testfile => 'testdata/testRunnerGeneratorSmall.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f testRunnerGeneratorSmall:*", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsNameFilterWithWildcardOnName', + :testfile => 'testdata/testRunnerGeneratorSmall.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f testRunnerGeneratorSmall:test_*", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsNameFilterWithWildcardAndShortName', + :testfile => 'testdata/testRunnerGeneratorSmall.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f testRunnerGeneratorSmall:te*", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsNameFilterWithWildcardOnBoth', + :testfile => 'testdata/testRunnerGeneratorSmall.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f testRunnerGeneratorSm*:*", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsExcludeFilterJustTest', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-x test_", + :expected => { + :to_pass => [ 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + 'should_RunTestsStartingWithShouldByDefault', + ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeAndExcludeFilter', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + :includes => ['Defs.h'], + }, + :cmdline_args => "-f test_ -x Ignored", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeSingleTest', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f ThisTestAlwaysPasses", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeSingleTestInSpecificFile', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f testRunnerGenerator:ThisTestAlwaysPasses", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeTestFileWithExtension', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f testRunnerGenerator.c:ThisTestAlwaysPasses", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeDoubleQuotes', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f \"testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails\"", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeSingleQuotes', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f 'testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails'", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsHandlePreciseMatch', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-n 'test_ThisTestAlwaysPasses'", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsHandlePreciseMatches', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-n 'test_ThisTestAlwaysPasses,test_ThisTestAlwaysFails'", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsRequiresPreciseMatchNotPartial', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-n ThisTestAlwaysPass", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeAValidTestForADifferentFile', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f AnotherFile:ThisTestDoesNotExist", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeNoTests', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f ThisTestDoesNotExist", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsExcludeAllTests', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-x _", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeFullFile', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f testRunnerGenerator", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses', + 'spec_ThisTestPassesWhenNormalSetupRan', + 'spec_ThisTestPassesWhenNormalTeardownRan', + 'test_NotBeConfusedByLongComplicatedStrings', + 'test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings', + 'test_StillNotBeConfusedByLongComplicatedStrings', + 'should_RunTestsStartingWithShouldByDefault', + 'spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan', + ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ 'test_ThisTestAlwaysIgnored' ], + } + }, + + { :name => 'ArgsIncludeWithAlternateFlag', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f=\"testRunnerGenerator:ThisTestAlwaysPasses,test_ThisTestAlwaysFails\"", + :expected => { + :to_pass => [ 'test_ThisTestAlwaysPasses' ], + :to_fail => [ 'test_ThisTestAlwaysFails' ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsIncludeWithParameterized', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :cmdline => "--use_param_tests=1", + :yaml => { + :cmdline_args => true, + :test_prefix => "paratest" + }, + :cmdline_args => "-f ShouldHandleParameterizedTests", + :features => [ :parameterized ], + :expected => { + :to_pass => [ 'paratest_ShouldHandleParameterizedTests\(25\)', + 'paratest_ShouldHandleParameterizedTests\(125\)', + 'paratest_ShouldHandleParameterizedTests\(5\)', + 'paratest_ShouldHandleParameterizedTests2\(7\)', + ], + :to_fail => [ 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)' ], + :to_ignore => [ ], + } + }, + + { :name => 'ArgsList', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-l", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + :text => [ "testRunnerGenerator", + "test_ThisTestAlwaysPasses", + "test_ThisTestAlwaysFails", + "test_ThisTestAlwaysIgnored", + "spec_ThisTestPassesWhenNormalSuiteSetupAndTeardownRan", + "spec_ThisTestPassesWhenNormalSetupRan", + "spec_ThisTestPassesWhenNormalTeardownRan", + "test_NotBeConfusedByLongComplicatedStrings", + "test_NotDisappearJustBecauseTheTestBeforeAndAfterHaveCrazyStrings", + "test_StillNotBeConfusedByLongComplicatedStrings", + "should_RunTestsStartingWithShouldByDefault" + ] + } + }, + + { :name => 'ArgsListParameterized', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :test_prefix => "paratest", + :use_param_tests => true, + :cmdline_args => true, + }, + :cmdline_args => "-l", + :features => [ :parameterized ], + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + :text => [ "testRunnerGenerator", + 'paratest_ShouldHandleParameterizedTests\(25\)', + 'paratest_ShouldHandleParameterizedTests\(125\)', + 'paratest_ShouldHandleParameterizedTests\(5\)', + 'paratest_ShouldHandleParameterizedTests2\(7\)', + 'paratest_ShouldHandleNonParameterizedTestsWhenParameterizationValid', + 'paratest_ShouldHandleParameterizedTestsThatFail\(17\)', + 'paratest_WorksWithFunctionPointers\(isArgumentOne\)', + ], + } + }, + + { :name => 'ArgsIncompleteIncludeFlags', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-f", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + :text => [ "ERROR: No Test String to Include Matches For" ], + } + }, + + { :name => 'ArgsIncompleteExcludeFlags', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-x", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + :text => [ "ERROR: No Test String to Exclude Matches For" ], + } + }, + + { :name => 'ArgsIllegalFlags', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-z", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + :text => [ + "ERROR: Unknown Option z", + "Options:", + "-l List all tests and exit", + "-f NAME Filter to run only tests whose name includes NAME", + "-n NAME Run only the test named NAME", + "-h show this Help menu", + "-q Quiet/decrease verbosity", + "-v increase Verbosity", + "-x NAME eXclude tests whose name includes NAME", + ], + } + }, + + { :name => 'ArgsHelp', + :testfile => 'testdata/testRunnerGenerator.c', + :testdefines => ['TEST', 'UNITY_USE_COMMAND_LINE_ARGS'], + :options => { + :cmdline_args => true, + }, + :cmdline_args => "-h", + :expected => { + :to_pass => [ ], + :to_fail => [ ], + :to_ignore => [ ], + :text => [ + "Options:", + "-l List all tests and exit", + "-f NAME Filter to run only tests whose name includes NAME", + "-n NAME Run only the test named NAME", + "-h show this Help menu", + "-q Quiet/decrease verbosity", + "-v increase Verbosity", + "-x NAME eXclude tests whose name includes NAME", + ], + } + }, +] + +def runner_test(test, runner, expected, test_defines, cmdline_args, features) + # Tack on TEST define for compiling unit tests + load_configuration($cfg_file) + + # Drop Out if we're skipping this type of test + if $cfg[:skip_tests] && features + if $cfg[:skip_tests].include?(:parameterized) && features.include?(:parameterized) + report("Skipping Parameterized Tests for this Target:IGNORE") + return true + end + end + + #compile objects + obj_list = [ + compile(runner, test_defines), + compile(test, test_defines), + compile('../src/unity.c', test_defines), + ] + + # Link the test executable + test_base = File.basename(test, C_EXTENSION) + link_it(test_base, obj_list) + + # Execute unit test and generate results file + output = runtest(test_base, true, cmdline_args) + + #compare to the expected pass/fail + allgood = expected[:to_pass].inject(true) {|s,v| s && verify_match(/#{v}:PASS/, output) } + allgood = expected[:to_fail].inject(allgood) {|s,v| s && verify_match(/#{v}:FAIL/, output) } + allgood = expected[:to_ignore].inject(allgood) {|s,v| s && verify_match(/#{v}:IGNORE/, output) } + + #verify there weren't more pass/fail/etc than expected + allgood &&= verify_number( expected[:to_pass], /(:PASS)/, output) + allgood &&= verify_number( expected[:to_fail], /(:FAIL)/, output) + allgood &&= verify_number( expected[:to_ignore], /(:IGNORE)/, output) + + #if we care about any other text, check that too + if (expected[:text]) + allgood = expected[:text].inject(allgood) {|s,v| s && verify_match(/#{v}/, output) } + allgood &&= verify_number( expected[:text], /.+/, output ) + end + + report output if (!allgood && !$verbose) #report failures if not already reporting everything + return allgood +end + +def verify_match(expression, output) + if (expression =~ output) + return true + else + report " FAIL: No Match For /#{expression.to_s}/" + return false + end +end + +def verify_number(expected, expression, output) + exp = expected.length + act = output.scan(expression).length + if (exp == act) + return true + else + report " FAIL: Expected #{exp} Matches For /#{expression.to_s}/. Was #{act}" + return false + end +end + +RUNNER_TESTS.each do |testset| + basename = File.basename(testset[:testfile], C_EXTENSION) + testset_name = "Runner_#{basename}_#{testset[:name]}" + should testset_name do + runner_name = OUT_FILE + testset[:name] + '_runner.c' + + #create a yaml file first if required + yaml_option = "" + if (testset[:yaml]) + File.open("build/runner_options.yml",'w') {|f| f << { :unity => testset[:yaml] }.to_yaml } + yaml_option = "build/runner_options.yml" + end + + #run script via command line or through hash function call, as requested + if (testset[:cmdline]) + cmdstr = "ruby ../auto/generate_test_runner.rb #{yaml_option} #{testset[:cmdline]} \"#{testset[:testfile]}\" \"#{runner_name}\"" + `#{cmdstr}` + else + UnityTestRunnerGenerator.new(testset[:options]).run(testset[:testfile], runner_name) + end + + #test the script against the specified test file and check results + if (runner_test(testset[:testfile], runner_name, testset[:expected], testset[:testdefines], testset[:cmdline_args], testset[:features])) + report "#{testset_name}:PASS" + else + report "#{testset_name}:FAIL" + $generate_test_runner_failures += 1 + end + $generate_test_runner_tests += 1 + end +end + +raise "There were #{$generate_test_runner_failures.to_s} failures while testing generate_test_runner.rb" if ($generate_test_runner_failures > 0) diff --git a/src/subprojects/unity/test/tests/test_unity_arrays.c b/src/subprojects/unity/test/tests/test_unity_arrays.c new file mode 100644 index 00000000..f852c269 --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_arrays.c @@ -0,0 +1,2941 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#define TEST_INSTANCES +#include "self_assessment_utils.h" + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + { + /* These will be skipped internally if already failed/ignored */ + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); + } + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +void testInt64ArrayWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualSmallDelta[] = {12345001, -12344996, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + TEST_ASSERT_INT64_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_INT64_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +#endif +} + +void testInt64ArrayWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualSmallDelta[] = {12345001, -12344996, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +#endif +} + +void testInt64ArrayNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayNotWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaPointless(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaPointlessAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaExpectedNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaExpectedNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaActualNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaActualNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaSamePointer(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, expected, 3); +#endif +} + +void testInt64ArrayWithinDeltaSamePointerAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +#endif +} + +void testIntArrayWithinDelta(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + UNITY_INT actualSmallDelta[] = {5001, -4996, 5005}; + UNITY_INT actualBigDelta[] = {5101, -4896, 5055}; + + TEST_ASSERT_INT_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_INT_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +} + +void testIntArrayWithinDeltaAndMessage(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + UNITY_INT actualSmallDelta[] = {5001, -4996, 5005}; + UNITY_INT actualBigDelta[] = {5101, -4896, 5055}; + + TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +} + +void testIntArrayNotWithinDelta(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + UNITY_INT actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testIntArrayNotWithinDeltaAndMessage(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + UNITY_INT actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testIntArrayWithinDeltaPointless(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + UNITY_INT actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testIntArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + UNITY_INT actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testIntArrayWithinDeltaExpectedNull(void) +{ + UNITY_INT actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testIntArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_INT actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testIntArrayWithinDeltaActualNull(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testIntArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testIntArrayWithinDeltaSamePointer(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + + TEST_ASSERT_INT_ARRAY_WITHIN(110, expected, expected, 3); +} + +void testIntArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_INT expected[] = {5000, -4995, 5005}; + + TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +} + +void testInt16ArrayWithinDelta(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + UNITY_INT16 actualSmallDelta[] = {5001, -4996, 5005}; + UNITY_INT16 actualBigDelta[] = {5101, -4896, 5055}; + + TEST_ASSERT_INT16_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_INT16_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +} + +void testInt16ArrayWithinDeltaAndMessage(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + UNITY_INT16 actualSmallDelta[] = {5001, -4996, 5005}; + UNITY_INT16 actualBigDelta[] = {5101, -4896, 5055}; + + TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +} + +void testInt16ArrayNotWithinDelta(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + UNITY_INT16 actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testInt16ArrayNotWithinDeltaAndMessage(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + UNITY_INT16 actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testInt16ArrayWithinDeltaPointless(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + UNITY_INT16 actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testInt16ArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + UNITY_INT16 actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testInt16ArrayWithinDeltaExpectedNull(void) +{ + UNITY_INT16 actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testInt16ArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_INT16 actualBigDelta[] = {5101, -4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testInt16ArrayWithinDeltaActualNull(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testInt16ArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testInt16ArrayWithinDeltaSamePointer(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + + TEST_ASSERT_INT16_ARRAY_WITHIN(110, expected, expected, 3); +} + +void testInt16ArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_INT16 expected[] = {5000, -4995, 5005}; + + TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +} + +void testInt8ArrayWithinDelta(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + UNITY_INT8 actualSmallDelta[] = {21, -94, 55}; + UNITY_INT8 actualBigDelta[] = {11, -86, 45}; + + TEST_ASSERT_INT8_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_INT8_ARRAY_WITHIN(11, expected, actualBigDelta, 3); +} + +void testInt8ArrayWithinDeltaAndMessage(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + UNITY_INT8 actualSmallDelta[] = {21, -94, 55}; + UNITY_INT8 actualBigDelta[] = {11, -86, 45}; + + TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(11, expected, actualBigDelta, 3, "Custom Message."); +} + +void testInt8ArrayNotWithinDelta(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + UNITY_INT8 actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testInt8ArrayNotWithinDeltaAndMessage(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + UNITY_INT8 actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testInt8ArrayWithinDeltaPointless(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + UNITY_INT8 actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_ARRAY_WITHIN(11, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testInt8ArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + UNITY_INT8 actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(11, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testInt8ArrayWithinDeltaExpectedNull(void) +{ + UNITY_INT8 actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_ARRAY_WITHIN(11, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testInt8ArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_INT8 actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(11, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testInt8ArrayWithinDeltaActualNull(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_ARRAY_WITHIN(11, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testInt8ArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(11, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testInt8ArrayWithinDeltaSamePointer(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + + TEST_ASSERT_INT8_ARRAY_WITHIN(11, expected, expected, 3); +} + +void testInt8ArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_INT8 expected[] = {20, -95, 55}; + + TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(11, expected, expected, 3, "Custom Message."); +} + +void testCHARArrayWithinDelta(void) +{ + char expected[] = {20, -95, 55}; + char actualSmallDelta[] = {21, -94, 55}; + char actualBigDelta[] = {11, -86, 45}; + + TEST_ASSERT_CHAR_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_CHAR_ARRAY_WITHIN(11, expected, actualBigDelta, 3); +} + +void testCHARArrayWithinDeltaAndMessage(void) +{ + char expected[] = {20, -95, 55}; + char actualSmallDelta[] = {21, -94, 55}; + char actualBigDelta[] = {11, -86, 45}; + + TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(11, expected, actualBigDelta, 3, "Custom Message."); +} + +void testCHARArrayNotWithinDelta(void) +{ + char expected[] = {20, -95, 55}; + char actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testCHARArrayNotWithinDeltaAndMessage(void) +{ + char expected[] = {20, -95, 55}; + char actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testCHARArrayWithinDeltaPointless(void) +{ + char expected[] = {20, -95, 55}; + char actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_ARRAY_WITHIN(11, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testCHARArrayWithinDeltaPointlessAndMessage(void) +{ + char expected[] = {20, -95, 55}; + char actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(11, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testCHARArrayWithinDeltaExpectedNull(void) +{ + char actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_ARRAY_WITHIN(11, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testCHARArrayWithinDeltaExpectedNullAndMessage(void) +{ + char actualBigDelta[] = {11, -86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(11, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testCHARArrayWithinDeltaActualNull(void) +{ + char expected[] = {20, -95, 55}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_ARRAY_WITHIN(11, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testCHARArrayWithinDeltaActualNullAndMessage(void) +{ + char expected[] = {20, -95, 55}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(11, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testCHARArrayWithinDeltaSamePointer(void) +{ + char expected[] = {20, -95, 55}; + + TEST_ASSERT_CHAR_ARRAY_WITHIN(11, expected, expected, 3); +} + +void testCHARArrayWithinDeltaSamePointerAndMessage(void) +{ + char expected[] = {20, -95, 55}; + + TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(11, expected, expected, 3, "Custom Message."); +} + +void testUInt64ArrayWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualSmallDelta[] = {12345001, 12344996, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +#endif +} + +void testUInt64ArrayWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualSmallDelta[] = {12345001, 12344996, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +#endif +} + +void testUInt64ArrayNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayNotWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaPointless(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaPointlessAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaExpectedNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaExpectedNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaActualNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaActualNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaSamePointer(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, expected, 3); +#endif +} + +void testUInt64ArrayWithinDeltaSamePointerAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +#endif +} + +void testUIntArrayWithinDelta(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + UNITY_UINT actualSmallDelta[] = {125001, 124996, 125005}; + UNITY_UINT actualBigDelta[] = {125101, 124896, 125055}; + + TEST_ASSERT_UINT_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_UINT_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +} + +void testUIntArrayWithinDeltaAndMessage(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + UNITY_UINT actualSmallDelta[] = {125001, 124996, 125005}; + UNITY_UINT actualBigDelta[] = {125101, 124896, 125055}; + + TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +} + +void testUIntArrayNotWithinDelta(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + UNITY_UINT actualBigDelta[] = {125101, 124896, 125055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testUIntArrayNotWithinDeltaAndMessage(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + UNITY_UINT actualBigDelta[] = {125101, 124896, 125055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUIntArrayWithinDeltaPointless(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + UNITY_UINT actualBigDelta[] = {125101, 124896, 125055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testUIntArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + UNITY_UINT actualBigDelta[] = {125101, 124896, 125055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testUIntArrayWithinDeltaExpectedNull(void) +{ + UNITY_UINT actualBigDelta[] = {125101, 124896, 125055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testUIntArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_UINT actualBigDelta[] = {125101, 124896, 125055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUIntArrayWithinDeltaActualNull(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testUIntArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUIntArrayWithinDeltaSamePointer(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + + TEST_ASSERT_UINT_ARRAY_WITHIN(110, expected, expected, 3); +} + +void testUIntArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_UINT expected[] = {125000, 124995, 125005}; + + TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +} + +void testUInt16ArrayWithinDelta(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + UNITY_UINT16 actualSmallDelta[] = {5001, 4996, 5005}; + UNITY_UINT16 actualBigDelta[] = {5101, 4896, 5055}; + + TEST_ASSERT_UINT16_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_UINT16_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +} + +void testUInt16ArrayWithinDeltaAndMessage(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + UNITY_UINT16 actualSmallDelta[] = {5001, 4996, 5005}; + UNITY_UINT16 actualBigDelta[] = {5101, 4896, 5055}; + + TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +} + +void testUInt16ArrayNotWithinDelta(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + UNITY_UINT16 actualBigDelta[] = {5101, 4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testUInt16ArrayNotWithinDeltaAndMessage(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + UNITY_UINT16 actualBigDelta[] = {5101, 4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUInt16ArrayWithinDeltaPointless(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + UNITY_UINT16 actualBigDelta[] = {5101, 4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testUInt16ArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + UNITY_UINT16 actualBigDelta[] = {5101, 4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testUInt16ArrayWithinDeltaExpectedNull(void) +{ + UNITY_UINT16 actualBigDelta[] = {5101, 4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testUInt16ArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_UINT16 actualBigDelta[] = {5101, 4896, 5055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUInt16ArrayWithinDeltaActualNull(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testUInt16ArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUInt16ArrayWithinDeltaSamePointer(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + + TEST_ASSERT_UINT16_ARRAY_WITHIN(110, expected, expected, 3); +} + +void testUInt16ArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_UINT16 expected[] = {5000, 4995, 5005}; + + TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +} + +void testUInt8ArrayWithinDelta(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + UNITY_UINT8 actualSmallDelta[] = {21, 94, 55}; + UNITY_UINT8 actualBigDelta[] = {11, 86, 45}; + + TEST_ASSERT_UINT8_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_UINT8_ARRAY_WITHIN(11, expected, actualBigDelta, 3); +} + +void testUInt8ArrayWithinDeltaAndMessage(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + UNITY_UINT8 actualSmallDelta[] = {21, 94, 55}; + UNITY_UINT8 actualBigDelta[] = {11, 86, 45}; + + TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(11, expected, actualBigDelta, 3, "Custom Message."); +} + +void testUInt8ArrayNotWithinDelta(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + UNITY_UINT8 actualBigDelta[] = {11, 86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testUInt8ArrayNotWithinDeltaAndMessage(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + UNITY_UINT8 actualBigDelta[] = {11, 86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUInt8ArrayWithinDeltaPointless(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + UNITY_UINT8 actualBigDelta[] = {11, 86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_ARRAY_WITHIN(11, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testUInt8ArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + UNITY_UINT8 actualBigDelta[] = {11, 86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(11, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testUInt8ArrayWithinDeltaExpectedNull(void) +{ + UNITY_UINT8 actualBigDelta[] = {11, 86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_ARRAY_WITHIN(11, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testUInt8ArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_UINT8 actualBigDelta[] = {11, 86, 45}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(11, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUInt8ArrayWithinDeltaActualNull(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_ARRAY_WITHIN(11, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testUInt8ArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(11, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testUInt8ArrayWithinDeltaSamePointer(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + + TEST_ASSERT_UINT8_ARRAY_WITHIN(11, expected, expected, 3); +} + +void testUInt8ArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_UINT8 expected[] = {20, 95, 55}; + + TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(11, expected, expected, 3, "Custom Message."); +} + +void testHEX64ArrayWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualSmallDelta[] = {0xABCD123500000000, 0xABCD112100000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x100000000, expected, actualSmallDelta, 3); + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, expected, actualBigDelta, 3); +#endif +} + +void testHEX64ArrayWithinDeltaShouldNotHaveSignIssues(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0x7FFFFFFFFFFFFFFF, 0x8000000000000000}; + UNITY_UINT64 actualBigDelta[] = {0x8000000000000000, 0x7FFFFFFFFFFFFFFF}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN(1, expected, actualBigDelta, 2); +#endif +} + +void testHEX64ArrayWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualSmallDelta[] = {0xABCD123500000000, 0xABCD112100000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x100000000, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, expected, actualBigDelta, 3, "Custom Message."); +#endif +} + +void testHEX64ArrayNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x100000000, expected, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayNotWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x100000000, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaPointless(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, expected, actualBigDelta, 0); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaPointlessAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaExpectedNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaExpectedNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaActualNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, expected, NULL, 3); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaActualNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaSamePointer(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, expected, expected, 3); +#endif +} + +void testHEX64ArrayWithinDeltaSamePointerAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, expected, expected, 3, "Custom Message."); +#endif +} + +void testHEX32ArrayWithinDelta(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + UNITY_UINT actualSmallDelta[] = {0xABCD1235, 0xABCD1121, 0xABCD1277}; + UNITY_UINT actualBigDelta[] = {0xABCD1267, 0xABCD1188, 0xABCD12AC}; + + TEST_ASSERT_HEX32_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_HEX32_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +} + +void testHEX32ArrayWithinDeltaShouldNotHaveSignIssues(void) +{ + UNITY_UINT32 expected[] = {0x7FFFFFFF, 0x80000000}; + UNITY_UINT32 actualBigDelta[] = {0x80000000, 0x7FFFFFFF}; + + TEST_ASSERT_HEX32_ARRAY_WITHIN(1, expected, actualBigDelta, 2); +} + +void testHEX32ArrayWithinDeltaAndMessage(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + UNITY_UINT actualSmallDelta[] = {0xABCD1235, 0xABCD1121, 0xABCD1277}; + UNITY_UINT actualBigDelta[] = {0xABCD1267, 0xABCD1188, 0xABCD12AC}; + + TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +} + +void testHEX32ArrayNotWithinDelta(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + UNITY_UINT actualBigDelta[] = {0xABCD1267, 0xABCD1188, 0xABCD12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testHEX32ArrayNotWithinDeltaAndMessage(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + UNITY_UINT actualBigDelta[] = {0xABCD1267, 0xABCD1188, 0xABCD12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX32ArrayWithinDeltaPointless(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + UNITY_UINT actualBigDelta[] = {0xABCD1267, 0xABCD1188, 0xABCD12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testHEX32ArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + UNITY_UINT actualBigDelta[] = {0xABCD1267, 0xABCD1188, 0xABCD12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX32ArrayWithinDeltaExpectedNull(void) +{ + UNITY_UINT actualBigDelta[] = {0xABCD1267, 0xABCD1188, 0xABCD12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testHEX32ArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_UINT actualBigDelta[] = {0xABCD1267, 0xABCD1188, 0xABCD12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX32ArrayWithinDeltaActualNull(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testHEX32ArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX32ArrayWithinDeltaSamePointer(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + + TEST_ASSERT_HEX32_ARRAY_WITHIN(110, expected, expected, 3); +} + +void testHEX32ArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_UINT expected[] = {0xABCD1234, 0xABCD1122, 0xABCD1277}; + + TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +} + + +void testHEX16ArrayWithinDelta(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + UNITY_UINT16 actualSmallDelta[] = {0x1235, 0x1121, 0x1277}; + UNITY_UINT16 actualBigDelta[] = {0x1267, 0x1188, 0x12AC}; + + TEST_ASSERT_HEX16_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_HEX16_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +} + +void testHEX16ArrayWithinDeltaShouldNotHaveSignIssues(void) +{ + UNITY_UINT16 expected[] = {0x7FFF, 0x8000}; + UNITY_UINT16 actualBigDelta[] = {0x8000, 0x7FFF}; + + TEST_ASSERT_HEX16_ARRAY_WITHIN(1, expected, actualBigDelta, 2); +} + +void testHEX16ArrayWithinDeltaAndMessage(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + UNITY_UINT16 actualSmallDelta[] = {0x1235, 0x1121, 0x1277}; + UNITY_UINT16 actualBigDelta[] = {0x1267, 0x1188, 0x12AC}; + + TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +} + +void testHEX16ArrayNotWithinDelta(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + UNITY_UINT16 actualBigDelta[] = {0x1267, 0x1188, 0x12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testHEX16ArrayNotWithinDeltaAndMessage(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + UNITY_UINT16 actualBigDelta[] = {0x1267, 0x1188, 0x12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX16ArrayWithinDeltaPointless(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + UNITY_UINT16 actualBigDelta[] = {0x1267, 0x1188, 0x12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testHEX16ArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + UNITY_UINT16 actualBigDelta[] = {0x1267, 0x1188, 0x12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX16ArrayWithinDeltaExpectedNull(void) +{ + UNITY_UINT16 actualBigDelta[] = {0x1267, 0x1188, 0x12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testHEX16ArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_UINT16 actualBigDelta[] = {0x1267, 0x1188, 0x12AC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX16ArrayWithinDeltaActualNull(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testHEX16ArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX16ArrayWithinDeltaSamePointer(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + + TEST_ASSERT_HEX16_ARRAY_WITHIN(110, expected, expected, 3); +} + +void testHEX16ArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_UINT16 expected[] = {0x1234, 0x1122, 0x1277}; + + TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +} + +void testHEX8ArrayWithinDelta(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + UNITY_UINT8 actualSmallDelta[] = {0x35, 0x21, 0x77}; + UNITY_UINT8 actualBigDelta[] = {0x47, 0x48, 0x4C}; + + TEST_ASSERT_HEX8_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_HEX8_ARRAY_WITHIN(60, expected, actualBigDelta, 3); +} + +void testHEX8ArrayWithinDeltaAndMessage(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + UNITY_UINT8 actualSmallDelta[] = {0x35, 0x21, 0x77}; + UNITY_UINT8 actualBigDelta[] = {0x47, 0x48, 0x4C}; + + TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(60, expected, actualBigDelta, 3, "Custom Message."); +} + +void testHEX8ArrayNotWithinDelta(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + UNITY_UINT8 actualBigDelta[] = {0x67, 0x88, 0xAC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testHEX8ArrayWithinDeltaShouldNotHaveSignIssues(void) +{ + UNITY_UINT8 expected[] = {0x7F, 0x80}; + UNITY_UINT8 actualBigDelta[] = {0x80, 0x7F}; + + TEST_ASSERT_HEX8_ARRAY_WITHIN(1, expected, actualBigDelta, 2); +} + +void testHEX8ArrayNotWithinDeltaAndMessage(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + UNITY_UINT8 actualBigDelta[] = {0x67, 0x88, 0xAC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX8ArrayWithinDeltaPointless(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + UNITY_UINT8 actualBigDelta[] = {0x67, 0x88, 0xAC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_ARRAY_WITHIN(60, expected, actualBigDelta, 0); + VERIFY_FAILS_END +} + +void testHEX8ArrayWithinDeltaPointlessAndMessage(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + UNITY_UINT8 actualBigDelta[] = {0x67, 0x88, 0xAC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(60, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX8ArrayWithinDeltaExpectedNull(void) +{ + UNITY_UINT8 actualBigDelta[] = {0x67, 0x88, 0xAC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_ARRAY_WITHIN(60, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +} + +void testHEX8ArrayWithinDeltaExpectedNullAndMessage(void) +{ + UNITY_UINT8 actualBigDelta[] = {0x67, 0x88, 0xAC}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(60, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX8ArrayWithinDeltaActualNull(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_ARRAY_WITHIN(60, expected, NULL, 3); + VERIFY_FAILS_END +} + +void testHEX8ArrayWithinDeltaActualNullAndMessage(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(60, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX8ArrayWithinDeltaSamePointer(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + + TEST_ASSERT_HEX8_ARRAY_WITHIN(60, expected, expected, 3); +} + +void testHEX8ArrayWithinDeltaSamePointerAndMessage(void) +{ + UNITY_UINT8 expected[] = {0x34, 0x22, 0x77}; + + TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(60, expected, expected, 3, "Custom Message."); +} + +void testEqualIntArrays(void) +{ + int p0[] = {1, 8, 987, -2}; + int p1[] = {1, 8, 987, -2}; + int p2[] = {1, 8, 987, 2}; + int p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p3, 1); + TEST_ASSERT_EQUAL_INT_ARRAY(NULL, NULL, 1); +} + +void testNotEqualIntArraysNullExpected(void) +{ + int* p0 = NULL; + int p1[] = {1, 8, 987, 2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntArraysNullActual(void) +{ + int* p1 = NULL; + int p0[] = {1, 8, 987, 2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntArrays1(void) +{ + int p0[] = {1, 8, 987, -2}; + int p1[] = {1, 8, 987, 2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntArrays2(void) +{ + int p0[] = {1, 8, 987, -2}; + int p1[] = {2, 8, 987, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntArrays3(void) +{ + int p0[] = {1, 8, 987, -2}; + int p1[] = {1, 8, 986, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntArraysLengthZero(void) +{ + UNITY_UINT32 p0[1] = {1}; + UNITY_UINT32 p1[1] = {1}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 0); + VERIFY_FAILS_END +} + +void testEqualIntEachEqual(void) +{ + int p0[] = {1, 1, 1, 1}; + int p1[] = {987, 987, 987, 987}; + int p2[] = {-2, -2, -2, -3}; + int p3[] = {1, 5, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_INT(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_INT(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_INT(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_INT(-2, p2, 3); + TEST_ASSERT_EACH_EQUAL_INT(1, p3, 1); +} + +void testNotEqualIntEachEqualNullActual(void) +{ + int* p1 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(1, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntEachEqual1(void) +{ + int p0[] = {1, 1, 1, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(1, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntEachEqual2(void) +{ + int p0[] = {-5, -5, -1, -5}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(-5, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntEachEqual3(void) +{ + int p0[] = {1, 88, 88, 88}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(88, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualEachEqualLengthZero(void) +{ + UNITY_UINT32 p0[1] = {1}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(0, p0, 0); + VERIFY_FAILS_END +} + +void testEqualPtrArrays(void) +{ + char A = 1; + char B = 2; + char C = 3; + char* p0[] = {&A, &B, &C}; + char* p1[] = {&A, &B, &C, &A}; + char* p2[] = {&A, &B}; + char* p3[] = {&A}; + + TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p0, 3); + TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 3); + TEST_ASSERT_EQUAL_PTR_ARRAY(p1, p2, 2); + TEST_ASSERT_EQUAL_PTR_ARRAY(p3, p0, 1); +} + +void testNotEqualPtrArraysNullExpected(void) +{ + char A = 1; + char B = 2; + char** p0 = NULL; + char* p1[] = {&A, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 2); + VERIFY_FAILS_END +} + +void testNotEqualPtrArraysNullActual(void) +{ + char A = 1; + char B = 2; + char** p0 = NULL; + char* p1[] = {&A, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_PTR_ARRAY(p1, p0, 2); + VERIFY_FAILS_END +} + +void testNotEqualPtrArrays1(void) +{ + char A = 1; + char B = 2; + char C = 3; + char* p0[] = {&A, &B, &C, &B}; + char* p1[] = {&A, &B, &C, &A}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualPtrArrays2(void) +{ + char A = 1; + char B = 2; + char C = 3; + char* p0[] = {&B, &B, &C, &A}; + char* p1[] = {&A, &B, &C, &A}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualPtrArrays3(void) +{ + char A = 1; + char B = 2; + char C = 3; + char* p0[] = {&A, &B, &B, &A}; + char* p1[] = {&A, &B, &C, &A}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualPtrEachEqual(void) +{ + char A = 1; + char B = 2; + char C = 3; + char* p0[] = {&A, &A, &A}; + char* p1[] = {&A, &B, &C, &A}; + char* p2[] = {&B, &B}; + char* p3[] = {&C}; + + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 1); + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 3); + TEST_ASSERT_EACH_EQUAL_PTR(&A, p1, 1); + TEST_ASSERT_EACH_EQUAL_PTR(&B, p2, 2); + TEST_ASSERT_EACH_EQUAL_PTR(&C, p3, 1); +} + +void testNotEqualPtrEachEqualNullExpected(void) +{ + char A = 1; + char B = 1; + char* p0[] = {&A, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 2); + VERIFY_FAILS_END +} + +void testNotEqualPtrEachEqualNullActual(void) +{ + char A = 1; + char** p0 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 2); + VERIFY_FAILS_END +} + +void testNotEqualPtrEachEqual1(void) +{ + char A = 1; + char B = 1; + char* p0[] = {&A, &A, &A, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualPtrEachEqual2(void) +{ + char A = 1; + char B = 1; + char* p0[] = {&B, &B, &A, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&B, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualPtrEachEqual3(void) +{ + char A = 1; + char B = 1; + char* p0[] = {&A, &B, &B, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&B, p0, 4); + VERIFY_FAILS_END +} + +void testEqualInt8Arrays(void) +{ + UNITY_INT8 p0[] = {1, 8, 117, -2}; + UNITY_INT8 p1[] = {1, 8, 117, -2}; + UNITY_INT8 p2[] = {1, 8, 117, 2}; + UNITY_INT8 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p3, 1); +} + +void testNotEqualInt8Arrays(void) +{ + UNITY_INT8 p0[] = {1, 8, 36, -2}; + UNITY_INT8 p1[] = {1, 8, 36, 2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualInt8EachEqual(void) +{ + UNITY_INT8 p0[] = {1, 1, 1, 1}; + UNITY_INT8 p1[] = {117, 117, 117, -2}; + UNITY_INT8 p2[] = {-1, -1, 117, 2}; + UNITY_INT8 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_INT8(117, p1, 3); + TEST_ASSERT_EACH_EQUAL_INT8(-1, p2, 2); + TEST_ASSERT_EACH_EQUAL_INT8(1, p3, 1); +} + +void testNotEqualInt8EachEqual(void) +{ + UNITY_INT8 p0[] = {1, 8, 36, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 2); + VERIFY_FAILS_END +} + +void testEqualCHARArrays(void) +{ + char p0[] = {1, 8, 117, -2}; + char p1[] = {1, 8, 117, -2}; + char p2[] = {1, 8, 117, 2}; + char p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EQUAL_CHAR_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_CHAR_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_CHAR_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_CHAR_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_CHAR_ARRAY(p0, p3, 1); +} + +void testNotEqualCHARArrays(void) +{ + char p0[] = {1, 8, 36, -2}; + char p1[] = {1, 8, 36, 2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_CHAR_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualCHAREachEqual(void) +{ + char p0[] = {1, 1, 1, 1}; + char p1[] = {117, 117, 117, -2}; + char p2[] = {-1, -1, 117, 2}; + char p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EACH_EQUAL_CHAR(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_CHAR(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_CHAR(117, p1, 3); + TEST_ASSERT_EACH_EQUAL_CHAR(-1, p2, 2); + TEST_ASSERT_EACH_EQUAL_CHAR(1, p3, 1); +} + +void testNotEqualCHAREachEqual(void) +{ + char p0[] = {1, 8, 36, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_CHAR(1, p0, 2); + VERIFY_FAILS_END +} + +void testEqualUIntArrays(void) +{ + unsigned int p0[] = {1, 8, 987, 65132u}; + unsigned int p1[] = {1, 8, 987, 65132u}; + unsigned int p2[] = {1, 8, 987, 2}; + unsigned int p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p3, 1); +} + +void testNotEqualUIntArrays1(void) +{ + unsigned int p0[] = {1, 8, 987, 65132u}; + unsigned int p1[] = {1, 8, 987, 65131u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualUIntArrays2(void) +{ + unsigned int p0[] = {1, 8, 987, 65132u}; + unsigned int p1[] = {2, 8, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualUIntArrays3(void) +{ + unsigned int p0[] = {1, 8, 987, 65132u}; + unsigned int p1[] = {1, 8, 986, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualUIntEachEqual(void) +{ + unsigned int p0[] = {1, 1, 1, 1}; + unsigned int p1[] = {65132u, 65132u, 65132u, 65132u}; + unsigned int p2[] = {8, 8, 987, 2}; + unsigned int p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_UINT(65132u, p1, 4); + TEST_ASSERT_EACH_EQUAL_UINT(8, p2, 2); + TEST_ASSERT_EACH_EQUAL_UINT(1, p3, 1); +} + +void testNotEqualUIntEachEqual1(void) +{ + unsigned int p0[] = {1, 65132u, 65132u, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUIntEachEqual2(void) +{ + unsigned int p0[] = {987, 8, 987, 987}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUIntEachEqual3(void) +{ + unsigned int p0[] = {1, 1, 1, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 4); + VERIFY_FAILS_END +} + +void testEqualInt16Arrays(void) +{ + UNITY_INT16 p0[] = {1, 8, 117, 3}; + UNITY_INT16 p1[] = {1, 8, 117, 3}; + UNITY_INT16 p2[] = {1, 8, 117, 2}; + UNITY_INT16 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p3, 1); +} + +void testNotEqualInt16Arrays(void) +{ + UNITY_INT16 p0[] = {1, 8, 127, 3}; + UNITY_INT16 p1[] = {1, 8, 127, 2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualInt16EachEqual(void) +{ + UNITY_INT16 p0[] = {1, 1, 1, 1}; + UNITY_INT16 p1[] = {32111, 32111, 32111, 3}; + UNITY_INT16 p2[] = {-1, -1, -1, 2}; + UNITY_INT16 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EACH_EQUAL_INT16(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_INT16(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_INT16(32111, p1, 3); + TEST_ASSERT_EACH_EQUAL_INT16(-1, p2, 3); + TEST_ASSERT_EACH_EQUAL_INT16(1, p3, 1); +} + +void testNotEqualInt16EachEqual(void) +{ + UNITY_INT16 p0[] = {127, 127, 127, 3}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT16(127, p0, 4); + VERIFY_FAILS_END +} + +void testEqualInt32Arrays(void) +{ + UNITY_INT32 p0[] = {1, 8, 117, 3}; + UNITY_INT32 p1[] = {1, 8, 117, 3}; + UNITY_INT32 p2[] = {1, 8, 117, 2}; + UNITY_INT32 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p3, 1); +} + +void testNotEqualInt32Arrays(void) +{ + UNITY_INT32 p0[] = {1, 8, 127, 3}; + UNITY_INT32 p1[] = {1, 8, 127, 2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualInt32EachEqual(void) +{ + UNITY_INT32 p0[] = {8, 8, 8, 8}; + UNITY_INT32 p1[] = {65537, 65537, 65537, 65537}; + UNITY_INT32 p2[] = {-3, -3, -3, 2}; + UNITY_INT32 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EACH_EQUAL_INT32(8, p0, 1); + TEST_ASSERT_EACH_EQUAL_INT32(8, p0, 4); + TEST_ASSERT_EACH_EQUAL_INT32(65537, p1, 4); + TEST_ASSERT_EACH_EQUAL_INT32(-3, p2, 3); + TEST_ASSERT_EACH_EQUAL_INT32(1, p3, 1); +} + +void testNotEqualInt32EachEqual(void) +{ + UNITY_INT32 p0[] = {127, 8, 127, 127}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT32(127, p0, 4); + VERIFY_FAILS_END +} + +void testEqualUINT8Arrays(void) +{ + UNITY_UINT8 p0[] = {1, 8, 100, 127}; + UNITY_UINT8 p1[] = {1, 8, 100, 127}; + UNITY_UINT8 p2[] = {1, 8, 100, 2}; + UNITY_UINT8 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p3, 1); +} + +void testNotEqualUINT8Arrays1(void) +{ + unsigned char p0[] = {1, 8, 100, 127u}; + unsigned char p1[] = {1, 8, 100, 255u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT8Arrays2(void) +{ + unsigned char p0[] = {1, 8, 100, 127u}; + unsigned char p1[] = {1, 8, 100, 255u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT8Arrays3(void) +{ + unsigned char p0[] = {1, 8, 100, 127u}; + unsigned char p1[] = {1, 8, 100, 255u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + + +void testEqualUINT16Arrays(void) +{ + unsigned short p0[] = {1, 8, 987, 65132u}; + unsigned short p1[] = {1, 8, 987, 65132u}; + unsigned short p2[] = {1, 8, 987, 2}; + unsigned short p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p3, 1); +} + +void testNotEqualUINT16Arrays1(void) +{ + unsigned short p0[] = {1, 8, 987, 65132u}; + unsigned short p1[] = {1, 8, 987, 65131u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT16Arrays2(void) +{ + unsigned short p0[] = {1, 8, 987, 65132u}; + unsigned short p1[] = {2, 8, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT16Arrays3(void) +{ + unsigned short p0[] = {1, 8, 987, 65132u}; + unsigned short p1[] = {1, 8, 986, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualUINT32Arrays(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p2[] = {1, 8, 987, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p3, 1); +} + +void testNotEqualUINT32Arrays1(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 987, 65131u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT32Arrays2(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {2, 8, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT32Arrays3(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 986, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualHEXArrays(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p2[] = {1, 8, 987, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p3, 1); +} + +void testNotEqualHEXArrays1(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 987, 65131u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEXArrays2(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {2, 8, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEXArrays3(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 986, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualHEX32Arrays(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p2[] = {1, 8, 987, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p3, 1); +} + +void testNotEqualHEX32Arrays1(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 987, 65131u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX32Arrays2(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {2, 8, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX32Arrays3(void) +{ + UNITY_UINT32 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT32 p1[] = {1, 8, 986, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualHEX16Arrays(void) +{ + unsigned short p0[] = {1, 8, 987, 65132u}; + unsigned short p1[] = {1, 8, 987, 65132u}; + unsigned short p2[] = {1, 8, 987, 2}; + unsigned short p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p3, 1); +} + +void testNotEqualHEX16Arrays1(void) +{ + unsigned short p0[] = {1, 8, 987, 65132u}; + unsigned short p1[] = {1, 8, 987, 65131u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX16Arrays2(void) +{ + unsigned short p0[] = {1, 8, 987, 65132u}; + unsigned short p1[] = {2, 8, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX16Arrays3(void) +{ + unsigned short p0[] = {1, 8, 987, 65132u}; + unsigned short p1[] = {1, 8, 986, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualHEX8Arrays(void) +{ + unsigned char p0[] = {1, 8, 254u, 123}; + unsigned char p1[] = {1, 8, 254u, 123}; + unsigned char p2[] = {1, 8, 254u, 2}; + unsigned char p3[] = {1, 23, 25, 26}; + + TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p3, 1); +} + +void testNotEqualHEX8Arrays1(void) +{ + unsigned char p0[] = {1, 8, 254u, 253u}; + unsigned char p1[] = {1, 8, 254u, 252u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX8Arrays2(void) +{ + unsigned char p0[] = {1, 8, 254u, 253u}; + unsigned char p1[] = {2, 8, 254u, 253u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX8Arrays3(void) +{ + unsigned char p0[] = {1, 8, 254u, 253u}; + unsigned char p1[] = {1, 8, 255u, 253u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +} + +void testEqualUINT8EachEqual(void) +{ + UNITY_UINT8 p0[] = {127u, 127u, 127u, 127u}; + UNITY_UINT8 p1[] = {1u, 1u, 1u, 1u}; + UNITY_UINT8 p2[] = {128u, 128u, 128u, 2u}; + UNITY_UINT8 p3[] = {1u, 50u, 60u, 70u}; + + TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 1); + TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 4); + TEST_ASSERT_EACH_EQUAL_UINT8(1u, p1, 4); + TEST_ASSERT_EACH_EQUAL_UINT8(128u, p2, 3); + TEST_ASSERT_EACH_EQUAL_UINT8(1u, p3, 1); +} + +void testNotEqualUINT8EachEqual1(void) +{ + unsigned char p0[] = {127u, 127u, 128u, 127u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT8EachEqual2(void) +{ + unsigned char p0[] = {1, 1, 1, 127u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT8(1, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT8EachEqual3(void) +{ + unsigned char p0[] = {54u, 55u, 55u, 55u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT8(55u, p0, 4); + VERIFY_FAILS_END +} + +void testEqualUINT16EachEqual(void) +{ + unsigned short p0[] = {65132u, 65132u, 65132u, 65132u}; + unsigned short p1[] = {987, 987, 987, 987}; + unsigned short p2[] = {1, 1, 1, 2}; + unsigned short p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_UINT16(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_UINT16(1, p2, 3); + TEST_ASSERT_EACH_EQUAL_UINT16(1, p3, 1); +} + +void testNotEqualUINT16EachEqual1(void) +{ + unsigned short p0[] = {1, 65132u, 65132u, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT16EachEqual2(void) +{ + unsigned short p0[] = {65132u, 65132u, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT16EachEqual3(void) +{ + unsigned short p0[] = {65132u, 65132u, 65132u, 65133u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testEqualUINT32EachEqual(void) +{ + UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; + UNITY_UINT32 p1[] = {987, 987, 987, 987}; + UNITY_UINT32 p2[] = {8, 8, 8, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_UINT32(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_UINT32(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_UINT32(1, p3, 1); +} + +void testNotEqualUINT32EachEqual1(void) +{ + UNITY_UINT32 p0[] = {65132u, 65132u, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT32EachEqual2(void) +{ + UNITY_UINT32 p0[] = {1, 987, 987, 987}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT32(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT32EachEqual3(void) +{ + UNITY_UINT32 p0[] = {1, 1, 1, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT32(1, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEXEachEqual(void) +{ + UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; + UNITY_UINT32 p1[] = {987, 987, 987, 987}; + UNITY_UINT32 p2[] = {8, 8, 8, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_HEX(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_HEX(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_HEX(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_HEX(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_HEX(1, p3, 1); +} + +void testNotEqualHEXEachEqual1(void) +{ + UNITY_UINT32 p0[] = {1, 65132u, 65132u, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEXEachEqual2(void) +{ + UNITY_UINT32 p0[] = {987, 987, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEXEachEqual3(void) +{ + UNITY_UINT32 p0[] = {8, 8, 987, 8}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX(8, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEX32EachEqual(void) +{ + UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; + UNITY_UINT32 p1[] = {987, 987, 987, 987}; + UNITY_UINT32 p2[] = {8, 8, 8, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_HEX32(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_HEX32(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_HEX32(1, p3, 1); +} + +void testNotEqualHEX32EachEqual1(void) +{ + UNITY_UINT32 p0[] = {65132u, 8, 65132u, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX32EachEqual2(void) +{ + UNITY_UINT32 p0[] = {1, 987, 987, 987}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX32EachEqual3(void) +{ + UNITY_UINT32 p0[] = {8, 8, 8, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(8, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEX16EachEqual(void) +{ + UNITY_UINT16 p0[] = {65132u, 65132u, 65132u, 65132u}; + UNITY_UINT16 p1[] = {987, 987, 987, 987}; + UNITY_UINT16 p2[] = {8, 8, 8, 2}; + UNITY_UINT16 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_HEX16(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_HEX16(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_HEX16(1, p3, 1); +} + +void testNotEqualHEX16EachEqual1(void) +{ + unsigned short p0[] = {65132u, 65132u, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX16EachEqual2(void) +{ + unsigned short p0[] = {1, 987, 987, 987}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX16(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX16EachEqual3(void) +{ + unsigned short p0[] = {8, 8, 8, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX16(8, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEX8EachEqual(void) +{ + unsigned char p0[] = {254u, 254u, 254u, 254u}; + unsigned char p1[] = {123, 123, 123, 123}; + unsigned char p2[] = {8, 8, 8, 2}; + unsigned char p3[] = {1, 23, 25, 26}; + + TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 1); + TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 4); + TEST_ASSERT_EACH_EQUAL_HEX8(123, p1, 4); + TEST_ASSERT_EACH_EQUAL_HEX8(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_HEX8(1, p3, 1); +} + +void testNotEqualHEX8EachEqual1(void) +{ + unsigned char p0[] = {253u, 253u, 254u, 253u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX8(253u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX8EachEqual2(void) +{ + unsigned char p0[] = {254u, 254u, 254u, 253u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX8EachEqual3(void) +{ + unsigned char p0[] = {1, 8, 8, 8}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX8(8, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEX64Arrays(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT64 p1[] = {1, 8, 987, 65132u}; + UNITY_UINT64 p2[] = {1, 8, 987, 2}; + UNITY_UINT64 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p3, 1); +#endif +} + +void testEqualUint64Arrays(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT64 p1[] = {1, 8, 987, 65132u}; + UNITY_UINT64 p2[] = {1, 8, 987, 2}; + UNITY_UINT64 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p3, 1); +#endif +} + +void testEqualInt64Arrays(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 p0[] = {1, 8, 987, -65132}; + UNITY_INT64 p1[] = {1, 8, 987, -65132}; + UNITY_INT64 p2[] = {1, 8, 987, -2}; + UNITY_INT64 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p3, 1); +#endif +} + + +void testNotEqualHEX64Arrays1(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT64 p1[] = {1, 8, 987, 65131u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualHEX64Arrays2(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT64 p1[] = {2, 8, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualUint64Arrays(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 p0[] = {1, 8, 987, 65132u}; + UNITY_UINT64 p1[] = {1, 8, 987, 65131u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualInt64Arrays(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 p0[] = {1, 8, 987, -65132}; + UNITY_INT64 p1[] = {1, 8, 987, -65131}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testVerifyIntPassingPointerComparisonOnZeroLengthArray(void) +{ + int a[] = { 1 }; + +#ifndef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(a, a, 0); + VERIFY_FAILS_END +#else + + TEST_ASSERT_EQUAL_INT_ARRAY(a, a, 0); +#endif +} + +void testVerifyIntFailingPointerComparisonOnZeroLengthArray(void) +{ + int a[] = { 1 }; + int b[] = { 1 }; + +#ifndef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(a, b, 0); + VERIFY_FAILS_END +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_ARRAY(a, b, 0); + VERIFY_FAILS_END +#endif +} diff --git a/src/subprojects/unity/test/tests/test_unity_core.c b/src/subprojects/unity/test/tests/test_unity_core.c new file mode 100644 index 00000000..866f2ab1 --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_core.c @@ -0,0 +1,375 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#define TEST_INSTANCES +#include "self_assessment_utils.h" + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + { + /* These will be skipped internally if already failed/ignored */ + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); + } + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +void testUnitySizeInitializationReminder(void) +{ + /* This test ensures that sizeof(struct UNITY_STORAGE_T) doesn't change. If this + * test breaks, go look at the initialization of the Unity global variable + * in unity.c and make sure we're filling in the proper fields. */ + const char* message = "Unexpected size for UNITY_STORAGE_T struct. Please check that " + "the initialization of the Unity symbol in unity.c is " + "still correct."; + + /* Define a structure with all the same fields as `struct UNITY_STORAGE_T`. */ +#ifdef UNITY_EXCLUDE_DETAILS + struct { + const char* TestFile; + const char* CurrentTestName; + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif + } _Expected_Unity; +#else + struct { + const char* TestFile; + const char* CurrentTestName; + const char* CurrentDetails1; + const char* CurrentDetails2; + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_COUNTER_TYPE CurrentTestStartTime; + UNITY_COUNTER_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif + } _Expected_Unity; +#endif + + /* Compare our fake structure's size to the actual structure's size. They + * should be the same. + * + * This accounts for alignment, padding, and packing issues that might come + * up between different architectures. */ + TEST_ASSERT_EQUAL_MESSAGE(sizeof(_Expected_Unity), sizeof(Unity), message); +} + +void testPassShouldEndImmediatelyWithPass(void) +{ + TEST_PASS(); + TEST_FAIL_MESSAGE("We should have passed already and finished this test"); +} + +void testPassShouldEndImmediatelyWithPassAndMessage(void) +{ + TEST_PASS_MESSAGE("Woohoo! This Automatically Passes!"); + TEST_FAIL_MESSAGE("We should have passed already and finished this test"); +} + +void testMessageShouldDisplayMessageWithoutEndingAndGoOnToPass(void) +{ + TEST_MESSAGE("This is just a message"); + TEST_MESSAGE("This is another message"); + TEST_PASS(); +} + +void testMessageShouldDisplayMessageWithoutEndingAndGoOnToFail(void) +{ + TEST_MESSAGE("This is yet another message"); + + EXPECT_ABORT_BEGIN + TEST_FAIL(); + VERIFY_FAILS_END +} + +void testTrue(void) +{ + TEST_ASSERT(1); + + TEST_ASSERT_TRUE(1); +} + +void testFalse(void) +{ + TEST_ASSERT_FALSE(0); + + TEST_ASSERT_UNLESS(0); +} + +void testSingleStatement(void) +{ + for(int i = 0; i < 2; i++) + { + /* TEST_ASSERT_TRUE should expand to a single C statement, minus + * the semicolon. This if-else will fail to compile otherwise. */ + if(i > 0) + TEST_ASSERT_TRUE(i); + else + TEST_ASSERT_FALSE(i); + } +} + +void testPreviousPass(void) +{ + TEST_ASSERT_EQUAL_INT(0U, Unity.TestFailures); +} + +void testNotVanilla(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT(0); + VERIFY_FAILS_END +} + +void testNotTrue(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_TRUE(0); + VERIFY_FAILS_END +} + +void testNotFalse(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_FALSE(1); + VERIFY_FAILS_END +} + +void testNotUnless(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UNLESS(1); + VERIFY_FAILS_END +} + +void testNotNotEqual(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL(10, 10); + VERIFY_FAILS_END +} + +void testFail(void) +{ + EXPECT_ABORT_BEGIN + TEST_FAIL_MESSAGE("Expected for testing"); + VERIFY_FAILS_END +} + +void testIsNull(void) +{ + char* ptr1 = NULL; + const char* ptr2 = "hello"; + + TEST_ASSERT_NULL(ptr1); + TEST_ASSERT_NOT_NULL(ptr2); +} + +void testIsNullShouldFailIfNot(void) +{ + const char* ptr1 = "hello"; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NULL(ptr1); + VERIFY_FAILS_END +} + +void testNotNullShouldFailIfNULL(void) +{ + char* ptr1 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_NULL(ptr1); + VERIFY_FAILS_END +} + +void testIsEmpty(void) +{ + const char* ptr1 = "\0"; + const char* ptr2 = "hello"; + + TEST_ASSERT_EMPTY(ptr1); + TEST_ASSERT_NOT_EMPTY(ptr2); +} + +void testIsEmptyShouldFailIfNot(void) +{ + const char* ptr1 = "hello"; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EMPTY(ptr1); + VERIFY_FAILS_END +} + +void testNotEmptyShouldFailIfEmpty(void) +{ + const char* ptr1 = "\0"; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EMPTY(ptr1); + VERIFY_FAILS_END +} + +void testIgnore(void) +{ + EXPECT_ABORT_BEGIN + TEST_IGNORE(); + TEST_FAIL_MESSAGE("This should not be reached"); + VERIFY_IGNORES_END +} + +void testIgnoreMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_IGNORE_MESSAGE("This is an expected TEST_IGNORE_MESSAGE string!"); + TEST_FAIL_MESSAGE("This should not be reached"); + VERIFY_IGNORES_END +} + +void testProtection(void) +{ + volatile int mask = 0; + + if (TEST_PROTECT()) + { + mask |= 1; + TEST_ABORT(); + } + else + { + Unity.CurrentTestFailed = 0; + mask |= 2; + } + + TEST_ASSERT_EQUAL(3, mask); +} + +void testIgnoredAndThenFailInTearDown(void) +{ + SetToOneToFailInTearDown = 1; + TEST_IGNORE(); +} + +void testFailureCountIncrementsAndIsReturnedAtEnd(void) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + int failures = 0; + UNITY_COUNTER_TYPE savedGetFlushSpyCalls = 0; + UNITY_COUNTER_TYPE savedFailures = Unity.TestFailures; + Unity.CurrentTestFailed = 1; + startPutcharSpy(); /* Suppress output */ + startFlushSpy(); + savedGetFlushSpyCalls = getFlushSpyCalls(); + UnityConcludeTest(); + endPutcharSpy(); + TEST_ASSERT_EQUAL(0, savedGetFlushSpyCalls); + TEST_ASSERT_EQUAL(savedFailures + 1, Unity.TestFailures); +#if defined(UNITY_OUTPUT_FLUSH) && defined(UNITY_OUTPUT_FLUSH_HEADER_DECLARATION) + TEST_ASSERT_EQUAL(1, getFlushSpyCalls()); +#else + TEST_ASSERT_EQUAL(0, getFlushSpyCalls()); +#endif + endFlushSpy(); + + startPutcharSpy(); /* Suppress output */ + failures = UnityEnd(); + Unity.TestFailures--; + endPutcharSpy(); + TEST_ASSERT_EQUAL(savedFailures + 1, failures); +#endif +} + +/* ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DETAIL SUPPORT ================== */ + +void testThatDetailsCanBeHandleOneDetail(void) +{ +#ifdef UNITY_EXCLUDE_DETAILS + TEST_IGNORE(); +#else + UNITY_SET_DETAIL("Detail1"); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT_MESSAGE(5, 6, "Should Fail And Say Detail1"); + VERIFY_FAILS_END +#endif +} + +void testThatDetailsCanHandleTestFail(void) +{ +#ifdef UNITY_EXCLUDE_DETAILS + TEST_IGNORE(); +#else + UNITY_SET_DETAILS("Detail1","Detail2"); + + EXPECT_ABORT_BEGIN + TEST_FAIL_MESSAGE("Should Fail And Say Detail1 and Detail2"); + VERIFY_FAILS_END +#endif +} + +void testThatDetailsCanBeHandleTwoDetails(void) +{ +#ifdef UNITY_EXCLUDE_DETAILS + TEST_IGNORE(); +#else + UNITY_SET_DETAILS("Detail1","Detail2"); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX8_MESSAGE(7, 8, "Should Fail And Say Detail1 and Detail2"); + VERIFY_FAILS_END +#endif +} + +void testThatDetailsCanBeHandleSingleDetailClearingTwoDetails(void) +{ +#ifdef UNITY_EXCLUDE_DETAILS + TEST_IGNORE(); +#else + UNITY_SET_DETAILS("Detail1","Detail2"); + UNITY_SET_DETAIL("DetailNew"); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_MESSAGE("MEH", "GUH", "Should Fail And Say DetailNew"); + VERIFY_FAILS_END +#endif +} diff --git a/src/subprojects/unity/test/tests/test_unity_doubles.c b/src/subprojects/unity/test/tests/test_unity_doubles.c new file mode 100644 index 00000000..b9e70cff --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_doubles.c @@ -0,0 +1,1285 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#define TEST_INSTANCES +#include "self_assessment_utils.h" + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + { + /* These will be skipped internally if already failed/ignored */ + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); + } + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +void testDoublesWithinDelta(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_WITHIN(0.00003, 187245.03485, 187245.03488); + TEST_ASSERT_DOUBLE_WITHIN(1.0, 187245.0, 187246.0); + TEST_ASSERT_DOUBLE_WITHIN(0.05, 9273.2549, 9273.2049); + TEST_ASSERT_DOUBLE_WITHIN(0.007, -726.93725, -726.94424); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_NOT_WITHIN(0.05, 9273.2549, 9273.2049); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotWithinDelta(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_NOT_WITHIN(0.05, 9273.2649, 9273.2049); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_WITHIN(0.05, 9273.2649, 9273.2049); + VERIFY_FAILS_END +#endif +} + + +void testDoublesEqual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_DOUBLE(187245123456.0, 187245123456.0); + TEST_ASSERT_EQUAL_DOUBLE(187241234567.5, 187241234567.6); + TEST_ASSERT_EQUAL_DOUBLE(9273.2512345649, 9273.25123455699); + TEST_ASSERT_EQUAL_DOUBLE(-726.12345693724, -726.1234569374); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_DOUBLE(-726.12345693724, -726.1234569374); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(9273.9649, 9273.0049); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(9273.9649, 9273.0049); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualNegative1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(-9273.9649, -9273.0049); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(-9273.9649, -9273.0049); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualNegative2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(-9273.0049, -9273.9649); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(-9273.0049, -9273.9649); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualActualNaN(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(85.963, 0.0 / d_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(85.963, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualExpectedNaN(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(0.0 / d_zero, 85.963); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 85.963); + VERIFY_FAILS_END +#endif +} + +void testDoublesEqualBothNaN(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 0.0 / d_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_DOUBLE(0.0 / d_zero, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualInfNaN(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(1.0 / d_zero, 0.0 / d_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualNaNInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(0.0 / d_zero, 1.0 / d_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualActualInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(321.642, 1.0 / d_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(321.642, 1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualExpectedInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(1.0 / d_zero, 321.642); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 321.642); + VERIFY_FAILS_END +#endif +} + +void testDoublesEqualBothInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 1.0 / d_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_DOUBLE(1.0 / d_zero, 1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotEqualPlusMinusInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_DOUBLE(1.0 / d_zero, -1.0 / d_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, -1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesGreaterThan(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_THAN_DOUBLE(1.0, 2.0); + TEST_ASSERT_GREATER_THAN_DOUBLE(-1.0, 1.0); + TEST_ASSERT_GREATER_THAN_DOUBLE(-2.0, -1.0); +#endif +} + +void testDoublesGreaterThanInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_THAN_DOUBLE(1.0, 1.0 / d_zero); + TEST_ASSERT_GREATER_THAN_DOUBLE(-1.0 / d_zero, 1.0 / d_zero); + TEST_ASSERT_GREATER_THAN_DOUBLE(-1.0 / d_zero, 1.0); +#endif +} + +void testDoublesNotGreaterThan(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_DOUBLE(2.0, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterThanNanActual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_DOUBLE(1.0, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterThanNanThreshold(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_DOUBLE(0.0 / d_zero, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterThanNanBoth(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_DOUBLE(0.0 / d_zero, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterThanInfActual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_DOUBLE(1.0 / d_zero, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterThanNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_DOUBLE(1.0, -1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterThanBothInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_DOUBLE(1.0 / d_zero, 1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterThanBothNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_DOUBLE(-1.0 / d_zero, -1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesGreaterOrEqual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(1.0, 2.0); + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(2.0, 2.0); + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(-1.0, 1.0); + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(-2.0, -1.0); + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(-2.0, -2.0); +#endif +} + +void testDoublesGreaterOrEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(1.0, 1.0 / d_zero); + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(-1.0 / d_zero, 1.0 / d_zero); + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(-1.0 / d_zero, 1.0); +#endif +} + +void testDoublesNotGreaterOrEqual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(2.0, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterOrEqualNanActual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(1.0, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterOrEqualNanThreshold(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(0.0 / d_zero, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesGreaterOrEqualNanBoth(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(0.0 / d_zero, 0.0 / d_zero); +#endif +} + +void testDoublesNotGreaterOrEqualInfActual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(1.0 / d_zero, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotGreaterOrEqualNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(1.0, -1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesGreaterOrEqualBothInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(1.0 / d_zero, 1.0 / d_zero); +#endif +} + +void testDoublesGreaterOrEqualBothNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(-1.0 / d_zero, -1.0 / d_zero); +#endif +} + +void testDoublesLessThan(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_THAN_DOUBLE(2.0, 1.0); + TEST_ASSERT_LESS_THAN_DOUBLE(1.0, -1.0); + TEST_ASSERT_LESS_THAN_DOUBLE(-1.0, -2.0); +#endif +} + +void testDoublesLessThanInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_THAN_DOUBLE(1.0 / d_zero, 1.0); + TEST_ASSERT_LESS_THAN_DOUBLE(1.0 / d_zero, -1.0 / d_zero); + TEST_ASSERT_LESS_THAN_DOUBLE(1.0, -1.0 / d_zero); +#endif +} + +void testDoublesNotLessThan(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_DOUBLE(1.0, 2.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessThanNanActual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_DOUBLE(1.0, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessThanNanThreshold(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_DOUBLE(0.0 / d_zero, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessThanNanBoth(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_DOUBLE(0.0 / d_zero, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessThanInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_DOUBLE(1.0, 1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessThanNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_DOUBLE(-1.0 / d_zero, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessThanBothInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_DOUBLE(1.0 / d_zero, 1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessThanBothNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_DOUBLE(-1.0 / d_zero, -1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesLessOrEqual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(2.0, 1.0); + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(2.0, 2.0); + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(1.0, -1.0); + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(-1.0, -2.0); + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(-2.0, -2.0); +#endif +} + +void testDoublesLessOrEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(1.0 / d_zero, 1.0); + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(1.0 / d_zero, -1.0 / d_zero); + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(1.0, -1.0 / d_zero); +#endif +} + +void testDoublesNotLessOrEqual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(1.0, 2.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessOrEqualNanActual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(1.0, 0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessOrEqualNanThreshold(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(0.0 / d_zero, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesLessOrEqualNanBoth(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(0.0 / d_zero, 0.0 / d_zero); +#endif +} + +void testDoublesNotLessOrEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(1.0, 1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoublesNotLessOrEqualNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(-1.0 / d_zero, 1.0); + VERIFY_FAILS_END +#endif +} + +void testDoublesLessOrEqualBothInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(1.0 / d_zero, 1.0 / d_zero); +#endif +} + +void testDoublesLessOrEqualBothNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(-1.0 / d_zero, -1.0 / d_zero); +#endif +} + +void testDoubleIsPosInf1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_IS_INF(2.0 / d_zero); +#endif +} + +void testDoubleIsPosInf2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_NOT_INF(2.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoubleIsNegInf1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_IS_NEG_INF(-3.0 / d_zero); +#endif +} + +void testDoubleIsNegInf2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(-3.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoubleIsNotPosInf1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_INF(2.0); + VERIFY_FAILS_END +#endif +} + +void testDoubleIsNotPosInf2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_IS_NOT_INF(2.0); +#endif +} + +void testDoubleIsNotNegInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_NEG_INF(-999.876); + VERIFY_FAILS_END +#endif +} + +void testDoubleIsNan1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_IS_NAN(0.0 / d_zero); +#endif +} + +void testDoubleIsNan2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_NOT_NAN(0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoubleIsNotNan1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_NAN(234.9); + VERIFY_FAILS_END +#endif +} + +void testDoubleIsNotNan2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_IS_NOT_NAN(234.9); +#endif +} + +void testDoubleInfIsNotNan(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_NAN(1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoubleNanIsNotInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_INF(0.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoubleIsDeterminate1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_IS_DETERMINATE(0.0); + TEST_ASSERT_DOUBLE_IS_DETERMINATE(123.3); + TEST_ASSERT_DOUBLE_IS_DETERMINATE(-88.3); +#endif +} + +void testDoubleIsDeterminate2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(-88.3); + VERIFY_FAILS_END +#endif +} + +void testDoubleIsNotDeterminate1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(1.0 / d_zero); + TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(-1.0 / d_zero); + TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(0.0 / d_zero); +#endif +} + +void testDoubleIsNotDeterminate2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_IS_DETERMINATE(-1.0 / d_zero); + VERIFY_FAILS_END +#endif +} + +void testDoubleTraitFailsOnInvalidTrait(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + UnityAssertDoubleSpecial(1.0, NULL, __LINE__, UNITY_FLOAT_INVALID_TRAIT); + VERIFY_FAILS_END +#endif +} + +void testEqualDoubleArrays(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, -8.0, 25.4, -0.123}; + double p1[] = {1.0, -8.0, 25.4, -0.123}; + double p2[] = {1.0, -8.0, 25.4, -0.2}; + double p3[] = {1.0, -23.0, 25.0, -0.26}; + + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p3, 1); + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(NULL, NULL, 1); +#endif +} + +void testNotEqualDoubleArraysExpectedNull(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double* p0 = NULL; + double p1[] = {1.0, 8.0, 25.4, 0.252}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleArraysActualNull(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 8.0, 25.4, 0.253}; + double* p1 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleArrays1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 8.0, 25.4, 0.25666666667}; + double p1[] = {1.0, 8.0, 25.4, 0.25666666666}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleArrays2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 8.0, 25.4, 0.253}; + double p1[] = {2.0, 8.0, 25.4, 0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleArrays3(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 8.0, 25.4, 0.253}; + double p1[] = {1.0, 8.0, 25.5, 0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleArraysNegative1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-1.0, -8.0, -25.4, -0.2566666667}; + double p1[] = {-1.0, -8.0, -25.4, -0.2566666666}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleArraysNegative2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-1.0, -8.0, -25.4, -0.253}; + double p1[] = {-2.0, -8.0, -25.4, -0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleArraysNegative3(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-1.0, -8.0, -25.4, -0.253}; + double p1[] = {-1.0, -8.0, -25.5, -0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testEqualDoubleArraysNaN(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 0.0 / d_zero, 25.4, 0.253}; + double p1[] = {1.0, 0.0 / d_zero, 25.4, 0.253}; + + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); +#endif +} + +void testEqualDoubleArraysInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 1.0 / d_zero, 25.4, 0.253}; + double p1[] = {1.0, 1.0 / d_zero, 25.4, 0.253}; + + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4); +#endif +} + +void testNotEqualDoubleArraysLengthZero(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[1] = {0.0}; + double p1[1] = {0.0}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 0); + VERIFY_FAILS_END +#endif +} + +void testDoubleArraysWithin(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, -8.0, 25.4, -0.123}; + double p1[] = {1.0, -8.0, 25.4, -0.123}; + double p2[] = {1.0, -8.0, 25.4, -0.2}; + double p3[] = {1.0, -23.0, 25.0, -0.26}; + double p4[] = {2.0, -9.0, 26.2, 0.26}; + double p5[] = {-1.0, -7.0, 29.0, 2.6}; + + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(1.0, p0, p0, 1); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(1.0, p0, p0, 4); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(1.0, p0, p1, 4); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(1.0, p0, p2, 3); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(1.0, p0, p3, 1); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(1.0, p0, p4, 1); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(1.0, p0, p4, 4); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(2.0, p0, p5, 1); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(2.0, p0, p5, 2); + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(1.0, NULL, NULL, 1); +#endif +} + +void testDoubleArraysWithinUnusualDelta(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-INFINITY, -8.0, 25.4, -0.123}; + double p1[] = {INFINITY, 10.1}; + + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(INFINITY, p0, p1, 2); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_DOUBLE_ARRAY_WITHIN(NAN, p0, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testEqualDoubleEachEqual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 1.0, 1.0, 1.0}; + double p1[] = {-0.123, -0.123, -0.123, -0.123}; + double p2[] = {25.4, 25.4, 25.4, -0.2}; + double p3[] = {1.0, -23.0, 25.0, -0.26}; + + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 1); + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 4); + TEST_ASSERT_EACH_EQUAL_DOUBLE(-0.123, p1, 4); + TEST_ASSERT_EACH_EQUAL_DOUBLE(25.4, p2, 3); + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p3, 1); +#endif +} + +void testNotEqualDoubleEachEqualActualNull(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double* p0 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(5, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqual1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {0.253, 8.0, 0.253, 0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(0.253, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqual2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {8.0, 8.0, 8.0, 0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(8.0, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqual3(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 1.0, 1.0, 0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqualNegative1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-1.0, -0.253, -0.253, -0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(-0.253, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqualNegative2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-25.4, -8.0, -25.4, -25.4}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(-25.4, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqualNegative3(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-8.0, -8.0, -8.0, -0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(-8.0, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testEqualDoubleEachEqualNaN(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {0.0 / d_zero, 0.0 / d_zero, 0.0 / d_zero, 0.0 / d_zero}; + + TEST_ASSERT_EACH_EQUAL_DOUBLE(0.0 / d_zero, p0, 4); +#endif +} + +void testEqualDoubleEachEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0 / d_zero, 1.0 / d_zero, 25.4, 0.253}; + + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0 / d_zero, p0, 2); +#endif +} + +void testNotEqualDoubleEachEqualLengthZero(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[1] = {0.0}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(0.0, p0, 0); + VERIFY_FAILS_END +#endif +} + +void testDoublePrinting(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5.0000005e-07", 0.00000050000005); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.100469499", 0.100469499); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 0.9999999995); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25); + TEST_ASSERT_EQUAL_PRINT_FLOATING("7.99999999", 7.99999999); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0000002", 16.0000002); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0000004", 16.0000004); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.0000006", 16.0000006); + TEST_ASSERT_EQUAL_PRINT_FLOATING("999999999", 999999999.0); /*Last full print integer*/ + + TEST_ASSERT_EQUAL_PRINT_FLOATING("0", -0.0); /* -0 no supported on all targets */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5.0000005e-07", -0.00000050000005); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.100469499", -0.100469499); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -0.9999999995); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.99999999", -7.99999999); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0000002", -16.0000002); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0000004", -16.0000004); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.0000006", -16.0000006); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-999999999", -999999999.0); /*Last full print integer*/ + + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.10046949999999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967295.9); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.2949673e+09", 4294967296.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 9999999995.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199254740990.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("7e+100", 7.0e+100); + TEST_ASSERT_EQUAL_PRINT_FLOATING("3e+200", 3.0e+200); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.23456789e+300", 9.23456789e+300); + + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.10046949999999999); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.2949673e+09", -4294967295.9); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.2949673e+09", -4294967296.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7e+100", -7.0e+100); +#endif +} + +void testDoublePrintingRoundTiesToEven(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + #ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00000001e+10", 10000000050.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199245000000.0); + #else /* Default to Round ties to even */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 10000000050.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719924e+15", 9007199245000000.0); + #endif +#endif +} + +void testDoublePrintingInfinityAndNaN(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_FLOATING("inf", 1.0 / d_zero); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-inf", -1.0 / d_zero); + + TEST_ASSERT_EQUAL_PRINT_FLOATING("nan", 0.0 / d_zero); +#endif +} diff --git a/src/subprojects/unity/test/tests/test_unity_floats.c b/src/subprojects/unity/test/tests/test_unity_floats.c new file mode 100644 index 00000000..006c76ab --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_floats.c @@ -0,0 +1,1395 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#define TEST_INSTANCES +#include "self_assessment_utils.h" + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + { + /* These will be skipped internally if already failed/ignored */ + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); + } + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +void testFloatsWithinDelta(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_WITHIN(0.00003f, 187245.03485f, 187245.03488f); + TEST_ASSERT_FLOAT_WITHIN(1.0f, 187245.0f, 187246.0f); + TEST_ASSERT_FLOAT_WITHIN(0.05f, 9273.2549f, 9273.2049f); + TEST_ASSERT_FLOAT_WITHIN(0.007f, -726.93724f, -726.94424f); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_NOT_WITHIN(0.05f, 9273.2549f, 9273.2049f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotWithinDelta(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_NOT_WITHIN(0.05f, 9273.2649f, 9273.2049f); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_WITHIN(0.05f, 9273.2649f, 9273.2049f); + VERIFY_FAILS_END +#endif +} + +void testFloatsEqual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_FLOAT(187245.0f, 187246.0f); + TEST_ASSERT_EQUAL_FLOAT(18724.5f, 18724.6f); + TEST_ASSERT_EQUAL_FLOAT(9273.2549f, 9273.2599f); + TEST_ASSERT_EQUAL_FLOAT(-726.93724f, -726.9374f); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_FLOAT(-726.93724f, -726.9374f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(9273.9649f, 9273.0049f); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(9273.9649f, 9273.0049f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualNegative1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(-9273.9649f, -9273.0049f); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(-9273.9649f, -9273.0049f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualNegative2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(-9273.0049f, -9273.9649f); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(-9273.0049f, -9273.9649f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualActualNaN(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(85.963f, 0.0f / f_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(85.963f, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualExpectedNaN(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(0.0f / f_zero, 85.963f); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 85.963f); + VERIFY_FAILS_END +#endif +} + +void testFloatsEqualBothNaN(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 0.0f / f_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_FLOAT(0.0f / f_zero, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualInfNaN(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(1.0f / f_zero, 0.0f / f_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualNaNInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(0.0f / f_zero, 1.0f / f_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualActualInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(321.642f, 1.0f / f_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(321.642f, 1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualExpectedInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(1.0f / f_zero, 321.642f); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 321.642f); + VERIFY_FAILS_END +#endif +} + +void testFloatsEqualBothInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 1.0f / f_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_FLOAT(1.0f / f_zero, 1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotEqualPlusMinusInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_NOT_EQUAL_FLOAT(1.0f / f_zero, -1.0f / f_zero); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, -1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsGreaterThan(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_THAN_FLOAT(1.0f, 2.0f); + TEST_ASSERT_GREATER_THAN_FLOAT(-1.0f, 1.0f); + TEST_ASSERT_GREATER_THAN_FLOAT(-2.0f, -1.0f); +#endif +} + +void testFloatsGreaterThanInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_THAN_FLOAT(1.0f, 1.0f / f_zero); + TEST_ASSERT_GREATER_THAN_FLOAT(-1.0f / f_zero, 1.0f / f_zero); + TEST_ASSERT_GREATER_THAN_FLOAT(-1.0f / f_zero, 1.0f); +#endif +} + +void testFloatsNotGreaterThan(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_FLOAT(2.0f, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterThanNanActual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_FLOAT(1.0f, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterThanNanThreshold(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_FLOAT(0.0f / f_zero, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterThanNanBoth(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_FLOAT(0.0f / f_zero, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterThanInfActual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_FLOAT(1.0f / f_zero, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterThanNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_FLOAT(1.0f, -1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterThanBothInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_FLOAT(1.0f / f_zero, 1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterThanBothNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_FLOAT(-1.0f / f_zero, -1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsGreaterOrEqual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(1.0f, 2.0f); + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(2.0f, 2.0f); + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(-1.0f, 1.0f); + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(-2.0f, -1.0f); + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(-2.0f, -2.0f); +#endif +} + +void testFloatsGreaterOrEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(1.0f, 1.0f / f_zero); + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(-1.0f / f_zero, 1.0f / f_zero); + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(-1.0f / f_zero, 1.0f); +#endif +} + +void testFloatsNotGreaterOrEqual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(2.0f, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterOrEqualNanActual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(1.0f, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterOrEqualNanThreshold(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(0.0f / f_zero, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsGreaterOrEqualNanBoth(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(0.0f / f_zero, 0.0f / f_zero); +#endif +} + +void testFloatsNotGreaterOrEqualInfActual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(1.0f / f_zero, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotGreaterOrEqualNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(1.0f, -1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsGreaterOrEqualBothInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(1.0f / f_zero, 1.0f / f_zero); +#endif +} + +void testFloatsGreaterOrEqualBothNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(-1.0f / f_zero, -1.0f / f_zero); +#endif +} + +void testFloatsLessThan(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_THAN_FLOAT(2.0f, 1.0f); + TEST_ASSERT_LESS_THAN_FLOAT(1.0f, -1.0f); + TEST_ASSERT_LESS_THAN_FLOAT(-1.0f, -2.0f); +#endif +} + +void testFloatsLessThanInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_THAN_FLOAT(1.0f / f_zero, 1.0f); + TEST_ASSERT_LESS_THAN_FLOAT(1.0f / f_zero, -1.0f / f_zero); + TEST_ASSERT_LESS_THAN_FLOAT(1.0f, -1.0f / f_zero); +#endif +} + +void testFloatsNotLessThan(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_FLOAT(1.0f, 2.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessThanNanActual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_FLOAT(1.0f, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessThanNanThreshold(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_FLOAT(0.0f / f_zero, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessThanNanBoth(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_FLOAT(0.0f / f_zero, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessThanInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_FLOAT(1.0f, 1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessThanNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_FLOAT(-1.0f / f_zero, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessThanBothInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_FLOAT(1.0f / f_zero, 1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessThanBothNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_FLOAT(-1.0f / f_zero, -1.0f / f_zero); + VERIFY_FAILS_END +#endif +} +void testFloatsLessOrEqual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(2.0f, 1.0f); + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(2.0f, 2.0f); + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(1.0f, -1.0f); + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(-1.0f, -2.0f); + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(-2.0f, -2.0f); +#endif +} + +void testFloatsLessOrEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(1.0f / f_zero, 1.0f); + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(1.0f / f_zero, -1.0f / f_zero); + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(1.0f, -1.0f / f_zero); +#endif +} + +void testFloatsNotLessOrEqual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(1.0f, 2.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessOrEqualNanActual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(1.0f, 0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessOrEqualNanThreshold(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(0.0f / f_zero, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsLessOrEqualNanBoth(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(0.0f / f_zero, 0.0f / f_zero); +#endif +} + +void testFloatsNotLessOrEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(1.0f, 1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatsNotLessOrEqualNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(-1.0f / f_zero, 1.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatsLessOrEqualBothInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(1.0f / f_zero, 1.0f / f_zero); +#endif +} + +void testFloatsLessOrEqualBothNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_LESS_OR_EQUAL_FLOAT(-1.0f / f_zero, -1.0f / f_zero); +#endif +} + +void testFloatIsPosInf1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_IS_INF(2.0f / f_zero); +#endif +} + +void testFloatIsPosInf2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_NOT_INF(2.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatIsNegInf1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_IS_NEG_INF(-3.0f / f_zero); +#endif +} + +void testFloatIsNegInf2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(-3.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatIsNotPosInf1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_INF(2.0f); + VERIFY_FAILS_END +#endif +} + +void testFloatIsNotPosInf2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_IS_NOT_INF(2.0f); +#endif +} + +void testFloatIsNotNegInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_NEG_INF(-999.876f); + VERIFY_FAILS_END +#endif +} + +void testFloatIsNan1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_IS_NAN(0.0f / f_zero); +#endif +} + +void testFloatIsNan2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_NOT_NAN(0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatIsNotNan1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_NAN(234.9f); + VERIFY_FAILS_END +#endif +} + +void testFloatIsNotNan2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_IS_NOT_NAN(234.9f); +#endif +} + +void testFloatInfIsNotNan(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_NAN(1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatNanIsNotInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_INF(0.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatIsDeterminate1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_IS_DETERMINATE(0.0f); + TEST_ASSERT_FLOAT_IS_DETERMINATE(123.3f); + TEST_ASSERT_FLOAT_IS_DETERMINATE(-88.3f); +#endif +} + +void testFloatIsDeterminate2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(-88.3f); + VERIFY_FAILS_END +#endif +} + +void testFloatIsNotDeterminate1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(1.0f / f_zero); + TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(-1.0f / f_zero); + TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(0.0f / f_zero); +#endif +} + +void testFloatIsNotDeterminate2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_IS_DETERMINATE(-1.0f / f_zero); + VERIFY_FAILS_END +#endif +} + +void testFloatTraitFailsOnInvalidTrait(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + UnityAssertFloatSpecial(1.0f, NULL, __LINE__, UNITY_FLOAT_INVALID_TRAIT); + VERIFY_FAILS_END +#endif +} + +void testEqualFloatArrays(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, -8.0f, 25.4f, -0.123f}; + float p1[] = {1.0f, -8.0f, 25.4f, -0.123f}; + float p2[] = {1.0f, -8.0f, 25.4f, -0.2f}; + float p3[] = {1.0f, -23.0f, 25.0f, -0.26f}; + + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p0, 1); + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p0, 4); + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p2, 3); + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p3, 1); + TEST_ASSERT_EQUAL_FLOAT_ARRAY(NULL, NULL, 1); +#endif +} + +void testNotEqualFloatArraysExpectedNull(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float* p0 = NULL; + float p1[] = {1.0f, 8.0f, 25.4f, 0.252f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatArraysActualNull(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 8.0f, 25.4f, 0.253f}; + float* p1 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatArrays1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 8.0f, 25.4f, 0.253f}; + float p1[] = {1.0f, 8.0f, 25.4f, 0.252f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatArrays2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 8.0f, 25.4f, 0.253f}; + float p1[] = {2.0f, 8.0f, 25.4f, 0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatArrays3(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 8.0f, 25.4f, 0.253f}; + float p1[] = {1.0f, 8.0f, 25.5f, 0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatArraysNegative1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f}; + float p1[] = {-1.0f, -8.0f, -25.4f, -0.252f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatArraysNegative2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f}; + float p1[] = {-2.0f, -8.0f, -25.4f, -0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatArraysNegative3(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f}; + float p1[] = {-1.0f, -8.0f, -25.5f, -0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); + VERIFY_FAILS_END +#endif +} + +void testEqualFloatArraysNaN(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 0.0f / f_zero, 25.4f, 0.253f}; + float p1[] = {1.0f, 0.0f / f_zero, 25.4f, 0.253f}; + + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); +#endif +} + +void testEqualFloatArraysInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f}; + float p1[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f}; + + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4); +#endif +} + +void testNotEqualFloatArraysLengthZero(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[1] = {0.0f}; + float p1[1] = {0.0f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 0); + VERIFY_FAILS_END +#endif +} + +void testFloatArraysWithin(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, -8.0f, 25.4f, -0.123f}; + float p1[] = {1.0f, -8.0f, 25.4f, -0.123f}; + float p2[] = {1.0f, -8.0f, 25.4f, -0.2f}; + float p3[] = {1.0f, -23.0f, 25.0f, -0.26f}; + float p4[] = {2.0f, -9.0f, 26.2f, 0.26f}; + float p5[] = {-1.0f, -7.0f, 29.0f, 2.6f}; + + TEST_ASSERT_FLOAT_ARRAY_WITHIN(1.0f, p0, p0, 1); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(1.0f, p0, p0, 4); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(1.0f, p0, p1, 4); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(1.0f, p0, p2, 3); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(1.0f, p0, p3, 1); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(1.0f, p0, p4, 1); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(1.0f, p0, p4, 4); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(2.0f, p0, p5, 1); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(2.0f, p0, p5, 2); + TEST_ASSERT_FLOAT_ARRAY_WITHIN(1.0f, NULL, NULL, 1); +#endif +} + +void testFloatArraysWithinUnusualDelta(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {(float)-INFINITY, -8.0f, 25.4f, -0.123f}; + float p1[] = {(float)INFINITY, 10.1f}; + + TEST_ASSERT_FLOAT_ARRAY_WITHIN(INFINITY, p0, p1, 2); + + EXPECT_ABORT_BEGIN + TEST_ASSERT_FLOAT_ARRAY_WITHIN(NAN, p0, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testEqualFloatEachEqual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 1.0f, 1.0f, 1.0f}; + float p1[] = {-0.123f, -0.123f, -0.123f, -0.123f}; + float p2[] = {25.4f, 25.4f, 25.4f, -0.2f}; + float p3[] = {1.0f, -23.0f, 25.0f, -0.26f}; + + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 1); + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 4); + TEST_ASSERT_EACH_EQUAL_FLOAT(-0.123f, p1, 4); + TEST_ASSERT_EACH_EQUAL_FLOAT(25.4f, p2, 3); + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p3, 1); +#endif +} + +void testNotEqualFloatEachEqualActualNull(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float* p0 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(5, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqual1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {0.253f, 8.0f, 0.253f, 0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(0.253f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqual2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {8.0f, 8.0f, 8.0f, 0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(8.0f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqual3(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 1.0f, 1.0f, 0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqualNegative1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-1.0f, -0.253f, -0.253f, -0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(-0.253f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqualNegative2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-25.4f, -8.0f, -25.4f, -25.4f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(-25.4f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqualNegative3(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-8.0f, -8.0f, -8.0f, -0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(-8.0f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testEqualFloatEachEqualNaN(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {0.0f / f_zero, 0.0f / f_zero, 0.0f / f_zero, 0.0f / f_zero}; + + TEST_ASSERT_EACH_EQUAL_FLOAT(0.0f / f_zero, p0, 4); +#endif +} + +void testEqualFloatEachEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f / f_zero, 1.0f / f_zero, 25.4f, 0.253f}; + + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f / f_zero, p0, 2); +#endif +} + +void testNotEqualFloatEachEqualLengthZero(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[1] = {0.0f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(0.0f, p0, 0); + VERIFY_FAILS_END +#endif +} + +void testFloatPrinting(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_INCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.100469499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("2", 1.9999995f); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.25", 1.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("7.999999", 7.999999f); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00002", 16.00002f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00004", 16.00004f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("16.00006", 16.00006f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9999999", 9999999.0f); /*Last full print integer*/ + + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.100469499f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-2", -1.9999995f); /*Rounding to int place*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1.25", -1.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-7.999999", -7.999999f); /*Not rounding*/ + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00002", -16.00002f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00004", -16.00004f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-16.00006", -16.00006f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-9999999", -9999999.0f); /*Last full print integer*/ + + /* Fails, prints "4.294968e+09" due to FP math imprecision + * TEST_ASSERT_EQUAL_PRINT_FLOATING("4.294967e+09", 4294967296.0f); */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("5e+09", 5000000000.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("8e+09", 8.0e+09f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("8.309999e+09", 8309999104.0f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 1.0e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 10000000000.0f); + /* Some compilers have trouble with inexact float constants, a float cast works generally */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.000055e+10", (float)1.000055e+10f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.1e+38", (float)1.10000005e+38f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.635299e+10", 1.63529943e+10f); + /* Fails, prints "3.402824e+38" due to FP math imprecision + * TEST_ASSERT_EQUAL_PRINT_FLOATING("3.402823e+38", 3.40282346638e38f); */ + + TEST_ASSERT_EQUAL_PRINT_FLOATING("-1e+10", -1.0e+10f); + /* Fails, prints "-3.402824e+38" due to FP math imprecision + * TEST_ASSERT_EQUAL_PRINT_FLOATING("-3.402823e+38", -3.40282346638e38f); */ +#endif +} + +void testFloatPrintingRoundTiesToEven(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_INCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + #ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0004882813", 0.00048828125f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("488281.3", 488281.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5.000001e-07", 0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5.000001e-07", -0.00000050000005f); + #else /* Default to Round ties to even */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0004882812", 0.00048828125f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("488281.2", 488281.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.00000050000005f); + #endif +#endif +} + +void testFloatPrintingInfinityAndNaN(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_FLOATING("inf", 1.0f / f_zero); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-inf", -1.0f / f_zero); + + TEST_ASSERT_EQUAL_PRINT_FLOATING("nan", 0.0f / f_zero); +#endif +} + +#if defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) && defined(USING_OUTPUT_SPY) +#ifdef UNITY_INCLUDE_DOUBLE +static void printFloatValue(float f) +{ + char expected[18]; + + startPutcharSpy(); + UnityPrintFloat(f); + + sprintf(expected, "%.9g", f); + /* We print all NaN's as "nan", not "-nan" */ + if (strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); + + if (strcmp(expected, getBufferPutcharSpy())) + { + /* Fail with diagnostic printing */ + TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f); + } +} +#else +static void printFloatValue(float f) +{ + char expected[18]; + char expected_lower[18]; + char expected_lower2[18]; + char expected_lower3[18]; + char expected_higher[18]; + char expected_higher2[18]; + char expected_higher3[18]; + + startPutcharSpy(); + UnityPrintFloat(f); + + sprintf(expected, "%.7g", f); + /* We print all NaN's as "nan", not "-nan" */ + if (strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); + + strcpy(expected_lower, expected); + strcpy(expected_lower2, expected); + strcpy(expected_lower3, expected); + strcpy(expected_higher, expected); + strcpy(expected_higher2, expected); + strcpy(expected_higher3, expected); + + /* Allow for rounding differences in the last digit */ + double lower = (double)f * 0.99999995; + double higher = (double)f * 1.00000005; + + if(isfinite(lower)) sprintf(expected_lower, "%.7g", lower); + if(isfinite(higher)) sprintf(expected_higher, "%.7g", higher); + + /* Outside [1,10000000] allow for relative error of +/-2.5e-7 */ + if (f < 1.0 || f > 10000000) + { + double lower2 = (double)f * 0.99999985; + double lower3 = (double)f * 0.99999975; + double higher2 = (double)f * 1.00000015; + double higher3 = (double)f * 1.00000025; + + if (isfinite(lower2)) sprintf(expected_lower2, "%.7g", lower2); + if (isfinite(lower3)) sprintf(expected_lower3, "%.7g", lower3); + if (isfinite(higher2)) sprintf(expected_higher2, "%.7g", higher2); + if (isfinite(higher3)) sprintf(expected_higher3, "%.7g", higher3); + } + + if (strcmp(expected, getBufferPutcharSpy()) != 0 && + strcmp(expected_lower, getBufferPutcharSpy()) != 0 && + strcmp(expected_lower2, getBufferPutcharSpy()) != 0 && + strcmp(expected_lower3, getBufferPutcharSpy()) != 0 && + strcmp(expected_higher, getBufferPutcharSpy()) != 0 && + strcmp(expected_higher2, getBufferPutcharSpy()) != 0 && + strcmp(expected_higher3, getBufferPutcharSpy()) != 0) + { + /* Fail with diagnostic printing */ + TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f); + } +} +#endif +#endif + +void testFloatPrintingRandomSamples(void) +{ +#if !defined(UNITY_TEST_ALL_FLOATS_PRINT_OK) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + union { float f_value; uint32_t int_value; } u; + + /* These values are not covered by the MINSTD generator */ + u.int_value = 0x00000000; printFloatValue(u.f_value); + u.int_value = 0x80000000; printFloatValue(u.f_value); + u.int_value = 0x7fffffff; printFloatValue(u.f_value); + u.int_value = 0xffffffff; printFloatValue(u.f_value); + + uint32_t a = 1; + for(int num_tested = 0; num_tested < 1000000; num_tested++) + { + /* MINSTD pseudo-random number generator */ + a = (uint32_t)(((uint64_t)a * 48271u) % 2147483647u); + + /* MINSTD does not set the highest bit; test both possibilities */ + u.int_value = a; printFloatValue(u.f_value); + u.int_value = a | 0x80000000; printFloatValue(u.f_value); + } +#endif +} diff --git a/src/subprojects/unity/test/tests/test_unity_integers.c b/src/subprojects/unity/test/tests/test_unity_integers.c new file mode 100644 index 00000000..1b8c6e30 --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_integers.c @@ -0,0 +1,2863 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#define TEST_INSTANCES +#include "self_assessment_utils.h" + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + { + /* These will be skipped internally if already failed/ignored */ + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); + } + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +void testNotEqualInts(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT(3982, 3983); + VERIFY_FAILS_END +} + +void testNotEqualInt8s(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT8(-127, -126); + VERIFY_FAILS_END +} + +void testNotEqualChars(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_CHAR('A', 'a'); + VERIFY_FAILS_END +} + +void testNotEqualInt16s(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT16(-16383, -16382); + VERIFY_FAILS_END +} + +void testNotEqualInt32s(void) +{ + EXPECT_ABORT_BEGIN + /*use largest 32 bit negative to test printability*/ + /*note: (-2147483647 - 1) is used instead of -2147483648 because of C90 casting rules */ + TEST_ASSERT_EQUAL_INT32(-2147483647, (-2147483647 - 1)); + VERIFY_FAILS_END +} + +void testNotEqualBits(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_BITS(0xFF00, 0x5555, 0x5A55); + VERIFY_FAILS_END +} + +void testNotEqualUInts(void) +{ + UNITY_UINT16 v0, v1; + + v0 = 9000; + v1 = 9001; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualUInt8s(void) +{ + UNITY_UINT8 v0, v1; + + v0 = 254; + v1 = 255; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT8(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualUInt16s(void) +{ + UNITY_UINT16 v0, v1; + + v0 = 65535u; + v1 = 65534u; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT16(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualUInt32s(void) +{ + UNITY_UINT32 v0, v1; + + v0 = 4294967295u; + v1 = 4294967294u; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT32(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualHex8s(void) +{ + UNITY_UINT8 v0, v1; + + v0 = 0x23; + v1 = 0x22; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX8(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualHex8sIfSigned(void) +{ + UNITY_INT8 v0, v1; + + v0 = -2; + v1 = 2; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX8(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualHex16s(void) +{ + UNITY_UINT16 v0, v1; + + v0 = 0x1234; + v1 = 0x1235; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX16(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualHex16sIfSigned(void) +{ + UNITY_INT16 v0, v1; + + v0 = -1024; + v1 = -1028; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX16(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualHex32s(void) +{ + UNITY_UINT32 v0, v1; + + v0 = 900000; + v1 = 900001; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX32(v0, v1); + VERIFY_FAILS_END +} + +void testNotEqualHex32sIfSigned(void) +{ + UNITY_INT32 v0, v1; + + v0 = -900000; + v1 = 900001; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX32(v0, v1); + VERIFY_FAILS_END +} + +void testEqualInts(void) +{ + int v0, v1; + int *p0, *p1; + + v0 = 19467; + v1 = 19467; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT(1837, 1837); + TEST_ASSERT_EQUAL_INT(-27365, -27365); + TEST_ASSERT_EQUAL_INT(v0, v1); + TEST_ASSERT_EQUAL_INT(19467, v1); + TEST_ASSERT_EQUAL_INT(v0, 19467); + TEST_ASSERT_EQUAL_INT(*p0, v1); + TEST_ASSERT_EQUAL_INT(*p0, *p1); + TEST_ASSERT_EQUAL_INT(*p0, 19467); +} + +void testEqualInt8s(void) +{ + UNITY_INT8 v0, v1; + UNITY_INT8 *p0, *p1; + + v0 = 0x22; + v1 = 0x22; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT8(0x22, 0x22); + TEST_ASSERT_EQUAL_INT8(v0, v1); + TEST_ASSERT_EQUAL_INT8(0x22, v1); + TEST_ASSERT_EQUAL_INT8(v0, 0x22); + TEST_ASSERT_EQUAL_INT8(*p0, v1); + TEST_ASSERT_EQUAL_INT8(*p0, *p1); + TEST_ASSERT_EQUAL_INT8(*p0, 0x22); +} + +void testEqualInt8sWhenThereAreDifferencesOutside8Bits(void) +{ + TEST_ASSERT_EQUAL_INT8(0x321,0x421); + TEST_ASSERT_EQUAL_INT8(0xFF21,0x0021); +} + +void testEqualChars(void) +{ + char v0, v1; + char *p0, *p1; + + v0 = 'A'; + v1 = 'A'; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_CHAR('A', 'A'); + TEST_ASSERT_EQUAL_CHAR(v0, v1); + TEST_ASSERT_EQUAL_CHAR('A', v1); + TEST_ASSERT_EQUAL_CHAR(v0, 'A'); + TEST_ASSERT_EQUAL_CHAR(*p0, v1); + TEST_ASSERT_EQUAL_CHAR(*p0, *p1); + TEST_ASSERT_EQUAL_CHAR(*p0, 'A'); +} + +void testEqualCharsWhenThereAreDifferencesOutside8Bits(void) +{ + TEST_ASSERT_EQUAL_CHAR(0x321,0x421); + TEST_ASSERT_EQUAL_CHAR(0xFF21,0x0021); +} + + +void testEqualInt16s(void) +{ + UNITY_INT16 v0, v1; + UNITY_INT16 *p0, *p1; + + v0 = 0x7876; + v1 = 0x7876; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT16(0x7876, 0x7876); + TEST_ASSERT_EQUAL_INT16(v0, v1); + TEST_ASSERT_EQUAL_INT16(0x7876, v1); + TEST_ASSERT_EQUAL_INT16(v0, 0x7876); + TEST_ASSERT_EQUAL_INT16(*p0, v1); + TEST_ASSERT_EQUAL_INT16(*p0, *p1); + TEST_ASSERT_EQUAL_INT16(*p0, 0x7876); +} + +void testEqualInt16sNegatives(void) +{ + UNITY_INT16 v0, v1; + UNITY_INT16 *p0, *p1; + + v0 = -7876; + v1 = -7876; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT16(-7876, -7876); + TEST_ASSERT_EQUAL_INT16(v0, v1); + TEST_ASSERT_EQUAL_INT16(-7876, v1); + TEST_ASSERT_EQUAL_INT16(v0, -7876); + TEST_ASSERT_EQUAL_INT16(*p0, v1); + TEST_ASSERT_EQUAL_INT16(*p0, *p1); + TEST_ASSERT_EQUAL_INT16(*p0, -7876); +} + +void testEqualInt16sWhenThereAreDifferencesOutside16Bits(void) +{ + TEST_ASSERT_EQUAL_INT16(0x54321,0x64321); + TEST_ASSERT_EQUAL_INT16(0xFFFF4321,0x00004321); +} + +void testEqualInt32s(void) +{ + UNITY_INT32 v0, v1; + UNITY_INT32 *p0, *p1; + + v0 = 0x78760000; + v1 = 0x78760000; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT32(0x78760000, 0x78760000); + TEST_ASSERT_EQUAL_INT32(v0, v1); + TEST_ASSERT_EQUAL_INT32(0x78760000, v1); + TEST_ASSERT_EQUAL_INT32(v0, 0x78760000); + TEST_ASSERT_EQUAL_INT32(*p0, v1); + TEST_ASSERT_EQUAL_INT32(*p0, *p1); + TEST_ASSERT_EQUAL_INT32(*p0, 0x78760000); +} + +void testEqualInt32sNegatives(void) +{ + UNITY_INT32 v0, v1; + UNITY_INT32 *p0, *p1; + + v0 = -123456789; + v1 = -123456789; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT32(-123456789, -123456789); + TEST_ASSERT_EQUAL_INT32(v0, v1); + TEST_ASSERT_EQUAL_INT32(-123456789, v1); + TEST_ASSERT_EQUAL_INT32(v0, -123456789); + TEST_ASSERT_EQUAL_INT32(*p0, v1); + TEST_ASSERT_EQUAL_INT32(*p0, *p1); + TEST_ASSERT_EQUAL_INT32(*p0, -123456789); +} + + +void testEqualUints(void) +{ + unsigned int v0, v1; + unsigned int *p0, *p1; + + v0 = 19467; + v1 = 19467; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_UINT(1837, 1837); + TEST_ASSERT_EQUAL_UINT(v0, v1); + TEST_ASSERT_EQUAL_UINT(19467, v1); + TEST_ASSERT_EQUAL_UINT(v0, 19467); + TEST_ASSERT_EQUAL_UINT(*p0, v1); + TEST_ASSERT_EQUAL_UINT(*p0, *p1); + TEST_ASSERT_EQUAL_UINT(*p0, 19467); + TEST_ASSERT_EQUAL_UINT(60872u, 60872u); +} + + +void testEqualUint8s(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 0x22; + v1 = 0x22; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_UINT8(0x22, 0x22); + TEST_ASSERT_EQUAL_UINT8(v0, v1); + TEST_ASSERT_EQUAL_UINT8(0x22, v1); + TEST_ASSERT_EQUAL_UINT8(v0, 0x22); + TEST_ASSERT_EQUAL_UINT8(*p0, v1); + TEST_ASSERT_EQUAL_UINT8(*p0, *p1); + TEST_ASSERT_EQUAL_UINT8(*p0, 0x22); +} + +void testEqualUint8sWhenThereAreDifferencesOutside8Bits(void) +{ + TEST_ASSERT_EQUAL_UINT8(0x321,0x421); + TEST_ASSERT_EQUAL_UINT8(0xFF21,0x0021); +} + +void testEqualUint16s(void) +{ + UNITY_UINT16 v0, v1; + UNITY_UINT16 *p0, *p1; + + v0 = 0x9876; + v1 = 0x9876; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_UINT16(0x9876, 0x9876); + TEST_ASSERT_EQUAL_UINT16(v0, v1); + TEST_ASSERT_EQUAL_UINT16(0x9876, v1); + TEST_ASSERT_EQUAL_UINT16(v0, 0x9876); + TEST_ASSERT_EQUAL_UINT16(*p0, v1); + TEST_ASSERT_EQUAL_UINT16(*p0, *p1); + TEST_ASSERT_EQUAL_UINT16(*p0, 0x9876); +} + +void testEqualUint16sWhenThereAreDifferencesOutside16Bits(void) +{ + TEST_ASSERT_EQUAL_UINT16(0x54321,0x64321); + TEST_ASSERT_EQUAL_UINT16(0xFFFF4321,0x00004321); +} + +void testEqualUint32s(void) +{ + UNITY_UINT32 v0, v1; + UNITY_UINT32 *p0, *p1; + + v0 = 0x98760000; + v1 = 0x98760000; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_UINT32(0x98760000, 0x98760000); + TEST_ASSERT_EQUAL_UINT32(v0, v1); + TEST_ASSERT_EQUAL_UINT32(0x98760000, v1); + TEST_ASSERT_EQUAL_UINT32(v0, 0x98760000); + TEST_ASSERT_EQUAL_UINT32(*p0, v1); + TEST_ASSERT_EQUAL_UINT32(*p0, *p1); + TEST_ASSERT_EQUAL_UINT32(*p0, 0x98760000); +} + +void testNotEqual(void) +{ + TEST_ASSERT_NOT_EQUAL(0, 1); + TEST_ASSERT_NOT_EQUAL(1, 0); + TEST_ASSERT_NOT_EQUAL(100, 101); + TEST_ASSERT_NOT_EQUAL(0, -1); + TEST_ASSERT_NOT_EQUAL(65535, -65535); + TEST_ASSERT_NOT_EQUAL(75, 900); + TEST_ASSERT_NOT_EQUAL(-100, -101); +} + +void testEqualHex8s(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 0x22; + v1 = 0x22; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_HEX8(0x22, 0x22); + TEST_ASSERT_EQUAL_HEX8(v0, v1); + TEST_ASSERT_EQUAL_HEX8(0x22, v1); + TEST_ASSERT_EQUAL_HEX8(v0, 0x22); + TEST_ASSERT_EQUAL_HEX8(*p0, v1); + TEST_ASSERT_EQUAL_HEX8(*p0, *p1); + TEST_ASSERT_EQUAL_HEX8(*p0, 0x22); +} + +void testEqualHex8sWhenThereAreDifferencesOutside8Bits(void) +{ + TEST_ASSERT_EQUAL_HEX8(0x321,0x421); + TEST_ASSERT_EQUAL_HEX8(0xFF21,0x0021); +} + +void testEqualHex8sNegatives(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 0xDD; + v1 = 0xDD; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_HEX8(0xDD, 0xDD); + TEST_ASSERT_EQUAL_HEX8(v0, v1); + TEST_ASSERT_EQUAL_HEX8(0xDD, v1); + TEST_ASSERT_EQUAL_HEX8(v0, 0xDD); + TEST_ASSERT_EQUAL_HEX8(*p0, v1); + TEST_ASSERT_EQUAL_HEX8(*p0, *p1); + TEST_ASSERT_EQUAL_HEX8(*p0, 0xDD); +} + +void testEqualHex16s(void) +{ + UNITY_UINT16 v0, v1; + UNITY_UINT16 *p0, *p1; + + v0 = 0x9876; + v1 = 0x9876; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_HEX16(0x9876, 0x9876); + TEST_ASSERT_EQUAL_HEX16(v0, v1); + TEST_ASSERT_EQUAL_HEX16(0x9876, v1); + TEST_ASSERT_EQUAL_HEX16(v0, 0x9876); + TEST_ASSERT_EQUAL_HEX16(*p0, v1); + TEST_ASSERT_EQUAL_HEX16(*p0, *p1); + TEST_ASSERT_EQUAL_HEX16(*p0, 0x9876); +} + +void testEqualHex16sWhenThereAreDifferencesOutside16Bits(void) +{ + TEST_ASSERT_EQUAL_HEX16(0x54321,0x64321); + TEST_ASSERT_EQUAL_HEX16(0xFFFF4321,0x00004321); +} + +void testEqualHex32s(void) +{ + UNITY_UINT32 v0, v1; + UNITY_UINT32 *p0, *p1; + + v0 = 0x98765432ul; + v1 = 0x98765432ul; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_HEX32(0x98765432ul, 0x98765432ul); + TEST_ASSERT_EQUAL_HEX32(v0, v1); + TEST_ASSERT_EQUAL_HEX32(0x98765432ul, v1); + TEST_ASSERT_EQUAL_HEX32(v0, 0x98765432ul); + TEST_ASSERT_EQUAL_HEX32(*p0, v1); + TEST_ASSERT_EQUAL_HEX32(*p0, *p1); + TEST_ASSERT_EQUAL_HEX32(*p0, 0x98765432ul); +} + +void testEqualBits(void) +{ + UNITY_UINT32 v0 = 0xFF55AA00; + UNITY_UINT32 v1 = 0x55550000; + + TEST_ASSERT_BITS(v1, v0, 0x55550000); + TEST_ASSERT_BITS(v1, v0, 0xFF55CC00); + TEST_ASSERT_BITS(0xFFFFFFFF, v0, 0xFF55AA00); + TEST_ASSERT_BITS(0xFFFFFFFF, v0, v0); + TEST_ASSERT_BITS(0xF0F0F0F0, v0, 0xFC5DAE0F); + TEST_ASSERT_BITS_HIGH(v1, v0); + TEST_ASSERT_BITS_LOW(0x000055FF, v0); + TEST_ASSERT_BIT_HIGH(30, v0); + TEST_ASSERT_BIT_LOW(5, v0); +} + +void testNotEqualBitHigh(void) +{ + UNITY_UINT32 v0 = 0x7F55AA00; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_BIT_HIGH(31, v0); + VERIFY_FAILS_END +} + +void testNotEqualBitLow(void) +{ + UNITY_UINT32 v0 = 0xFF55AA00; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_BIT_LOW(30, v0); + VERIFY_FAILS_END +} + +void testNotEqualBitsHigh(void) +{ + UNITY_UINT32 v0 = 0xFF55AA00; + UNITY_UINT32 v1 = 0x55550000; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_BITS_HIGH(v0, v1); + VERIFY_FAILS_END + +} + +void testNotEqualBitsLow(void) +{ + UNITY_UINT32 v0 = 0xFF55AA00; + UNITY_UINT32 v1 = 0x55550000; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_BITS_LOW(v0, v1); + VERIFY_FAILS_END +} + + +void testEqualShorts(void) +{ + short v0, v1; + short *p0, *p1; + + v0 = 19467; + v1 = 19467; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT(1837, 1837); + TEST_ASSERT_EQUAL_INT(-2987, -2987); + TEST_ASSERT_EQUAL_INT(v0, v1); + TEST_ASSERT_EQUAL_INT(19467, v1); + TEST_ASSERT_EQUAL_INT(v0, 19467); + TEST_ASSERT_EQUAL_INT(*p0, v1); + TEST_ASSERT_EQUAL_INT(*p0, *p1); + TEST_ASSERT_EQUAL_INT(*p0, 19467); +} + +void testEqualUShorts(void) +{ + unsigned short v0, v1; + unsigned short *p0, *p1; + + v0 = 19467; + v1 = 19467; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_UINT(1837, 1837); + TEST_ASSERT_EQUAL_UINT(2987, 2987); + TEST_ASSERT_EQUAL_UINT(v0, v1); + TEST_ASSERT_EQUAL_UINT(19467, v1); + TEST_ASSERT_EQUAL_UINT(v0, 19467); + TEST_ASSERT_EQUAL_UINT(*p0, v1); + TEST_ASSERT_EQUAL_UINT(*p0, *p1); + TEST_ASSERT_EQUAL_UINT(*p0, 19467); +} + +void testEqualUInts(void) +{ + unsigned char v0, v1; + unsigned char *p0, *p1; + + v0 = 109; + v1 = 109; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_UINT(42, 42); + TEST_ASSERT_EQUAL_UINT(-116, -116); + TEST_ASSERT_EQUAL_UINT(v0, v1); + TEST_ASSERT_EQUAL_UINT(109, v1); + TEST_ASSERT_EQUAL_UINT(v0, 109); + TEST_ASSERT_EQUAL_UINT(*p0, v1); + TEST_ASSERT_EQUAL_UINT(*p0, *p1); + TEST_ASSERT_EQUAL_UINT(*p0, 109); +} + +void testEqualUChars(void) +{ + unsigned char v0, v1; + unsigned char *p0, *p1; + + v0 = 251; + v1 = 251; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT(42, 42); + TEST_ASSERT_EQUAL_INT(v0, v1); + TEST_ASSERT_EQUAL_INT(251, v1); + TEST_ASSERT_EQUAL_INT(v0, 251); + TEST_ASSERT_EQUAL_INT(*p0, v1); + TEST_ASSERT_EQUAL_INT(*p0, *p1); + TEST_ASSERT_EQUAL_INT(*p0, 251); +} + +void testEqualPointers(void) +{ + int v0, v1; + int *p0, *p1, *p2; + + v0 = 19467; + v1 = 18271; + p0 = &v0; + p1 = &v1; + p2 = &v1; + + TEST_ASSERT_EQUAL_PTR(p0, &v0); + TEST_ASSERT_EQUAL_PTR(&v1, p1); + TEST_ASSERT_EQUAL_PTR(p2, p1); + TEST_ASSERT_EQUAL_PTR(&v0, &v0); +} + +void testNotEqualPointers(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_PTR(0x12345678, 0x12345677); + VERIFY_FAILS_END +} + +void testIntsWithinDelta(void) +{ + TEST_ASSERT_INT_WITHIN(1, 5000, 5001); + TEST_ASSERT_INT_WITHIN(5, 5000, 4996); + TEST_ASSERT_INT_WITHIN(5, 5000, 5005); + TEST_ASSERT_INT_WITHIN(500, 50, -440); + + TEST_ASSERT_INT_WITHIN(2, -1, -1); + TEST_ASSERT_INT_WITHIN(5, 1, -1); + TEST_ASSERT_INT_WITHIN(5, -1, 1); +} + +void testIntsWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_INT_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); + TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); + TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); + TEST_ASSERT_INT_WITHIN_MESSAGE(500, 50, -440, "Custom Message."); + + TEST_ASSERT_INT_WITHIN_MESSAGE(2, -1, -1, "Custom Message."); + TEST_ASSERT_INT_WITHIN_MESSAGE(5, 1, -1, "Custom Message."); + TEST_ASSERT_INT_WITHIN_MESSAGE(5, -1, 1, "Custom Message."); +} + +void testIntsNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_WITHIN(5, 5000, 5006); + VERIFY_FAILS_END +} + +void testIntsNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 5006, "Custom Message."); + VERIFY_FAILS_END +} + +void testUIntsWithinDelta(void) +{ + TEST_ASSERT_UINT_WITHIN(1, 5000, 5001); + TEST_ASSERT_UINT_WITHIN(5, 5000, 4996); + TEST_ASSERT_UINT_WITHIN(5, 5000, 5005); +} + +void testUIntsWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_UINT_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); + TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); + TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); +} + +void testUIntsNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_WITHIN(1, 2147483647u, 2147483649u); + VERIFY_FAILS_END +} + +void testUIntsNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message."); + VERIFY_FAILS_END +} + +void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassSmallFirst(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_WITHIN(5, 1, -1); + VERIFY_FAILS_END +} + +void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassSmallFirstAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 1, -1, "Custom Message."); + VERIFY_FAILS_END +} + +void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassBigFirst(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_WITHIN(5, -1, 1); + VERIFY_FAILS_END +} + +void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassBigFirstAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT_WITHIN_MESSAGE(5, -1, 1, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX32sWithinDelta(void) +{ + TEST_ASSERT_HEX32_WITHIN(1, 5000, 5001); + TEST_ASSERT_HEX32_WITHIN(5, 5000, 4996); + TEST_ASSERT_HEX32_WITHIN(5, 5000, 5005); +} + +void testHEX32sWithinDeltaShouldIgnoreSign(void) +{ + TEST_ASSERT_HEX32_WITHIN(1, 0x7FFFFFFF, 0x80000000); +} + +void testHEX32sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_HEX32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); + TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); + TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); +} + +void testHEX32sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_WITHIN(1, 2147483647u, 2147483649u); + VERIFY_FAILS_END +} + +void testHEX32sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX32sNotWithinDeltaEvenThoughASignedIntWouldPass(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_WITHIN(5, 1, -1); + VERIFY_FAILS_END +} + +void testHEX32sNotWithinDeltaEvenThoughASignedIntWouldPassAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 1, -1, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX16sWithinDelta(void) +{ + TEST_ASSERT_HEX16_WITHIN(1, 5000, 5001); + TEST_ASSERT_HEX16_WITHIN(5, 5000, 4996); + TEST_ASSERT_HEX16_WITHIN(5, 5000, 5005); +} + +void testHEX16sWithinDeltaShouldIgnoreSign(void) +{ + TEST_ASSERT_HEX16_WITHIN(1, 0x7FFF, 0x8000); +} + +void testHEX16sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_HEX16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); + TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); + TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); +} + +void testHEX16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void) +{ + TEST_ASSERT_HEX16_WITHIN(5, 0x54321, 0x44321); +} + +void testHEX16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void) +{ + TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message."); +} + +void testHEX16sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_WITHIN(2, 65535, 0); + VERIFY_FAILS_END +} + +void testHEX16sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX16_WITHIN_MESSAGE(2, 65535, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testHEX8sWithinDelta(void) +{ + TEST_ASSERT_HEX8_WITHIN(1, 254, 255); + TEST_ASSERT_HEX8_WITHIN(5, 251, 255); + TEST_ASSERT_HEX8_WITHIN(5, 1, 4); +} + +void testHEX8sWithinDeltaShouldIgnoreSign(void) +{ + TEST_ASSERT_HEX8_WITHIN(1, 0x7F, 0x80); +} + +void testHEX8sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_HEX8_WITHIN_MESSAGE(1, 254, 255, "Custom Message."); + TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 251, 255, "Custom Message."); + TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 1, 4, "Custom Message."); +} + +void testHEX8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void) +{ + TEST_ASSERT_HEX8_WITHIN(5, 0x123, 0xF23); +} + +void testHEX8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void) +{ + TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message."); +} + +void testHEX8sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_WITHIN(2, 255, 0); + VERIFY_FAILS_END +} + +void testHEX8sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX8_WITHIN_MESSAGE(2, 255, 0, "Custom Message."); + VERIFY_FAILS_END +} + +/*-----------------*/ + +void testUINT32sWithinDelta(void) +{ + TEST_ASSERT_UINT32_WITHIN(1, 5000, 5001); + TEST_ASSERT_UINT32_WITHIN(5, 5000, 4996); + TEST_ASSERT_UINT32_WITHIN(5, 5000, 5005); +} + +void testUINT32sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_UINT32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); + TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); + TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); +} + +void testUINT32sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT32_WITHIN(1, 2147483647u, 2147483649u); + VERIFY_FAILS_END +} + +void testUINT32sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT32_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message."); + VERIFY_FAILS_END +} + +void testUINT32sNotWithinDeltaEvenThoughASignedIntWouldPass(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT32_WITHIN(5, 1, -1); + VERIFY_FAILS_END +} + +void testUINT32sNotWithinDeltaEvenThoughASignedIntWouldPassAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 1, -1, "Custom Message."); + VERIFY_FAILS_END +} + +void testUINT16sWithinDelta(void) +{ + TEST_ASSERT_UINT16_WITHIN(1, 5000, 5001); + TEST_ASSERT_UINT16_WITHIN(5, 5000, 4996); + TEST_ASSERT_UINT16_WITHIN(5, 5000, 5005); +} + +void testUINT16sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_UINT16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); + TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message."); + TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message."); +} + +void testUINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void) +{ + TEST_ASSERT_UINT16_WITHIN(5, 0x54321, 0x44321); +} + +void testUINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void) +{ + TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message."); +} + +void testUINT16sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_WITHIN(2, 65535, 0); + VERIFY_FAILS_END +} + +void testUINT16sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT16_WITHIN_MESSAGE(2, 65535, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testUINT8sWithinDelta(void) +{ + TEST_ASSERT_UINT8_WITHIN(1, 254, 255); + TEST_ASSERT_UINT8_WITHIN(5, 251, 255); + TEST_ASSERT_UINT8_WITHIN(5, 1, 4); +} + +void testUINT8sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_UINT8_WITHIN_MESSAGE(1, 254, 255, "Custom Message."); + TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 251, 255, "Custom Message."); + TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 1, 4, "Custom Message."); +} + +void testUINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void) +{ + TEST_ASSERT_UINT8_WITHIN(5, 0x123, 0xF23); +} + +void testUINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void) +{ + TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message."); +} + +void testUINT8sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_WITHIN(2, 255, 0); + VERIFY_FAILS_END +} + +void testUINT8sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT8_WITHIN_MESSAGE(2, 255, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testINT32sWithinDelta(void) +{ + TEST_ASSERT_INT32_WITHIN(1, 5000, 5001); + TEST_ASSERT_INT32_WITHIN(5, 1, -2); + TEST_ASSERT_INT32_WITHIN(5, -2, 1); +} + +void testINT32sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_INT32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); +} + +void testINT32sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT32_WITHIN(1, -3, 1); + VERIFY_FAILS_END +} + +void testINT32sNotWithinDeltaAndDifferenceOverflows(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT32_WITHIN(1, -1, 0x7FFFFFFF); + VERIFY_FAILS_END +} +void testINT32sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT32_WITHIN_MESSAGE(1, -2, 1, "Custom Message."); + VERIFY_FAILS_END +} + +void testINT16sWithinDelta(void) +{ + TEST_ASSERT_INT16_WITHIN(1, 5000, 5001); + TEST_ASSERT_INT16_WITHIN(5, 2, -2); + TEST_ASSERT_INT16_WITHIN(5, -2, 2); +} + +void testINT16sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_INT16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message."); +} + +void testINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void) +{ + TEST_ASSERT_INT16_WITHIN(5, 0x54321, 0x44321); +} + +void testINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void) +{ + TEST_ASSERT_INT16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message."); +} + +void testINT16sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_WITHIN(2, 4, -2); + VERIFY_FAILS_END +} + +void testINT16sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT16_WITHIN_MESSAGE(2, 3, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testINT8sWithinDelta(void) +{ + TEST_ASSERT_INT8_WITHIN(1, 127, 126); + TEST_ASSERT_INT8_WITHIN(5, -2, 2); + TEST_ASSERT_INT8_WITHIN(5, 2, -2); +} + +void testINT8sWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_INT8_WITHIN_MESSAGE(5, 1, 4, "Custom Message."); +} + +void testINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void) +{ + TEST_ASSERT_INT8_WITHIN(5, 0x123, 0xF23); +} + +void testINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void) +{ + TEST_ASSERT_INT8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message."); +} + +void testINT8sNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_WITHIN(2, -3, 0); + VERIFY_FAILS_END +} + +void testINT8sNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT8_WITHIN_MESSAGE(2, -4, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testCHARsWithinDelta(void) +{ + TEST_ASSERT_CHAR_WITHIN(1, 'M', 'L'); + TEST_ASSERT_CHAR_WITHIN(5, -2, 2); + TEST_ASSERT_CHAR_WITHIN(5, 2, -2); +} + +void testCHARsWithinDeltaAndCustomMessage(void) +{ + TEST_ASSERT_CHAR_WITHIN_MESSAGE(5, 1, 4, "Custom Message."); +} + +void testCHARsWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void) +{ + TEST_ASSERT_CHAR_WITHIN(5, 0x123, 0xF23); +} + +void testCHARsWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void) +{ + TEST_ASSERT_CHAR_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message."); +} + +void testCHARsNotWithinDelta(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_WITHIN(2, -3, 0); + VERIFY_FAILS_END +} + +void testCHARsNotWithinDeltaAndCustomMessage(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_CHAR_WITHIN_MESSAGE(2, -4, 0, "Custom Message."); + VERIFY_FAILS_END +} + +void testNotEqualINT(void) +{ + UNITY_INT v0, v1; + UNITY_INT *p0, *p1; + + v0 = 302; + v1 = 3334; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_INT(v0, v1); + TEST_ASSERT_NOT_EQUAL_INT(*p0, v1); + TEST_ASSERT_NOT_EQUAL_INT(v0, *p1); + TEST_ASSERT_NOT_EQUAL_INT(*p1, *p0); +} + +void testNotNotEqualINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_INT(302, 302); + VERIFY_FAILS_END +} + +void testNotEqualINT8(void) +{ + UNITY_INT8 v0, v1; + UNITY_INT8 *p0, *p1; + + v0 = -128; + v1 = 127; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_INT8(v0, v1); + TEST_ASSERT_NOT_EQUAL_INT8(*p0, v1); + TEST_ASSERT_NOT_EQUAL_INT8(v0, *p1); + TEST_ASSERT_NOT_EQUAL_INT8(*p1, *p0); +} + +void testNotNotEqualINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_INT8(-128, -128); + VERIFY_FAILS_END +} + +void testNotEqualCHAR(void) +{ + char v0, v1; + char *p0, *p1; + + v0 = -128; + v1 = 127; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_CHAR(v0, v1); + TEST_ASSERT_NOT_EQUAL_CHAR(*p0, v1); + TEST_ASSERT_NOT_EQUAL_CHAR(v0, *p1); + TEST_ASSERT_NOT_EQUAL_CHAR(*p1, *p0); +} + +void testNotNotEqualCHAR(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_CHAR(127, 127); + VERIFY_FAILS_END +} + +void testNotEqualINT16(void) +{ + UNITY_INT16 v0, v1; + UNITY_INT16 *p0, *p1; + + v0 = -32768; + v1 = 32767; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_INT16(v0, v1); + TEST_ASSERT_NOT_EQUAL_INT16(*p0, v1); + TEST_ASSERT_NOT_EQUAL_INT16(v0, *p1); + TEST_ASSERT_NOT_EQUAL_INT16(*p1, *p0); +} + +void testNotNotEqualINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_INT16(-32768, -32768); + VERIFY_FAILS_END +} + +void testNotEqualINT32(void) +{ + UNITY_INT32 v0, v1; + UNITY_INT32 *p0, *p1; + + v0 = -214783648; + v1 = 214783647; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_INT32(v0, v1); + TEST_ASSERT_NOT_EQUAL_INT32(*p0, v1); + TEST_ASSERT_NOT_EQUAL_INT32(v0, *p1); + TEST_ASSERT_NOT_EQUAL_INT32(*p1, *p0); +} + +void testNotNotEqualINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_INT32(-214783648, -214783648); + VERIFY_FAILS_END +} + +void testNotEqualUINT(void) +{ + UNITY_UINT v0, v1; + UNITY_UINT *p0, *p1; + + v0 = 0; + v1 = 1; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_UINT(v0, v1); + TEST_ASSERT_NOT_EQUAL_UINT(*p0, v1); + TEST_ASSERT_NOT_EQUAL_UINT(v0, *p1); + TEST_ASSERT_NOT_EQUAL_UINT(*p1, *p0); +} + +void testNotNotEqualUINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_UINT(1, 1); + VERIFY_FAILS_END +} + +void testNotEqualUINT8(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 0; + v1 = 255; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_UINT8(v0, v1); + TEST_ASSERT_NOT_EQUAL_UINT8(*p0, v1); + TEST_ASSERT_NOT_EQUAL_UINT8(v0, *p1); + TEST_ASSERT_NOT_EQUAL_UINT8(*p1, *p0); +} + +void testNotNotEqualUINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_UINT8(255, 255); + VERIFY_FAILS_END +} + +void testNotEqualUINT16(void) +{ + UNITY_UINT16 v0, v1; + UNITY_UINT16 *p0, *p1; + + v0 = 0; + v1 = 65535; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_UINT16(v0, v1); + TEST_ASSERT_NOT_EQUAL_UINT16(*p0, v1); + TEST_ASSERT_NOT_EQUAL_UINT16(v0, *p1); + TEST_ASSERT_NOT_EQUAL_UINT16(*p1, *p0); +} + +void testNotNotEqualUINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_UINT16(65535, 65535); + VERIFY_FAILS_END +} + +void testNotEqualUINT32(void) +{ + UNITY_UINT32 v0, v1; + UNITY_UINT32 *p0, *p1; + + v0 = 0u; + v1 = 4294967295u; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_UINT32(v0, v1); + TEST_ASSERT_NOT_EQUAL_UINT32(*p0, v1); + TEST_ASSERT_NOT_EQUAL_UINT32(v0, *p1); + TEST_ASSERT_NOT_EQUAL_UINT32(*p1, *p0); +} + +void testNotNotEqualUINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_UINT32(4294967295u, 4294967295u); + VERIFY_FAILS_END +} + +void testNotEqualHEX8(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 0x00; + v1 = 0xFF; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_HEX8(v0, v1); + TEST_ASSERT_NOT_EQUAL_HEX8(*p0, v1); + TEST_ASSERT_NOT_EQUAL_HEX8(v0, *p1); + TEST_ASSERT_NOT_EQUAL_HEX8(*p1, *p0); +} + +void testNotNotEqualHEX8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_HEX8(0xFF, 0xFF); + VERIFY_FAILS_END +} + +void testNotEqualHEX16(void) +{ + UNITY_UINT16 v0, v1; + UNITY_UINT16 *p0, *p1; + + v0 = 0x0000; + v1 = 0xFFFF; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_HEX16(v0, v1); + TEST_ASSERT_NOT_EQUAL_HEX16(*p0, v1); + TEST_ASSERT_NOT_EQUAL_HEX16(v0, *p1); + TEST_ASSERT_NOT_EQUAL_HEX16(*p1, *p0); +} + +void testNotNotEqualHEX16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_HEX16(0xFFFF, 0xFFFF); + VERIFY_FAILS_END +} + +void testNotEqualHEX32(void) +{ + UNITY_UINT32 v0, v1; + UNITY_UINT32 *p0, *p1; + + v0 = 0x00000000; + v1 = 0xFFFFFFFF; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_NOT_EQUAL_HEX32(v0, v1); + TEST_ASSERT_NOT_EQUAL_HEX32(*p0, v1); + TEST_ASSERT_NOT_EQUAL_HEX32(v0, *p1); + TEST_ASSERT_NOT_EQUAL_HEX32(*p1, *p0); +} + +void testNotNotEqualHEX32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_NOT_EQUAL_HEX32(0xFFFFFFFF, 0xFFFFFFFF); + VERIFY_FAILS_END +} + +/*-----------------*/ + +void testGreaterThan(void) +{ + UNITY_INT v0, v1; + UNITY_INT *p0, *p1; + + v0 = 0; + v1 = 1; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN(v0, v1); + TEST_ASSERT_GREATER_THAN(*p0, v1); + TEST_ASSERT_GREATER_THAN(v0, *p1); + TEST_ASSERT_GREATER_THAN(*p0, *p1); +} + +void testNotGreaterThan(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN(0, -1); + VERIFY_FAILS_END +} + +void testGreaterThanINT(void) +{ + UNITY_INT v0, v1; + UNITY_INT *p0, *p1; + + v0 = 302; + v1 = 3334; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_INT(v0, v1); + TEST_ASSERT_GREATER_THAN_INT(*p0, v1); + TEST_ASSERT_GREATER_THAN_INT(v0, *p1); + TEST_ASSERT_GREATER_THAN_INT(*p0, *p1); +} + +void testNotGreaterThanINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_INT(3334, 302); + VERIFY_FAILS_END +} + +void testGreaterThanINT8(void) +{ + UNITY_INT8 v0, v1; + UNITY_INT8 *p0, *p1; + + v0 = -128; + v1 = 127; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_INT8(v0, v1); + TEST_ASSERT_GREATER_THAN_INT8(*p0, v1); + TEST_ASSERT_GREATER_THAN_INT8(v0, *p1); + TEST_ASSERT_GREATER_THAN_INT8(*p0, *p1); +} + +void testNotGreaterThanINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_INT8(127, -128); + VERIFY_FAILS_END +} + +void testGreaterThanCHAR(void) +{ + char v0, v1; + char *p0, *p1; + + v0 = -128; + v1 = 127; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_CHAR(v0, v1); + TEST_ASSERT_GREATER_THAN_CHAR(*p0, v1); + TEST_ASSERT_GREATER_THAN_CHAR(v0, *p1); + TEST_ASSERT_GREATER_THAN_CHAR(*p0, *p1); +} + +void testNotGreaterThanCHAR(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_CHAR(127, -128); + VERIFY_FAILS_END +} + +void testGreaterThanINT16(void) +{ + UNITY_INT16 v0, v1; + UNITY_INT16 *p0, *p1; + + v0 = -32768; + v1 = 32767; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_INT16(v0, v1); + TEST_ASSERT_GREATER_THAN_INT16(*p0, v1); + TEST_ASSERT_GREATER_THAN_INT16(v0, *p1); + TEST_ASSERT_GREATER_THAN_INT16(*p0, *p1); +} + +void testNotGreaterThanINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_INT16(32768, -32768); + VERIFY_FAILS_END +} + +void testGreaterThanINT32(void) +{ + UNITY_INT32 v0, v1; + UNITY_INT32 *p0, *p1; + + v0 = -214783648; + v1 = 214783647; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_INT32(v0, v1); + TEST_ASSERT_GREATER_THAN_INT32(*p0, v1); + TEST_ASSERT_GREATER_THAN_INT32(v0, *p1); + TEST_ASSERT_GREATER_THAN_INT32(*p0, *p1); +} + +void testNotGreaterThanINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_INT32(214783647, -214783648); + VERIFY_FAILS_END +} + +void testGreaterThanUINT(void) +{ + UNITY_UINT v0, v1; + UNITY_UINT *p0, *p1; + + v0 = 0; + v1 = 1; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_UINT(v0, v1); + TEST_ASSERT_GREATER_THAN_UINT(*p0, v1); + TEST_ASSERT_GREATER_THAN_UINT(v0, *p1); + TEST_ASSERT_GREATER_THAN_UINT(*p0, *p1); +} + +void testNotGreaterThanUINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_UINT(1, 0); + VERIFY_FAILS_END +} + +void testGreaterThanUINT8(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 0; + v1 = 255; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_UINT8(v0, v1); + TEST_ASSERT_GREATER_THAN_UINT8(*p0, v1); + TEST_ASSERT_GREATER_THAN_UINT8(v0, *p1); + TEST_ASSERT_GREATER_THAN_UINT8(*p0, *p1); +} + +void testNotGreaterThanUINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_UINT8(255, 0); + VERIFY_FAILS_END +} + +void testGreaterThanUINT16(void) +{ + UNITY_UINT16 v0, v1; + UNITY_UINT16 *p0, *p1; + + v0 = 0; + v1 = 65535; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_UINT16(v0, v1); + TEST_ASSERT_GREATER_THAN_UINT16(*p0, v1); + TEST_ASSERT_GREATER_THAN_UINT16(v0, *p1); + TEST_ASSERT_GREATER_THAN_UINT16(*p0, *p1); +} + +void testNotGreaterThanUINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_UINT16(65535, 0); + VERIFY_FAILS_END +} + +void testGreaterThanUINT32(void) +{ + UNITY_UINT32 v0, v1; + UNITY_UINT32 *p0, *p1; + + v0 = 0u; + v1 = 4294967295u; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_UINT32(v0, v1); + TEST_ASSERT_GREATER_THAN_UINT32(*p0, v1); + TEST_ASSERT_GREATER_THAN_UINT32(v0, *p1); + TEST_ASSERT_GREATER_THAN_UINT32(*p0, *p1); +} + +void testNotGreaterThanUINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_UINT32(4294967295u, 0); + VERIFY_FAILS_END +} + +void testGreaterThanHEX8(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 0x00; + v1 = 0xFF; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_HEX8(v0, v1); + TEST_ASSERT_GREATER_THAN_HEX8(*p0, v1); + TEST_ASSERT_GREATER_THAN_HEX8(v0, *p1); + TEST_ASSERT_GREATER_THAN_HEX8(*p0, *p1); +} + +void testNotGreaterThanHEX8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_HEX8(0xFF, 0x00); + VERIFY_FAILS_END +} + +void testGreaterThanHEX16(void) +{ + UNITY_UINT16 v0, v1; + UNITY_UINT16 *p0, *p1; + + v0 = 0x0000; + v1 = 0xFFFF; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_HEX16(v0, v1); + TEST_ASSERT_GREATER_THAN_HEX16(*p0, v1); + TEST_ASSERT_GREATER_THAN_HEX16(v0, *p1); + TEST_ASSERT_GREATER_THAN_HEX16(*p0, *p1); +} + +void testNotGreaterThanHEX16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_HEX16(0xFFFF, 0x00); + VERIFY_FAILS_END +} + +void testGreaterThanHEX32(void) +{ + UNITY_UINT32 v0, v1; + UNITY_UINT32 *p0, *p1; + + v0 = 0x00000000; + v1 = 0xFFFFFFFF; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_GREATER_THAN_HEX32(v0, v1); + TEST_ASSERT_GREATER_THAN_HEX32(*p0, v1); + TEST_ASSERT_GREATER_THAN_HEX32(v0, *p1); + TEST_ASSERT_GREATER_THAN_HEX32(*p0, *p1); +} + +void testNotGreaterThanHEX32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_THAN_HEX32(0xFFFFFFFF, 0x00); + VERIFY_FAILS_END +} + +void testGreaterOrEqual(void) +{ + UNITY_INT v0, v1, v2; + UNITY_INT *p0, *p1, *p2; + + v0 = 0; + v1 = 1; + v2 = 0; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL(*p0, *p2); +} + +void testNotGreaterOrEqual(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL(0, -1); + VERIFY_FAILS_END +} + +void testGreaterOrEqualINT(void) +{ + UNITY_INT v0, v1, v2; + UNITY_INT *p0, *p1, *p2; + + v0 = 302; + v1 = 3334; + v2 = 302; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_INT(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_INT(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_INT(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_INT(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_INT(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_INT(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_INT(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_INT(*p0, *p2); +} + +void testNotGreaterOrEqualINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_INT(3334, 302); + VERIFY_FAILS_END +} + +void testGreaterOrEqualINT8(void) +{ + UNITY_INT8 v0, v1, v2; + UNITY_INT8 *p0, *p1, *p2; + + v0 = -128; + v1 = 127; + v2 = -128; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_INT8(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_INT8(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_INT8(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_INT8(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_INT8(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_INT8(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_INT8(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_INT8(*p0, *p2); +} + +void testNotGreaterOrEqualINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_INT8(127, -128); + VERIFY_FAILS_END +} + +void testGreaterOrEqualCHAR(void) +{ + char v0, v1, v2; + char *p0, *p1, *p2; + + v0 = -128; + v1 = 127; + v2 = -128; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(*p0, *p2); +} + +void testNotGreaterOrEqualCHAR(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_CHAR(127, -128); + VERIFY_FAILS_END +} + +void testGreaterOrEqualINT16(void) +{ + UNITY_INT16 v0, v1, v2; + UNITY_INT16 *p0, *p1, *p2; + + v0 = -32768; + v1 = 32767; + v2 = -32768; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_INT16(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_INT16(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_INT16(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_INT16(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_INT16(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_INT16(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_INT16(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_INT16(*p0, *p2); +} + +void testNotGreaterOrEqualINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_INT16(32767, -32768); + VERIFY_FAILS_END +} + +void testGreaterOrEqualINT32(void) +{ + UNITY_INT32 v0, v1, v2; + UNITY_INT32 *p0, *p1, *p2; + + v0 = -214783648; + v1 = 214783647; + v2 = -214783648; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_INT32(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_INT32(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_INT32(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_INT32(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_INT32(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_INT32(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_INT32(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_INT32(*p0, *p2); +} + +void testNotGreaterOrEqualINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_INT32(214783647, -214783648); + VERIFY_FAILS_END +} + +void testGreaterOrEqualUINT(void) +{ + UNITY_UINT v0, v1, v2; + UNITY_UINT *p0, *p1, *p2; + + v0 = 0; + v1 = 1; + v2 = 0; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_UINT(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT(*p0, *p2); +} + +void testNotGreaterOrEqualUINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_UINT(1, 0); + VERIFY_FAILS_END +} + +void testGreaterOrEqualUINT8(void) +{ + UNITY_UINT8 v0, v1, v2; + UNITY_UINT8 *p0, *p1, *p2; + + v0 = 0; + v1 = 255; + v2 = 0; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(*p0, *p2); +} + +void testNotGreaterOrEqualUINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_UINT8(255, 0); + VERIFY_FAILS_END +} + +void testGreaterOrEqualUINT16(void) +{ + UNITY_UINT16 v0, v1, v2; + UNITY_UINT16 *p0, *p1, *p2; + + v0 = 0; + v1 = 65535; + v2 = 0; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(*p0, *p2); +} + +void testNotGreaterOrEqualUINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_UINT16(65535, 0); + VERIFY_FAILS_END +} + +void testGreaterOrEqualUINT32(void) +{ + UNITY_UINT32 v0, v1, v2; + UNITY_UINT32 *p0, *p1, *p2; + + v0 = 0; + v1 = 4294967295u; + v2 = 0; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(*p0, *p2); +} + +void testNotGreaterOrEqualUINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_UINT32(4294967295u, 0); + VERIFY_FAILS_END +} + +void testGreaterOrEqualHEX8(void) +{ + UNITY_UINT8 v0, v1, v2; + UNITY_UINT8 *p0, *p1, *p2; + + v0 = 0x00; + v1 = 0xFF; + v2 = 0x00; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(*p0, *p2); +} + +void testNotGreaterOrEqualHEX8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_HEX8(0xFF, 0x00); + VERIFY_FAILS_END +} + +void testGreaterOrEqualHEX16(void) +{ + UNITY_UINT16 v0, v1, v2; + UNITY_UINT16 *p0, *p1, *p2; + + v0 = 0x0000; + v1 = 0xFFFF; + v2 = 0x0000; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(*p0, *p2); +} + +void testNotGreaterOrEqualHEX16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_HEX16(0xFFFF, 0x00); + VERIFY_FAILS_END +} + +void testGreaterOrEqualHEX32(void) +{ + UNITY_UINT32 v0, v1, v2; + UNITY_UINT32 *p0, *p1, *p2; + + v0 = 0x00000000; + v1 = 0xFFFFFFFF; + v2 = 0x00000000; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(v0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(*p0, v1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(v0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(*p0, *p1); + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(v0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(*p0, v2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(v0, *p2); + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(*p0, *p2); +} + +void testNotGreaterOrEqualHEX32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_GREATER_OR_EQUAL_HEX32(0xFFFFFFFF, 0x00); + VERIFY_FAILS_END +} + +/*-----------------*/ + +void testLessThan(void) +{ + UNITY_INT v0, v1; + UNITY_INT *p0, *p1; + + v0 = 0; + v1 = -1; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN(v0, v1); + TEST_ASSERT_LESS_THAN(*p0, v1); + TEST_ASSERT_LESS_THAN(v0, *p1); + TEST_ASSERT_LESS_THAN(*p0, *p1); +} + +void testNotLessThan(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN(0, 1); + VERIFY_FAILS_END +} + +void testLessThanINT(void) +{ + UNITY_INT v0, v1; + UNITY_INT *p0, *p1; + + v0 = 3334; + v1 = 302; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_INT(v0, v1); + TEST_ASSERT_LESS_THAN_INT(*p0, v1); + TEST_ASSERT_LESS_THAN_INT(v0, *p1); + TEST_ASSERT_LESS_THAN_INT(*p0, *p1); +} + +void testNotLessThanINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_INT(302, 3334); + VERIFY_FAILS_END +} + +void testLessThanINT8(void) +{ + UNITY_INT8 v0, v1; + UNITY_INT8 *p0, *p1; + + v0 = 127; + v1 = -128; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_INT8(v0, v1); + TEST_ASSERT_LESS_THAN_INT8(*p0, v1); + TEST_ASSERT_LESS_THAN_INT8(v0, *p1); + TEST_ASSERT_LESS_THAN_INT8(*p0, *p1); +} + +void testNotLessThanINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_INT8(-128, 127); + VERIFY_FAILS_END +} + +void testLessThanCHAR(void) +{ + char v0, v1; + char *p0, *p1; + + v0 = 127; + v1 = -128; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_CHAR(v0, v1); + TEST_ASSERT_LESS_THAN_CHAR(*p0, v1); + TEST_ASSERT_LESS_THAN_CHAR(v0, *p1); + TEST_ASSERT_LESS_THAN_CHAR(*p0, *p1); +} + +void testNotLessThanCHAR(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_CHAR(-128, 127); + VERIFY_FAILS_END +} + +void testLessThanINT16(void) +{ + UNITY_INT16 v0, v1; + UNITY_INT16 *p0, *p1; + + v0 = 32767; + v1 = -32768; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_INT16(v0, v1); + TEST_ASSERT_LESS_THAN_INT16(*p0, v1); + TEST_ASSERT_LESS_THAN_INT16(v0, *p1); + TEST_ASSERT_LESS_THAN_INT16(*p0, *p1); +} + +void testNotLessThanINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_INT16(-32768, 32767); + VERIFY_FAILS_END +} + +void testLessThanINT32(void) +{ + UNITY_INT32 v0, v1; + UNITY_INT32 *p0, *p1; + + v0 = 214783647; + v1 = -214783648; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_INT32(v0, v1); + TEST_ASSERT_LESS_THAN_INT32(*p0, v1); + TEST_ASSERT_LESS_THAN_INT32(v0, *p1); + TEST_ASSERT_LESS_THAN_INT32(*p0, *p1); +} + +void testNotLessThanINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_INT32(-214783648, 214783647); + VERIFY_FAILS_END +} + +void testLessThanUINT(void) +{ + UNITY_UINT v0, v1; + UNITY_UINT *p0, *p1; + + v0 = 1; + v1 = 0; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_UINT(v0, v1); + TEST_ASSERT_LESS_THAN_UINT(*p0, v1); + TEST_ASSERT_LESS_THAN_UINT(v0, *p1); + TEST_ASSERT_LESS_THAN_UINT(*p0, *p1); +} + +void testNotLessThanUINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_UINT(0, 1); + VERIFY_FAILS_END +} + +void testLessThanUINT8(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 255; + v1 = 0; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_UINT8(v0, v1); + TEST_ASSERT_LESS_THAN_UINT8(*p0, v1); + TEST_ASSERT_LESS_THAN_UINT8(v0, *p1); + TEST_ASSERT_LESS_THAN_UINT8(*p0, *p1); +} + +void testNotLessThanUINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_UINT8(0, 255); + VERIFY_FAILS_END +} + +void testLessThanUINT16(void) +{ + UNITY_UINT16 v0, v1; + UNITY_UINT16 *p0, *p1; + + v0 = 65535; + v1 = 0; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_UINT16(v0, v1); + TEST_ASSERT_LESS_THAN_UINT16(*p0, v1); + TEST_ASSERT_LESS_THAN_UINT16(v0, *p1); + TEST_ASSERT_LESS_THAN_UINT16(*p0, *p1); +} + +void testNotLessThanUINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_UINT16(0, 65535); + VERIFY_FAILS_END +} + +void testLessThanUINT32(void) +{ + UNITY_UINT32 v0, v1; + UNITY_UINT32 *p0, *p1; + + v0 = 4294967295u; + v1 = 0; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_UINT32(v0, v1); + TEST_ASSERT_LESS_THAN_UINT32(*p0, v1); + TEST_ASSERT_LESS_THAN_UINT32(v0, *p1); + TEST_ASSERT_LESS_THAN_UINT32(*p0, *p1); +} + +void testNotLessThanUINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_UINT32(0, 4294967295u); + VERIFY_FAILS_END +} + +void testLessThanHEX8(void) +{ + UNITY_UINT8 v0, v1; + UNITY_UINT8 *p0, *p1; + + v0 = 0xFF; + v1 = 0x00; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_HEX8(v0, v1); + TEST_ASSERT_LESS_THAN_HEX8(*p0, v1); + TEST_ASSERT_LESS_THAN_HEX8(v0, *p1); + TEST_ASSERT_LESS_THAN_HEX8(*p0, *p1); +} + +void testNotLessThanHEX8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_HEX8(0x00, 0xFF); + VERIFY_FAILS_END +} + +void testLessThanHEX16(void) +{ + UNITY_UINT16 v0, v1; + UNITY_UINT16 *p0, *p1; + + v0 = 0xFFFF; + v1 = 0x0000; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_HEX16(v0, v1); + TEST_ASSERT_LESS_THAN_HEX16(*p0, v1); + TEST_ASSERT_LESS_THAN_HEX16(v0, *p1); + TEST_ASSERT_LESS_THAN_HEX16(*p0, *p1); +} + +void testNotLessThanHEX16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_HEX16(0x0000, 0xFFFF); + VERIFY_FAILS_END +} + +void testLessThanHEX32(void) +{ + UNITY_UINT32 v0, v1; + UNITY_UINT32 *p0, *p1; + + v0 = 0xFFFFFFFF; + v1 = 0x00000000; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_LESS_THAN_HEX32(v0, v1); + TEST_ASSERT_LESS_THAN_HEX32(*p0, v1); + TEST_ASSERT_LESS_THAN_HEX32(v0, *p1); + TEST_ASSERT_LESS_THAN_HEX32(*p0, *p1); +} + +void testNotLessThanHEX32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_THAN_HEX32(0x00000000, 0xFFFFFFFF); + VERIFY_FAILS_END +} + +void testLessOrEqual(void) +{ + UNITY_INT v0, v1, v2; + UNITY_INT *p0, *p1, *p2; + + v0 = 0; + v1 = -1; + v2 = 0; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL(*p0, *p2); +} + +void testNotLessOrEqual(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL(0, 1); + VERIFY_FAILS_END +} + +void testLessOrEqualINT(void) +{ + UNITY_INT v0, v1, v2; + UNITY_INT *p0, *p1, *p2; + + v0 = 3334; + v1 = 302; + v2 = 3334; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_INT(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_INT(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_INT(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_INT(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_INT(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_INT(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_INT(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_INT(*p0, *p2); +} + +void testNotLessOrEqualINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_INT(302, 3334); + VERIFY_FAILS_END +} + +void testLessOrEqualINT8(void) +{ + UNITY_INT8 v0, v1, v2; + UNITY_INT8 *p0, *p1, *p2; + + v0 = 127; + v1 = -128; + v2 = 127; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_INT8(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_INT8(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_INT8(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_INT8(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_INT8(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_INT8(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_INT8(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_INT8(*p0, *p2); +} + +void testNotLessOrEqualINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_INT8(-128, 127); + VERIFY_FAILS_END +} + +void testLessOrEqualCHAR(void) +{ + char v0, v1, v2; + char *p0, *p1, *p2; + + v0 = 127; + v1 = -128; + v2 = 127; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_CHAR(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_CHAR(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_CHAR(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_CHAR(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_CHAR(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_CHAR(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_CHAR(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_CHAR(*p0, *p2); +} + +void testNotLessOrEqualCHAR(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_CHAR(-128, 127); + VERIFY_FAILS_END +} + +void testLessOrEqualINT16(void) +{ + UNITY_INT16 v0, v1, v2; + UNITY_INT16 *p0, *p1, *p2; + + v0 = 32767; + v1 = -32768; + v2 = 32767; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_INT16(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_INT16(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_INT16(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_INT16(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_INT16(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_INT16(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_INT16(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_INT16(*p0, *p2); +} + +void testNotLessOrEqualINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_INT16(-32768, 32767); + VERIFY_FAILS_END +} + +void testLessOrEqualINT32(void) +{ + UNITY_INT32 v0, v1, v2; + UNITY_INT32 *p0, *p1, *p2; + + v0 = 214783647; + v1 = -214783648; + v2 = 214783647; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_INT32(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_INT32(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_INT32(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_INT32(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_INT32(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_INT32(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_INT32(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_INT32(*p0, *p2); +} + +void testNotLessOrEqualINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_INT32(-214783648, 214783647); + VERIFY_FAILS_END +} + +void testLessOrEqualUINT(void) +{ + UNITY_UINT v0, v1, v2; + UNITY_UINT *p0, *p1, *p2; + + v0 = 1; + v1 = 0; + v2 = 1; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_UINT(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_UINT(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_UINT(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_UINT(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_UINT(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_UINT(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_UINT(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_UINT(*p0, *p2); +} + +void testNotLessOrEqualUINT(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_UINT(0, 1); + VERIFY_FAILS_END +} + +void testLessOrEqualUINT8(void) +{ + UNITY_UINT8 v0, v1, v2; + UNITY_UINT8 *p0, *p1, *p2; + + v0 = 255; + v1 = 0; + v2 = 255; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_UINT8(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_UINT8(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_UINT8(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_UINT8(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_UINT8(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_UINT8(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_UINT8(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_UINT8(*p0, *p2); +} + +void testNotLessOrEqualUINT8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_UINT8(0, 255); + VERIFY_FAILS_END +} + +void testLessOrEqualUINT16(void) +{ + UNITY_UINT16 v0, v1, v2; + UNITY_UINT16 *p0, *p1, *p2; + + v0 = 65535; + v1 = 0; + v2 = 65535; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_UINT16(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_UINT16(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_UINT16(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_UINT16(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_UINT16(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_UINT16(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_UINT16(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_UINT16(*p0, *p2); +} + +void testNotLessOrEqualUINT16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_UINT16(0, 65535); + VERIFY_FAILS_END +} + +void testLessOrEqualUINT32(void) +{ + UNITY_UINT32 v0, v1, v2; + UNITY_UINT32 *p0, *p1, *p2; + + v0 = 4294967295u; + v1 = 0; + v2 = 4294967295u; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_UINT32(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_UINT32(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_UINT32(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_UINT32(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_UINT32(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_UINT32(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_UINT32(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_UINT32(*p0, *p2); +} + +void testNotLessOrEqualUINT32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_UINT32(0, 4294967295u); + VERIFY_FAILS_END +} + +void testLessOrEqualHEX8(void) +{ + UNITY_UINT8 v0, v1, v2; + UNITY_UINT8 *p0, *p1, *p2; + + v0 = 0xFF; + v1 = 0x00; + v2 = 0xFF; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_HEX8(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_HEX8(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_HEX8(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_HEX8(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_HEX8(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_HEX8(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_HEX8(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_HEX8(*p0, *p2); +} + +void testNotLessOrEqualHEX8(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_HEX8(0x00, 0xFF); + VERIFY_FAILS_END +} + +void testLessOrEqualHEX16(void) +{ + UNITY_UINT16 v0, v1, v2; + UNITY_UINT16 *p0, *p1, *p2; + + v0 = 0xFFFF; + v1 = 0x0000; + v2 = 0xFFFF; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_HEX16(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_HEX16(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_HEX16(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_HEX16(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_HEX16(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_HEX16(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_HEX16(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_HEX16(*p0, *p2); +} + +void testNotLessOrEqualHEX16(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_HEX16(0x0000, 0xFFFF); + VERIFY_FAILS_END +} + +void testLessOrEqualHEX32(void) +{ + UNITY_UINT32 v0, v1, v2; + UNITY_UINT32 *p0, *p1, *p2; + + v0 = 0xFFFFFFFF; + v1 = 0x00000000; + v2 = 0xFFFFFFFF; + p0 = &v0; + p1 = &v1; + p2 = &v2; + + TEST_ASSERT_LESS_OR_EQUAL_HEX32(v0, v1); + TEST_ASSERT_LESS_OR_EQUAL_HEX32(*p0, v1); + TEST_ASSERT_LESS_OR_EQUAL_HEX32(v0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_HEX32(*p0, *p1); + TEST_ASSERT_LESS_OR_EQUAL_HEX32(v0, v2); + TEST_ASSERT_LESS_OR_EQUAL_HEX32(*p0, v2); + TEST_ASSERT_LESS_OR_EQUAL_HEX32(v0, *p2); + TEST_ASSERT_LESS_OR_EQUAL_HEX32(*p0, *p2); +} + +void testNotLessOrEqualHEX32(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_LESS_OR_EQUAL_HEX32(0x00000000, 0xFFFFFFFF); + VERIFY_FAILS_END +} + +void testHexPrintsUpToMaxNumberOfNibbles(void) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + startPutcharSpy(); + UnityPrintNumberHex(0xBEE, 21); + endPutcharSpy(); +#ifdef UNITY_SUPPORT_64 + TEST_ASSERT_EQUAL_INT(16, strlen(getBufferPutcharSpy())); +#else + TEST_ASSERT_EQUAL_INT( 8, strlen(getBufferPutcharSpy())); +#endif +#endif +} + +void testPrintNumbers32(void) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE_MESSAGE("Compile with '-D UNITY_OUTPUT_CHAR=putcharSpy' to enable print testing"); +#else + TEST_ASSERT_EQUAL_PRINT_NUMBERS("0", 0); + TEST_ASSERT_EQUAL_PRINT_NUMBERS("1", 1); + TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", -1); + TEST_ASSERT_EQUAL_PRINT_NUMBERS("2000000000", 2000000000); + TEST_ASSERT_EQUAL_PRINT_NUMBERS("-2147483648", (UNITY_INT32)0x80000000); + TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", (UNITY_INT32)0xFFFFFFFF); +#endif +} + +void testPrintNumbersUnsigned32(void) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("0", 0); + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("1", 1); + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("1500000000", 1500000000); + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("2147483648", (UNITY_UINT32)0x80000000); + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("4294967295", (UNITY_UINT32)0xFFFFFFFF); +#endif +} diff --git a/src/subprojects/unity/test/tests/test_unity_integers_64.c b/src/subprojects/unity/test/tests/test_unity_integers_64.c new file mode 100644 index 00000000..6fb0957f --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_integers_64.c @@ -0,0 +1,783 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#define TEST_INSTANCES +#include "self_assessment_utils.h" + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + { + /* These will be skipped internally if already failed/ignored */ + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); + } + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +void testInt64ArrayWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualSmallDelta[] = {12345001, -12344996, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + TEST_ASSERT_INT64_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_INT64_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +#endif +} + +void testInt64ArrayWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualSmallDelta[] = {12345001, -12344996, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +#endif +} + +void testInt64ArrayNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayNotWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaPointless(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaPointlessAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaExpectedNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaExpectedNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 actualBigDelta[] = {12345101, -12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaActualNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaActualNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testInt64ArrayWithinDeltaSamePointer(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, expected, 3); +#endif +} + +void testInt64ArrayWithinDeltaSamePointerAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 expected[] = {12345000, -12344995, 12345005}; + + TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +#endif +} + +void testUInt64ArrayWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualSmallDelta[] = {12345001, 12344996, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN(1, expected, actualSmallDelta, 3); + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, actualBigDelta, 3); +#endif +} + +void testUInt64ArrayWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualSmallDelta[] = {12345001, 12344996, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(1, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 3, "Custom Message."); +#endif +} + +void testUInt64ArrayNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(1, expected, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayNotWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(1, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaPointless(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, actualBigDelta, 0); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaPointlessAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaExpectedNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaExpectedNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 actualBigDelta[] = {12345101, 12344896, 12345055}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaActualNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, NULL, 3); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaActualNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testUInt64ArrayWithinDeltaSamePointer(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN(110, expected, expected, 3); +#endif +} + +void testUInt64ArrayWithinDeltaSamePointerAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {12345000, 12344995, 12345005}; + + TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(110, expected, expected, 3, "Custom Message."); +#endif +} + +void testHEX64ArrayWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualSmallDelta[] = {0xABCD123500000000, 0xABCD112100000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x100000000, expected, actualSmallDelta, 3); + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, expected, actualBigDelta, 3); +#endif +} + +void testHEX64ArrayWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualSmallDelta[] = {0xABCD123500000000, 0xABCD112100000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x100000000, expected, actualSmallDelta, 3, "Custom Message."); + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, expected, actualBigDelta, 3, "Custom Message."); +#endif +} + +void testHEX64ArrayNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x100000000, expected, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayNotWithinDeltaAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x100000000, expected, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaPointless(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, expected, actualBigDelta, 0); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaPointlessAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, expected, actualBigDelta, 0, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaExpectedNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, NULL, actualBigDelta, 3); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaExpectedNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 actualBigDelta[] = {0xABCD126700000000, 0xABCD118800000000, 0xABCD12AC00000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, NULL, actualBigDelta, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaActualNull(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, expected, NULL, 3); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaActualNullAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, expected, NULL, 3, "Custom Message."); + VERIFY_FAILS_END +#endif +} + +void testHEX64ArrayWithinDeltaSamePointer(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN(0x6E00000000, expected, expected, 3); +#endif +} + +void testHEX64ArrayWithinDeltaSamePointerAndMessage(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 expected[] = {0xABCD123400000000, 0xABCD112200000000, 0xABCD127700000000}; + + TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(0x6E00000000, expected, expected, 3, "Custom Message."); +#endif +} + +void testEqualHex64s(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 v0, v1; + UNITY_UINT64 *p0, *p1; + + v0 = 0x9876543201234567; + v1 = 0x9876543201234567; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_HEX64(0x9876543201234567, 0x9876543201234567); + TEST_ASSERT_EQUAL_HEX64(v0, v1); + TEST_ASSERT_EQUAL_HEX64(0x9876543201234567, v1); + TEST_ASSERT_EQUAL_HEX64(v0, 0x9876543201234567); + TEST_ASSERT_EQUAL_HEX64(*p0, v1); + TEST_ASSERT_EQUAL_HEX64(*p0, *p1); + TEST_ASSERT_EQUAL_HEX64(*p0, 0x9876543201234567); +#endif +} + +void testEqualUint64s(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 v0, v1; + UNITY_UINT64 *p0, *p1; + + v0 = 0x9876543201234567; + v1 = 0x9876543201234567; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_UINT64(0x9876543201234567, 0x9876543201234567); + TEST_ASSERT_EQUAL_UINT64(v0, v1); + TEST_ASSERT_EQUAL_UINT64(0x9876543201234567, v1); + TEST_ASSERT_EQUAL_UINT64(v0, 0x9876543201234567); + TEST_ASSERT_EQUAL_UINT64(*p0, v1); + TEST_ASSERT_EQUAL_UINT64(*p0, *p1); + TEST_ASSERT_EQUAL_UINT64(*p0, 0x9876543201234567); +#endif +} + +void testEqualInt64s(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 v0, v1; + UNITY_INT64 *p0, *p1; + + v0 = (UNITY_INT64)0x9876543201234567; + v1 = (UNITY_INT64)0x9876543201234567; + p0 = &v0; + p1 = &v1; + + TEST_ASSERT_EQUAL_INT64(0x9876543201234567, 0x9876543201234567); + TEST_ASSERT_EQUAL_INT64(v0, v1); + TEST_ASSERT_EQUAL_INT64(0x9876543201234567, v1); + TEST_ASSERT_EQUAL_INT64(v0, 0x9876543201234567); + TEST_ASSERT_EQUAL_INT64(*p0, v1); + TEST_ASSERT_EQUAL_INT64(*p0, *p1); + TEST_ASSERT_EQUAL_INT64(*p0, 0x9876543201234567); +#endif +} + + +void testNotEqualHex64s(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 v0, v1; + + v0 = 9000000000; + v1 = 9100000000; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX64(v0, v1); + VERIFY_FAILS_END +#endif +} + +void testNotEqualUint64s(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_UINT64 v0, v1; + + v0 = 9000000000; + v1 = 9100000000; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_UINT64(v0, v1); + VERIFY_FAILS_END +#endif +} + +void testNotEqualInt64s(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 v0, v1; + + v0 = -9000000000; + v1 = 9100000000; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_INT64(v0, v1); + VERIFY_FAILS_END +#endif +} + +void testNotEqualHex64sIfSigned(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + UNITY_INT64 v0, v1; + + v0 = -9000000000; + v1 = 9000000000; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_HEX64(v0, v1); + VERIFY_FAILS_END +#endif +} + +void testHEX64sWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE); + TEST_ASSERT_HEX64_WITHIN(5, 5000, 4996); + TEST_ASSERT_HEX64_WITHIN(5, 5000, 5005); +#endif +} + +void testHEX32sWithinDeltaShouldIgnoreSign(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x8000000000000000); +#endif +} + +void testHEX64sNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC); + VERIFY_FAILS_END +#endif +} + +void testHEX64sNotWithinDeltaEvenThoughASignedIntWouldPass(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_HEX64_WITHIN(5, 1, -1); + VERIFY_FAILS_END +#endif +} + +void testUINT64sWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + TEST_ASSERT_UINT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE); + TEST_ASSERT_UINT64_WITHIN(5, 5000, 4996); + TEST_ASSERT_UINT64_WITHIN(5, 5000, 5005); +#endif +} + +void testUINT64sNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC); + VERIFY_FAILS_END +#endif +} + +void testUINT64sNotWithinDeltaEvenThoughASignedIntWouldPass(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_UINT64_WITHIN(5, 1, -1); + VERIFY_FAILS_END +#endif +} + +void testINT64sWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + TEST_ASSERT_INT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE); + TEST_ASSERT_INT64_WITHIN(5, 5000, 4996); + TEST_ASSERT_INT64_WITHIN(5, 5000, 5005); +#endif +} + +void testINT64sNotWithinDelta(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC); + VERIFY_FAILS_END +#endif +} + +void testINT64sNotWithinDeltaAndDifferenceOverflows(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + EXPECT_ABORT_BEGIN + TEST_ASSERT_INT64_WITHIN(1, 0x8000000000000000, 0x7FFFFFFFFFFFFFFF); + VERIFY_FAILS_END +#endif +} + +void testPrintNumbersInt64(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + #ifndef USING_OUTPUT_SPY + TEST_IGNORE(); + #else + TEST_ASSERT_EQUAL_PRINT_NUMBERS("0", 0); + TEST_ASSERT_EQUAL_PRINT_NUMBERS("10000000000", 10000000000); + TEST_ASSERT_EQUAL_PRINT_NUMBERS("-9223372036854775808", (UNITY_INT)0x8000000000000000); + TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", (UNITY_INT)0xFFFFFFFFFFFFFFFF); + #endif +#endif +} + +void testPrintNumbersUInt64(void) +{ +#ifndef UNITY_SUPPORT_64 + TEST_IGNORE(); +#else + #ifndef USING_OUTPUT_SPY + TEST_IGNORE(); + #else + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("0", 0); + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("70000000000", 70000000000); + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("9223372036854775808", (UNITY_UINT)0x8000000000000000); + TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("18446744073709551615", (UNITY_UINT)0xFFFFFFFFFFFFFFFF); + #endif +#endif +} diff --git a/src/subprojects/unity/test/tests/test_unity_memory.c b/src/subprojects/unity/test/tests/test_unity_memory.c new file mode 100644 index 00000000..d4897de4 --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_memory.c @@ -0,0 +1,82 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#define TEST_INSTANCES +#include "self_assessment_utils.h" + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + { + /* These will be skipped internally if already failed/ignored */ + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); + } + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +void testEqualMemory(void) +{ + const char *testString = "whatever"; + + TEST_ASSERT_EQUAL_MEMORY(testString, testString, 8); + TEST_ASSERT_EQUAL_MEMORY("whatever", "whatever", 8); + TEST_ASSERT_EQUAL_MEMORY("whatever", testString, 8); + TEST_ASSERT_EQUAL_MEMORY(testString, "whatever", 8); + TEST_ASSERT_EQUAL_MEMORY(testString, "whatever", 2); + TEST_ASSERT_EQUAL_MEMORY(NULL, NULL, 1); +} + +void testNotEqualMemory1(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_MEMORY("foo", "bar", 3); + VERIFY_FAILS_END +} + +void testNotEqualMemory2(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_MEMORY("fool", "food", 4); + VERIFY_FAILS_END +} + +void testNotEqualMemory3(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_MEMORY(NULL, "food", 4); + VERIFY_FAILS_END +} + +void testNotEqualMemory4(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_MEMORY("fool", NULL, 4); + VERIFY_FAILS_END +} + +void testNotEqualMemoryLengthZero(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_MEMORY(NULL, NULL, 0); + VERIFY_FAILS_END +} diff --git a/src/subprojects/unity/test/tests/test_unity_parameterized.c b/src/subprojects/unity/test/tests/test_unity_parameterized.c new file mode 100644 index 00000000..b9550986 --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_parameterized.c @@ -0,0 +1,309 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include +#include +#include "unity.h" +#include "types_for_test.h" + +/* Include Passthroughs for Linking Tests */ +void putcharSpy(int c) { (void)putchar(c);} +void flushSpy(void) {} + +#define EXPECT_ABORT_BEGIN \ + if (TEST_PROTECT()) \ + { + +#define VERIFY_FAILS_END \ + } \ + Unity.CurrentTestFailed = (Unity.CurrentTestFailed != 0) ? 0 : 1; \ + if (Unity.CurrentTestFailed == 1) { \ + SetToOneMeanWeAlreadyCheckedThisGuy = 1; \ + UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \ + UNITY_OUTPUT_CHAR(':'); \ + UnityPrint(Unity.CurrentTestName); \ + UnityPrint(":FAIL: [[[[ Test Should Have Failed But Did Not ]]]]"); \ + UNITY_OUTPUT_CHAR('\n'); \ + } + +#define VERIFY_IGNORES_END \ + } \ + Unity.CurrentTestFailed = (Unity.CurrentTestIgnored != 0) ? 0 : 1; \ + Unity.CurrentTestIgnored = 0; \ + if (Unity.CurrentTestFailed == 1) { \ + SetToOneMeanWeAlreadyCheckedThisGuy = 1; \ + UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber); \ + UNITY_OUTPUT_CHAR(':'); \ + UnityPrint(Unity.CurrentTestName); \ + UnityPrint(":FAIL: [[[[ Test Should Have Ignored But Did Not ]]]]"); \ + UNITY_OUTPUT_CHAR('\n'); \ + } + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; +static unsigned NextExpectedStringIndex; +static unsigned NextExpectedCharIndex; +static unsigned NextExpectedSpaceIndex; + +void suiteSetUp(void) +{ + NextExpectedStringIndex = 0; + NextExpectedCharIndex = 0; + NextExpectedSpaceIndex = 0; +} + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + if (SetToOneToFailInTearDown == 1) + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +TEST_CASE(0) +TEST_CASE(44) +TEST_CASE((90)+9) +void test_TheseShouldAllPass(int Num) +{ + TEST_ASSERT_TRUE(Num < 100); +} + +TEST_CASE(3) +TEST_CASE(77) +TEST_CASE( (99) + 1 - (1)) +void test_TheseShouldAllFail(int Num) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_TRUE(Num > 100); + VERIFY_FAILS_END +} + +TEST_CASE(1) +TEST_CASE(44) +TEST_CASE(99) +TEST_CASE(98) +void test_TheseAreEveryOther(int Num) +{ + if (Num & 1) + { + EXPECT_ABORT_BEGIN + TEST_ASSERT_TRUE(Num > 100); + VERIFY_FAILS_END + } + else + { + TEST_ASSERT_TRUE(Num < 100); + } +} + +void test_NormalPassesStillWork(void) +{ + TEST_ASSERT_TRUE(1); +} + +void test_NormalFailsStillWork(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_TRUE(0); + VERIFY_FAILS_END +} + +TEST_CASE(0, "abc") +TEST_CASE(1, "{") +TEST_CASE(2, "}") +TEST_CASE(3, ";") +TEST_CASE(4, "\"quoted\"") +void test_StringsArePreserved(unsigned index, const char * str) +{ + static const char * const expected[] = + { + "abc", + "{", + "}", + ";", + "\"quoted\"" + }; + + /* Ensure that no test cases are skipped by tracking the next expected index */ + TEST_ASSERT_EQUAL_UINT32(NextExpectedStringIndex, index); + TEST_ASSERT_LESS_THAN(sizeof(expected) / sizeof(expected[0]), index); + TEST_ASSERT_EQUAL_STRING(expected[index], str); + + NextExpectedStringIndex++; +} + +TEST_CASE(0, 'x') +TEST_CASE(1, '{') +TEST_CASE(2, '}') +TEST_CASE(3, ';') +TEST_CASE(4, '\'') +TEST_CASE(5, '"') +void test_CharsArePreserved(unsigned index, char c) +{ + static const char expected[] = + { + 'x', + '{', + '}', + ';', + '\'', + '"' + }; + + /* Ensure that no test cases are skipped by tracking the next expected index */ + TEST_ASSERT_EQUAL_UINT32(NextExpectedCharIndex, index); + TEST_ASSERT_LESS_THAN(sizeof(expected) / sizeof(expected[0]), index); + TEST_ASSERT_EQUAL(expected[index], c); + + NextExpectedCharIndex++; +} + +TEST_RANGE([0, 10, 2]) +void test_SingleRange(unsigned value) +{ + TEST_ASSERT_EQUAL(0, value % 2); + TEST_ASSERT_LESS_OR_EQUAL(10, value); +} + +TEST_RANGE([1, 2, 1], [2, 1, -1]) +void test_TwoRanges(unsigned first, unsigned second) +{ + TEST_ASSERT_LESS_OR_EQUAL(4, first * second); +} + +TEST_RANGE(<0, 10, 2>) +void test_SingleExclusiveRange(unsigned value) +{ + TEST_ASSERT_EQUAL(0, value % 2); + TEST_ASSERT_LESS_THAN(10, value); +} + +TEST_RANGE([2, 4, 1], <1, 2, 1>) +void test_BothInclusiveAndExclusiveRange(unsigned first, unsigned second) +{ + TEST_ASSERT_LESS_THAN(first, second); +} + +TEST_CASE(0, + + 1) +TEST_CASE(1, + + 2 + + ) +TEST_RANGE([2, + 5 , + 1], [6, 6, 1]) +TEST_CASE( + + 6 , 7) +TEST_MATRIX([7, + 8 , + + 9, 10], + [ + 11] + + ) +void test_SpaceInTestCase(unsigned index, unsigned bigger) +{ + TEST_ASSERT_EQUAL_UINT32(NextExpectedSpaceIndex, index); + TEST_ASSERT_LESS_THAN(bigger, index); + + NextExpectedSpaceIndex++; +} + +TEST_MATRIX([1, 5, (2*2)+1, 4]) +void test_SingleMatix(unsigned value) +{ + TEST_ASSERT_LESS_OR_EQUAL(10, value); +} + +TEST_MATRIX([2, 5l, 4u+3, 4ul], [-2, 3]) +void test_TwoMatrices(unsigned first, signed second) +{ + static unsigned idx = 0; + static const unsigned expected[] = + { + // -2 3 + -4, 6, // 2 + -10, 15, // 5 + -14, 21, // 7 + -8, 12, // 4 + }; + TEST_ASSERT_EQUAL_INT(expected[idx++], first * second); +} + +TEST_MATRIX(["String1", "String,2", "Stri" "ng3", "String[4]", "String\"5\""], [-5, 12.5f]) +void test_StringsAndNumbersMatrices(const char* str, float number) +{ + static unsigned idx = 0; + static const char* expected[] = + { + "String1_-05.00", + "String1_+12.50", + "String,2_-05.00", + "String,2_+12.50", + "String3_-05.00", + "String3_+12.50", + "String[4]_-05.00", + "String[4]_+12.50", + "String\"5\"_-05.00", + "String\"5\"_+12.50", + }; + char buf[200] = {0}; + snprintf(buf, sizeof(buf), "%s_%+06.2f", str, number); + TEST_ASSERT_EQUAL_STRING(expected[idx++], buf); +} + +TEST_MATRIX( + [ENUM_A, ENUM_4, ENUM_C], + [test_arr[0], 7.8f, test_arr[2]], + ['a', 'f', '[', ']', '\'', '"'], +) +void test_EnumCharAndArrayMatrices(test_enum_t e, float n, char c) +{ + static unsigned enum_idx = 0; + static const test_enum_t exp_enum[3] = { + ENUM_A, ENUM_4, ENUM_C, + }; + + static unsigned float_idx = 0; + float exp_float[3] = {0}; + exp_float[0] = test_arr[0]; + exp_float[1] = 7.8f; + exp_float[2] = test_arr[2]; + + static unsigned char_idx = 0; + static const test_enum_t exp_char[] = { + 'a', 'f', '[', ']', '\'', '"' + }; + + TEST_ASSERT_EQUAL_INT(exp_enum[enum_idx], e); + TEST_ASSERT_EQUAL_FLOAT(exp_float[float_idx], n); + TEST_ASSERT_EQUAL_CHAR(exp_char[char_idx], c); + + char_idx = (char_idx + 1) % 6; + if (char_idx == 0.0f) + { + float_idx = (float_idx + 1) % 3; + if (float_idx == 0.0f) + { + enum_idx = (enum_idx + 1) % 3; + } + } +} diff --git a/src/subprojects/unity/test/tests/test_unity_parameterizedDemo.c b/src/subprojects/unity/test/tests/test_unity_parameterizedDemo.c new file mode 100644 index 00000000..6de6e686 --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_parameterizedDemo.c @@ -0,0 +1,28 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" + +/* Support for Meta Test Rig */ +#ifndef TEST_CASE +#define TEST_CASE(...) +#endif +#ifndef TEST_RANGE +#define TEST_RANGE(...) +#endif +#ifndef TEST_MATRIX +#define TEST_MATRIX(...) +#endif + +TEST_CASE(1, 2, 5) +TEST_CASE(10, 7, 20) +TEST_RANGE([3, 4, 1], [10, 5, -2], <30, 31, 1>) +TEST_MATRIX([3, 4, 7], [10, 8, 2, 1],[30u, 20.0f]) +void test_demoParamFunction(int a, int b, int c) +{ + TEST_ASSERT_GREATER_THAN_INT(a + b, c); +} diff --git a/src/subprojects/unity/test/tests/test_unity_strings.c b/src/subprojects/unity/test/tests/test_unity_strings.c new file mode 100644 index 00000000..6a421135 --- /dev/null +++ b/src/subprojects/unity/test/tests/test_unity_strings.c @@ -0,0 +1,330 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#define TEST_INSTANCES +#include "self_assessment_utils.h" + +static int SetToOneToFailInTearDown; +static int SetToOneMeanWeAlreadyCheckedThisGuy; + +void setUp(void) +{ + SetToOneToFailInTearDown = 0; + SetToOneMeanWeAlreadyCheckedThisGuy = 0; +} + +void tearDown(void) +{ + endPutcharSpy(); /* Stop suppressing test output */ + if (SetToOneToFailInTearDown == 1) + { + /* These will be skipped internally if already failed/ignored */ + TEST_FAIL_MESSAGE("<= Failed in tearDown"); + TEST_IGNORE_MESSAGE("<= Ignored in tearDown"); + } + if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0)) + { + UnityPrint(": [[[[ Test Should Have Passed But Did Not ]]]]"); + UNITY_OUTPUT_CHAR('\n'); + } +} + +void testEqualStrings(void) +{ + const char *testString = "foo"; + + TEST_ASSERT_EQUAL_STRING(testString, testString); + TEST_ASSERT_EQUAL_STRING_MESSAGE("foo", "foo", "foo isn't foo"); + TEST_ASSERT_EQUAL_STRING("foo", testString); + TEST_ASSERT_EQUAL_STRING(testString, "foo"); + TEST_ASSERT_EQUAL_STRING("", ""); +} + +void testEqualStringsLen(void) +{ + const char *testString = "foobar"; + TEST_ASSERT_EQUAL_STRING_LEN(testString, testString, strlen(testString)); + TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE("foobar", "foobaz", 5, "fooba isn't fooba"); + TEST_ASSERT_EQUAL_STRING_LEN("foo", testString, 3); + TEST_ASSERT_EQUAL_STRING_LEN(testString, "foo", 3); + TEST_ASSERT_EQUAL_STRING_LEN("", "", 3); +} + +void testEqualStringsWithCarriageReturnsAndLineFeeds(void) +{ + const char *testString = "foo\r\nbar"; + + TEST_ASSERT_EQUAL_STRING(testString, testString); + TEST_ASSERT_EQUAL_STRING("foo\r\nbar", "foo\r\nbar"); + TEST_ASSERT_EQUAL_STRING("foo\r\nbar", testString); + TEST_ASSERT_EQUAL_STRING(testString, "foo\r\nbar"); + TEST_ASSERT_EQUAL_STRING("", ""); +} + +void testNotEqualString1(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING("foo", "bar"); + VERIFY_FAILS_END +} + +void testNotEqualStringLen1(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_LEN("foobar", "foobaz", 6); + VERIFY_FAILS_END +} + +void testNotEqualString2(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING("foo", ""); + VERIFY_FAILS_END +} + +void testNotEqualStringLen2(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_LEN("foo", "", 3); + VERIFY_FAILS_END +} + +void testNotEqualString3(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING("", "bar"); + VERIFY_FAILS_END +} + +void testNotEqualStringLen3(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_LEN("", "bar", 3); + VERIFY_FAILS_END +} + +void testNotEqualString4(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING("bar\r", "bar\n"); + VERIFY_FAILS_END +} + +void testNotEqualStringLen4(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_LEN("ba\r\x16", "ba\r\n", 4); + VERIFY_FAILS_END +} + +void testNotEqualString5(void) +{ + const char str1[] = { 0x41, 0x42, 0x03, 0x00 }; + const char str2[] = { 0x41, 0x42, 0x04, 0x00 }; + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING(str1, str2); + VERIFY_FAILS_END +} + +void testNotEqualString_ExpectedStringIsNull(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING(NULL, "bar"); + VERIFY_FAILS_END +} + +void testNotEqualStringLen_ExpectedStringIsNull(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_LEN(NULL, "bar", 1); + VERIFY_FAILS_END +} + +void testNotEqualString_ActualStringIsNull(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING("foo", NULL); + VERIFY_FAILS_END +} + +void testNotEqualStringLen_ActualStringIsNull(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_LEN("foo", NULL, 1); + VERIFY_FAILS_END +} + +void testNotEqualString_ExpectedStringIsLonger(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING("foo2", "foo"); + VERIFY_FAILS_END +} + +void testNotEqualString_ActualStringIsLonger(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING("foo", "foo2"); + VERIFY_FAILS_END +} + +void testEqualStringArrays(void) +{ + const char *testStrings[] = { "foo", "boo", "woo", "moo" }; + const char *expStrings[] = { "foo", "boo", "woo", "zoo" }; + + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, expStrings, 3); + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 3); + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 2); + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 1); +} + +void testNotEqualStringArray1(void) +{ + const char *testStrings[] = { "foo", "boo", "woo", "moo" }; + const char *expStrings[] = { "foo", "boo", "woo", "zoo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringArray2(void) +{ + const char *testStrings[] = { "zoo", "boo", "woo", "moo" }; + const char *expStrings[] = { "foo", "boo", "woo", "moo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringArray3(void) +{ + const char *testStrings[] = { "foo", "boo", "woo", NULL }; + const char *expStrings[] = { "foo", "boo", "woo", "zoo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringArray4(void) +{ + const char *testStrings[] = { "foo", "boo", "woo", "moo" }; + const char *expStrings[] = { "foo", NULL, "woo", "moo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringArray5(void) +{ + const char **testStrings = NULL; + const char *expStrings[] = { "foo", "boo", "woo", "zoo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringArray6(void) +{ + const char *testStrings[] = { "foo", "boo", "woo", "zoo" }; + const char **expStrings = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); + VERIFY_FAILS_END +} + +void testEqualStringArrayIfBothNulls(void) +{ + const char **testStrings = NULL; + const char **expStrings = NULL; + + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4); +} + +void testNotEqualStringArrayLengthZero(void) +{ + const char *testStrings[] = {NULL}; + const char **expStrings = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 0); + VERIFY_FAILS_END +} + +void testEqualStringEachEqual(void) +{ + const char *testStrings1[] = { "foo", "foo", "foo", "foo" }; + const char *testStrings2[] = { "boo", "boo", "boo", "zoo" }; + const char *testStrings3[] = { "", "", "", "" }; + + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings1, 4); + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings1, 1); + TEST_ASSERT_EACH_EQUAL_STRING("boo", testStrings2, 3); + TEST_ASSERT_EACH_EQUAL_STRING("", testStrings3, 4); +} + +void testNotEqualStringEachEqual1(void) +{ + const char *testStrings[] = { "foo", "foo", "foo", "moo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringEachEqual2(void) +{ + const char *testStrings[] = { "boo", "foo", "foo", "foo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringEachEqual3(void) +{ + const char *testStrings[] = { "foo", "foo", "foo", NULL }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringEachEqual4(void) +{ + const char *testStrings[] = { "foo", "foo", "woo", "foo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringEachEqual5(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", NULL, 1); + VERIFY_FAILS_END +} + +void testCstringsEscapeSequence(void) +{ +#ifndef USING_OUTPUT_SPY + TEST_IGNORE(); +#else + startPutcharSpy(); + UnityPrint("\x16\x10"); + endPutcharSpy(); + TEST_ASSERT_EQUAL_STRING("\\x16\\x10", getBufferPutcharSpy()); +#endif +} diff --git a/src/subprojects/unity/test/tests/types_for_test.h b/src/subprojects/unity/test/tests/types_for_test.h new file mode 100644 index 00000000..66828b95 --- /dev/null +++ b/src/subprojects/unity/test/tests/types_for_test.h @@ -0,0 +1,21 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#pragma once + +typedef enum { + ENUM_A, + ENUM_2, + ENUM_C, + ENUM_4, +} test_enum_t; + +static const float test_arr[] = { + 1.2f, + 2.3f, + 3.4f, +}; diff --git a/src/subprojects/unity/unity/unity.h b/src/subprojects/unity/unity/unity.h new file mode 100644 index 00000000..9e2a97b7 --- /dev/null +++ b/src/subprojects/unity/unity/unity.h @@ -0,0 +1,698 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 6 +#define UNITY_VERSION_BUILD 1 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/*------------------------------------------------------- + * Build Directives + *------------------------------------------------------- + + * These macros do nothing, but they are useful for additional build context. + * Tools (like Ceedling) can scan for these directives and make use of them for + * per-test-executable #include search paths and linking. */ + +/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ +#define TEST_SOURCE_FILE(a) + +/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ +#define TEST_INCLUDE_PATH(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/subprojects/unity/unity/unity_internals.h b/src/subprojects/unity/unity/unity_internals.h new file mode 100644 index 00000000..562f5b6d --- /dev/null +++ b/src/subprojects/unity/unity/unity_internals.h @@ -0,0 +1,1183 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else + #define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +/* UNITY_NORETURN is only required if we have setjmp.h. */ +#ifndef UNITY_EXCLUDE_SETJMP_H + #ifndef UNITY_NORETURN + #if defined(__cplusplus) + #if __cplusplus >= 201103L + #define UNITY_NORETURN [[ noreturn ]] + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L + /* _Noreturn keyword is used from C11 but deprecated in C23. */ + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #if defined(__GNUC__) + /* The header collides with __attribute(noreturn)__ from GCC. */ + #define UNITY_NORETURN _Noreturn + #else + #include + #define UNITY_NORETURN noreturn + #endif + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L + /* Since C23, the keyword _Noreturn has been replaced by the attribute noreturn, based on: */ + /* https://en.cppreference.com/w/c/language/attributes/noreturn */ + #define UNITY_NORETURN [[ noreturn ]] + #endif + #endif + #ifndef UNITY_NORETURN + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) + #endif +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isnan macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_NAN +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define UNITY_IS_NAN(n) ((n != n) ? 1 : 0) +#else +#define UNITY_IS_NAN(n) isnan(n) +#endif +#endif + +/* isinf macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_INF +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define UNITY_IS_INF(n) (UNITY_IS_NAN((n) - (n)) && !UNITY_IS_NAN(n)) +#else +#define UNITY_IS_INF(n) isinf(n) +#endif +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() (void)0 + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) || defined(__APPLE__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x0, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifdef UNITY_TEST_PROTECT +#define TEST_PROTECT() UNITY_TEST_PROTECT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#else +#define TEST_PROTECT() 1 +#endif +#endif + +#ifdef UNITY_TEST_ABORT +#define TEST_ABORT() UNITY_TEST_ABORT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_ABORT() return +#endif +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX) + #define TEST_MATRIX(...) + #endif + #endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((line), (message)); } } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/src/subprojects/unity/unityConfig.cmake b/src/subprojects/unity/unityConfig.cmake new file mode 100644 index 00000000..55410ccc --- /dev/null +++ b/src/subprojects/unity/unityConfig.cmake @@ -0,0 +1 @@ +include(${CMAKE_CURRENT_LIST_DIR}/unityTargets.cmake) \ No newline at end of file diff --git a/src/tools/go_build b/src/tools/go_build index 652ae94d..15959160 100755 --- a/src/tools/go_build +++ b/src/tools/go_build @@ -85,6 +85,11 @@ _dfile=$(realpath "$2") fix_input_envs fix_dependencies +if [ -z "$TMPDIR" ]; then + TMPDIR=/tmp + export TMPDIR +fi + if [ -z "$HOME" -o ! -w "$HOME" ]; then HOME=$TMPDIR export HOME diff --git a/src/tools/xce-build.sh b/src/tools/xce-build.sh index e2058ebd..fc77e3c3 100755 --- a/src/tools/xce-build.sh +++ b/src/tools/xce-build.sh @@ -4,16 +4,48 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SRC_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" -# Self-wrap into the hermetic nix dev shell. meson/ninja/capnp/Go live only -# there; a bare invocation outside it fails opaquely ("meson: command not -# found") well past the point a caller can tell why. Re-exec once under -# `nix develop` -- the same wrapper the /xce-build skill already documents -# running by hand -- so every caller (the skill, a bare `bash xce-build.sh`, -# CI, a human at a terminal) gets it automatically instead of relying on -# remembering it. `nix develop` sets IN_NIX_SHELL, so a nested invocation -# (e.g. already inside the shell) is a no-op past this check. -if [ -z "${IN_NIX_SHELL:-}" ]; then - exec nix develop "$SRC_DIR" --command "$0" "$@" +# Dependency preflight (de-nix build path, see DEPS.md): the build now runs +# directly on system packages + meson wrap subprojects -- no `nix develop` +# self-wrap anymore. Fail early with actionable names instead of an opaque +# "meson: command not found" (or a pkg-config resolution error) halfway +# through a configure step. The wrap-fetched libraries (librtti, c-capnproto, +# tinylog, struct2json, unity, packcc) are NOT checked here -- meson fetches +# and builds them itself; only host toolchain + apt-provided libs are. +missing_tools=() +for t in meson ninja pkg-config go python3 capnp gcc; do + if ! command -v "$t" >/dev/null 2>&1; then + missing_tools+=("$t") + fi +done +if [ ${#missing_tools[@]} -gt 0 ]; then + echo "ERROR: missing build tools: ${missing_tools[*]}" >&2 + echo "Install them per DEPS.md (build toolchain table), then retry." >&2 + exit 1 +fi + +missing_pkgs=() +while IFS= read -r line; do + [ -z "$line" ] && continue + if ! pkg-config --exists "$line" 2>/dev/null; then + missing_pkgs+=("$line") + fi +done <<'EOF' +libuv +openssl +libedit +sqlite3 +hwloc +libcgroup +libtirpc +libcyaml +yaml-0.1 +zlib +libsystemd +EOF +if [ ${#missing_pkgs[@]} -gt 0 ]; then + echo "ERROR: missing system libraries (pkg-config could not resolve): ${missing_pkgs[*]}" >&2 + echo "Install the matching dev packages per DEPS.md (C library table), then retry." >&2 + exit 1 fi # --incremental (bug-1565 escape hatch): opt-in, NOT the default. Every diff --git a/src/tools/xce-package.sh b/src/tools/xce-package.sh new file mode 100755 index 00000000..7c9c8004 --- /dev/null +++ b/src/tools/xce-package.sh @@ -0,0 +1,232 @@ +#!/usr/bin/env bash +# xce-package.sh -- production tarball packager (de-nix distribution path). +# +# Takes a release-profile build tree (src/tools/xce-build.sh release output) +# and assembles a self-contained tarball: daemons + CLI + bundled non-glibc +# shared libraries ($ORIGIN RPATH) + systemd unit samples + configs schema. +# +# The bundle rule mirrors DEPS.md "运行期 bundle 规则": every library a +# product binary links whose path is OUTSIDE the base system directories +# gets copied into lib/; glibc-family libs (libc/libm/libpthread/libdl/ +# librt/libsystemd) are never bundled -- the target host always has them. +# +# Usage: src/tools/xce-package.sh [build_dir] [output_dir] +# build_dir defaults to src/build.release (the release profile dir); +# output_dir defaults to dist/. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +SRC_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +REPO_ROOT="$(cd "$SRC_DIR/.." && pwd)" + +BUILD_DIR="${1:-$SRC_DIR/build.release}" +OUT_DIR="${2:-$SRC_DIR/dist}" + +if [ ! -x "$BUILD_DIR/controller/xce_controller" ]; then + echo "ERROR: $BUILD_DIR does not look like a built tree (no controller/xce_controller)." >&2 + echo "Build it first: src/tools/xce-build.sh all release" >&2 + exit 1 +fi + +VERSION="$("$BUILD_DIR/controller/xce_controller" --version 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+[^ ]*' || echo "0.0.0")" +STAGING="$OUT_DIR/staging-xce-$VERSION" +PKG_NAME="xce-$VERSION-linux-x86_64" + +echo "=== Packaging $PKG_NAME from $BUILD_DIR ===" +rm -rf "$STAGING" +mkdir -p "$STAGING"/{bin,lib,share/xce,share/docs} + +# --- binaries (meson install layout mirrors what nix build produced) --- +install -m 755 "$BUILD_DIR"/controller/xce_controller "$STAGING/bin/" +install -m 755 "$BUILD_DIR"/worker/xcecd "$STAGING/bin/" +install -m 755 "$BUILD_DIR"/worker/xcecd_worker "$STAGING/bin/" +install -m 755 "$BUILD_DIR"/worker/xrun "$STAGING/bin/" +install -m 755 "$BUILD_DIR"/scheduler/xce_scheduler "$STAGING/bin/" +install -m 755 "$BUILD_DIR"/frontend/apiserver/xce_apiserver "$STAGING/bin/" +install -m 755 "$BUILD_DIR"/frontend/xcecli/xcecli "$STAGING/bin/" +# xceadmin venv wrapper + tree (produced by the xceadmin meson target) +if [ -d "$BUILD_DIR/xceadmin/.venv" ]; then + cp -r "$BUILD_DIR/xceadmin/.venv" "$STAGING/share/xce/xceadmin-venv" + # ../share: bin/ and share/ are siblings both in staging (and later in + # the install prefix), so one level up from bin/ lands at the root. + ln -sf ../share/xce/xceadmin-venv/bin/xceadmin "$STAGING/bin/xceadmin" +fi +# static worker fallback for hosts without systemd --include cgroup support +[ -f "$BUILD_DIR"/worker/xcecd_virtual ] && install -m 755 "$BUILD_DIR"/worker/xcecd_virtual "$STAGING/bin/" + +# --- bundled shared libraries --- +# Every DT_NEEDED whose resolved path falls outside the base system dirs is +# a wrap-subproject or non-baseline artifact -> copy + rewrite RPATH. +# +# Collect from the BUILD-TREE binaries, not the staged copies: meson links +# product binaries with a build-tree RPATH ($ORIGIN/../subprojects/), +# which still resolves there. Once copied into staging that path dangles, +# and ldd prints " => not found" -- the very lines the naive +# `/=> \//` ldd filter drops, so the loop would silently bundle nothing. +# Reading the ORIGINAL binary paths keeps ldd resolution intact; the +# staged copies get a fresh $ORIGIN RPATH below. +BASE_LIB_RE='^/(lib|usr/lib|lib64|usr/lib64)/' +declare -A BUNDLED +stage_bins=( + "$BUILD_DIR/controller/xce_controller" + "$BUILD_DIR/worker/xcecd" + "$BUILD_DIR/worker/xcecd_worker" + "$BUILD_DIR/worker/xrun" + "$BUILD_DIR/scheduler/xce_scheduler" + "$BUILD_DIR/frontend/apiserver/xce_apiserver" +) +[ -f "$BUILD_DIR/worker/xcecd_virtual" ] && stage_bins+=("$BUILD_DIR/worker/xcecd_virtual") + +for src in "${stage_bins[@]}"; do + while IFS= read -r lib; do + [ -z "$lib" ] && continue + if [[ ! "$lib" =~ $BASE_LIB_RE ]]; then + name="$(basename "$lib")" + if [ -z "${BUNDLED[$name]:-}" ]; then + cp -L "$lib" "$STAGING/lib/" + BUNDLED[$name]=1 + fi + fi + done < <(ldd "$src" 2>/dev/null | awk '/=> \// {print $3} /^\// {print $1}') +done + +# NB: this box's bash 5.2.21 expands ${#BUNDLED[@]} on an EMPTY associative +# array as unbound under set -u, so test lib/ occupancy instead of the map. +if [ -n "$(ls -A "$STAGING/lib/" 2>/dev/null)" ]; then + echo "=== Bundled ${#BUNDLED[@]} non-base libraries: ${!BUNDLED[*]} ===" + # Give every packaged binary a $ORIGIN RPATH so bundled libs resolve + # without LD_LIBRARY_PATH (which leaks into child processes -- exactly + # what the nix layout got wrong, see DEPS.md). This REPLACES the + # build-tree RPATH meson baked in (which dangles in staging). + for bin in "$STAGING"/bin/*; do + if file "$bin" | grep -q ELF && [ ! -L "$bin" ]; then + patchelf --set-rpath '$ORIGIN/../lib' "$bin" 2>/dev/null || true + fi + done + for lib in "$STAGING"/lib/*; do + patchelf --set-rpath '$ORIGIN' "$lib" 2>/dev/null || true + done +else + echo "=== No non-base libraries to bundle (all resolved from base dirs) ===" +fi + +# --- xceadmin venv rebasing (venv python path is absolute -- rebase it) --- +XCEADMIN_REAL="$STAGING/share/xce/xceadmin-venv/bin/xceadmin" +if [ -f "$XCEADMIN_REAL" ]; then + # pip's console scripts carry the BUILD host's absolute venv-python + # shebang, and shebangs cannot be relative -- any fixed rewrite + # (staging path or /usr/bin/python3) breaks somewhere: + # - the staging path dangles after install.sh moves the tree; + # - the bare target python3 lacks the venv's site-packages, so + # `import xceadmin` dies with ModuleNotFoundError. + # Fix at INSTALL time instead: install.sh rewrites the shebangs to the + # venv's own bin/python3 (a symlink to the target's python3 -- same + # major version required, DEPS.md floor -- that launches with the + # venv's site-packages active). bin/xceadmin is a tiny sh wrapper + # exec'ing that same venv python directly, so it works even pre-rewrite. + host_py="$(head -1 "$XCEADMIN_REAL" | sed 's/^#!//')" + if [ -n "$host_py" ]; then + sed -i "1s|^#!.*|#!\"$(dirname "$XCEADMIN_REAL")/python3\"|" "$XCEADMIN_REAL" + fi + rm -f "$STAGING/bin/xceadmin" + cat > "$STAGING/bin/xceadmin" <<'EOF' +#!/bin/sh +# exec the bundled xceadmin venv CLI (paths relative to this wrapper: +# bin/ and share/ are siblings in the install prefix). +SELF_DIR="$(cd "$(dirname "$0")" && pwd)" +VENV="$SELF_DIR/../share/xce/xceadmin-venv" +exec "$VENV/bin/python3" "$VENV/bin/xceadmin" "$@" +EOF + chmod 755 "$STAGING/bin/xceadmin" +fi + +# --- configs + schemas + docs --- +cp -r "$SRC_DIR/configs" "$STAGING/share/xce/configs" +mkdir -p "$STAGING/share/xce/schema" +cp "$SRC_DIR"/schema/*.capnp "$STAGING/share/xce/schema/" +[ -f "$SRC_DIR/docs/xce.md" ] && cp "$SRC_DIR/docs/xce.md" "$STAGING/share/docs/" + +# --- systemd unit samples --- +mkdir -p "$STAGING/share/xce/systemd" +cat > "$STAGING/share/xce/systemd/xce-controller.service" <<'EOF' +[Unit] +Description=XCE Controller +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +ExecStart=/opt/xce/bin/xce_controller --myname %H --peers %H=localhost:9990 +Restart=on-failure +RestartSec=2 +User=root +LimitNOFILE=65536 + +[Install] +WantedBy=multi-user.target +EOF +cat > "$STAGING/share/xce/systemd/xce-worker@.service" <<'EOF' +[Unit] +Description=XCE Worker on %i +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +ExecStart=/opt/xce/bin/xcecd --myname %i --controller %i:9990 +Restart=on-failure +RestartSec=2 +User=root +LimitNOFILE=65536 + +[Install] +WantedBy=multi-user.target +EOF +cat > "$STAGING/share/xce/systemd/xce-scheduler.service" <<'EOF' +[Unit] +Description=XCE Scheduler +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +Environment=XCE_CONTROLLER_PEERS=ctrl=localhost:9990 +ExecStart=/opt/xce/bin/xce_scheduler -l /var/log/xce/xce_scheduler.log -v +Restart=on-failure +RestartSec=2 +User=root + +[Install] +WantedBy=multi-user.target +EOF + +# --- install script --- +cat > "$STAGING/install.sh" <<'EOF' +#!/bin/sh +# Install XCE into /opt/xce (override with PREFIX=... ./install.sh). +set -e +cd "$(dirname "$0")" # run from anywhere: resolve bin/ lib/ share/ next to us +PREFIX="${PREFIX:-/opt/xce}" +mkdir -p "$PREFIX" +cp -r bin lib share "$PREFIX/" +# Rebases the bundled xceadmin venv: pip's console-script shebangs carry +# the BUILD host's absolute venv-python path (a shebang cannot be +# relative, so the packager cannot pre-fix this for an unknown PREFIX). +VENV_PY="$PREFIX/share/xce/xceadmin-venv/bin/python3" +for f in "$PREFIX/share/xce/xceadmin-venv/bin"/*; do + case "$(head -1 "$f" 2>/dev/null)" in + # No quoting around $VENV_PY in the shebang: the kernel does NOT + # parse quotes on the #! line and would exec a path with literal '"'. + "#!"*python3 | "#!"*python3'"') sed -i "1s|^#!.*|#!$VENV_PY|" "$f" ;; + esac +done +echo "XCE installed to $PREFIX -- systemd unit samples in $PREFIX/share/xce/systemd/" +EOF +chmod 755 "$STAGING/install.sh" + +# --- tarball --- +STAGE_BASE="$(basename "$STAGING")" # staging-xce- +echo "=== Creating $OUT_DIR/$PKG_NAME.tar.gz ===" +tar -C "$OUT_DIR" -czf "$OUT_DIR/$PKG_NAME.tar.gz" "$STAGE_BASE" +rm -rf "$STAGING" +echo "=== Done: $OUT_DIR/$PKG_NAME.tar.gz ===" diff --git a/src/worker/meson.build b/src/worker/meson.build index abf45a02..4d97789b 100644 --- a/src/worker/meson.build +++ b/src/worker/meson.build @@ -27,18 +27,27 @@ xcecd_worker_srcs = [ incdir = include_directories('.', 'include', '../include', '../lib') -libuv_dep = dependency('libuv') -elogind_dep = dependency('libelogind') -sqlite3_dep = dependency('sqlite3') -libcgroup_dep = dependency('libcgroup') -hwloc_dep = dependency('hwloc') +libuv_dep = dependency('libuv', version: '>=1.44') +# sd-bus consumer (start_systemd_job / xcecd_dbus_manager): same sd-bus API +# ships in both libelogind (non-systemd platforms) and libsystemd (standard +# Ubuntu/RHEL). Default libsystemd -- the library every supported production +# distro has; opt back into elogind with -Duse_elogind=true (nix build path). +use_elogind = get_option('use_elogind') +if use_elogind + sd_dep = dependency('libelogind') +else + sd_dep = dependency('libsystemd') +endif +sqlite3_dep = dependency('sqlite3', version: '>=3.37') +libcgroup_dep = dependency('libcgroup', version: '>=2.0') +hwloc_dep = dependency('hwloc', version: '>=2.8') xcecd_worker_deps = [ libxce_dep, libcgroup_dep, hwloc_dep, libuv_dep, - elogind_dep, + sd_dep, sqlite3_dep, struct2json_dep, yaml_deps, diff --git a/src/worker/testsuite/meson.build b/src/worker/testsuite/meson.build index bac88e50..2464387f 100644 --- a/src/worker/testsuite/meson.build +++ b/src/worker/testsuite/meson.build @@ -6,12 +6,11 @@ # for why controller_connector.c is not also listed in xcecd_srcs here (it # would double-define every symbol in that file). -# unity.pc's Cflags only adds -I${includedir}/unity, so resolves -# but (used by every suite) does not — add the parent -# includedir as well (same fix as src/lib/meson.build). +# and both resolve through unity_dep itself: the +# wrap-path override (or the nix pc under the legacy build) carries the +# include roots for both layouts, so no extra parent-includedir hack here. worker_test_incdir = include_directories('../include', '../../include', '.', - '../src', '../../lib', - unity_dep.get_variable('includedir')) + '../src', '../../lib') worker_test_deps = [xcecd_worker_deps, unity_dep] diff --git a/src/xceadmin/meson-build.sh b/src/xceadmin/meson-build.sh index 2f423d73..6ab5898a 100755 --- a/src/xceadmin/meson-build.sh +++ b/src/xceadmin/meson-build.sh @@ -136,15 +136,28 @@ fi echo "=== xceadmin (meson): pinned install into build-dir venv (python: $PYTHON) ===" rm -rf "$VENV_DIR" -"$PYTHON" -m venv --system-site-packages "$VENV_DIR" -# Offline install: the Nix build sandbox has no network. Runtime deps -# (click/pycapnp/PyYAML/jsonschema) come from the nix python env via -# --system-site-packages; the setuptools build backend comes from the same -# env (added to nixSupport/xce.nix nativeBuildInputs). --no-build-isolation -# stops pip from fetching setuptools from PyPI to build in an isolated env; -# --no-index --no-deps forbid any network index / dependency resolution. -"$VENV_DIR/bin/pip" install "$WORK_DIR" \ - --no-build-isolation --no-index --no-deps --quiet +"$PYTHON" -m venv "$VENV_DIR" +# De-nix build path: the venv is self-contained (no --system-site-packages). +# Runtime deps (click/pycapnp/PyYAML/jsonschema) + the setuptools build +# backend are installed from requirements-build.txt (pinned, offline via a +# local pip cache or an index the build host can reach). pycapnp's C +# extension links the system capnproto C++ runtime (apt capnproto / +# libcapnp-dev, see DEPS.md). If the build host has no PyPI access, seed the +# pip cache first: pip download -r requirements-build.txt -d /path/to/wheels +# and export PIP_FIND_LINKS=/path/to/wheels. +"$VENV_DIR/bin/pip" install --upgrade pip setuptools wheel --quiet \ + ${PIP_FIND_LINKS:+--find-links "$PIP_FIND_LINKS"} \ + ${PIP_NO_INDEX:+--no-index} +# pytest is a test-only dependency (not in requirements-build.txt's runtime +# list) but meson-build.sh always runs the test suite below -- in the nix +# shell it came from the nix python env; the de-nix venv must pip-install it +# explicitly (same offline knobs as the installs above). +"$VENV_DIR/bin/pip" install pytest --quiet \ + ${PIP_FIND_LINKS:+--find-links "$PIP_FIND_LINKS"} \ + ${PIP_NO_INDEX:+--no-index} +"$VENV_DIR/bin/pip" install "$WORK_DIR" --quiet \ + ${PIP_FIND_LINKS:+--find-links "$PIP_FIND_LINKS"} \ + ${PIP_NO_INDEX:+--no-index} echo "=== xceadmin (meson): running tests ===" # tests/_live_e2e_common.py's XCEADMIN_CANDIDATES look for a sibling diff --git a/src/xceadmin/requirements-build.txt b/src/xceadmin/requirements-build.txt new file mode 100644 index 00000000..0f312d8f --- /dev/null +++ b/src/xceadmin/requirements-build.txt @@ -0,0 +1,11 @@ +# xceadmin build/runtime requirements (de-nix build path, see DEPS.md). +# Mirrors pyproject.toml dependencies; kept as a flat list so the build venv +# can be seeded with `pip install -r requirements-build.txt` (optionally +# offline via PIP_FIND_LINKS pointing at a pip download cache). +click>=8.0 +pycapnp>=1.3 +PyYAML>=6.0 +jsonschema>=4.0 +# build backend (pyproject build-system) +setuptools>=68 +wheel