Compare commits

...

266 Commits

Author SHA1 Message Date
Nicholas Dudfield
24baae1786 refactor(hooks): simplify macro names for byte validation
- Rename VALIDATE_JS_BYTES* macros to shorter JS_BYTES* variants
- Improve code readability with more concise macro names
- Apply consistent formatting to macro definitions
2025-07-29 16:37:28 +07:00
Nicholas Dudfield
81803283da refactor(hooks): add validation framework and clean up state_foreign_set
- Move error types into jshook namespace for better organization
- Rename JSByteConversion* to ByteConversion* for consistency
- Fix EmptyInput handling to return Success instead of error
- Add comprehensive validation framework with ValidationResult
- Create reusable validators for state_data, state_key, namespace, account_id
- Introduce VALIDATE_JS_BYTES macros for consistent validation
- Simplify state_foreign_set implementation using new validation system
- Improve variable naming and code clarity
2025-07-29 16:33:51 +07:00
Nicholas Dudfield
8dab03a39f refactor(hooks): improve error handling in FromJSIntArrayOrHexString
- Add comprehensive error enum JSByteConversionError
- Introduce JSByteConversionResult struct with detailed status
- Add JSByteConversionOptions for configuration
- Fix boundary condition (255 vs 256) in byte range validation
- Add truncation support for oversized inputs
- Improve memory management with proper JS_FreeValue calls
- Fix hex string parsing logic and bounds checking
2025-07-29 15:40:49 +07:00
tequ
a6c4e39235 Improve validation for state_foreign_set (#554)
* Fix `FromJSIntArrayOrHexString` `[]` or `”"` return vector(size=0), not nullptr.

* improve validation for `state_foreign_set`
2025-07-29 12:40:53 +07:00
tequ
50a6499112 Fix FromJSIntArrayOrHexString [] or ”" return vector(size=0), not nullptr. (#553) 2025-07-29 12:40:39 +07:00
tequ
429f3289d8 Merge branch 'dev' into jshooks 2025-07-16 13:27:02 +09:00
Niq Dudfield
849d447a20 docs(freeze): canceling escrows with deep frozen assets is allowed (#540) 2025-07-09 13:48:59 +10:00
tequ
ee27049687 IOUIssuerWeakTSH (#388) 2025-07-09 13:48:26 +10:00
tequ
60dec74baf Add DeepFreeze test for URIToken (#539) 2025-07-09 12:49:47 +10:00
Denis Angell
9abea13649 Feature Clawback (#534) 2025-07-09 12:48:46 +10:00
Denis Angell
810e15319c Feature DeepFreeze (#536)
---------

Co-authored-by: tequ <git@tequ.dev>
2025-07-09 10:33:08 +10:00
Niq Dudfield
d593f3bef5 fix: provisional PreviousTxn{Id,LedgerSeq} double threading (#515)
---------

Co-authored-by: tequ <git@tequ.dev>
2025-07-08 18:04:39 +10:00
Niq Dudfield
1233694b6c chore: add suspicious_patterns to .scripts/pre-hook and not-suspicious filter (#525)
* chore: add suspicious_patterns to .scripts/pre-hook and not-suspicious filter

* rm: kill annoying checkpatterns job

* chore: cleanup

---------

Co-authored-by: RichardAH <richard.holland@starstone.co.nz>
2025-07-01 20:58:06 +10:00
tequ
a1d42b7380 Improve unittests (#494)
* Match unit tests on start of test name (#4634)

* For example, without this change, to run the TxQ tests, must specify
  `--unittest=TxQ1,TxQ2` on the command line. With this change, can use
  `--unittest=TxQ`, and both will be run.
* An exact match will prevent any further partial matching.
* This could have some side effects for different tests with a common
  name beginning. For example, NFToken, NFTokenBurn, NFTokenDir. This
  might be useful. If not, the shorter-named test(s) can be renamed. For
  example, NFToken to NFTokens.
* Split the NFToken, NFTokenBurn, and Offer test classes. Potentially speeds
  up parallel tests by a factor of 5.

* SetHook_test, SetHookTSH_test, XahauGenesis_test

---------

Co-authored-by: Ed Hennis <ed@ripple.com>
2025-06-30 10:03:02 +10:00
tequ
f6d2bf819d Fix governance vote purge (#221)
governance hook should be independently and deterministically recompiled before being voted in
2025-06-16 17:12:06 +10:00
Nicholas Dudfield
257c46ec9c chore: remove duplicate cmake policy directive from bad merge 2025-05-15 08:57:42 +07:00
Nicholas Dudfield
637d626518 Merge remote-tracking branch 'origin/dev' into jshooks 2025-05-14 19:37:45 +07:00
Denis Angell
a5ea86fdfc Add Conan Building For Development (#432) 2025-05-14 14:00:20 +10:00
RichardAH
615f56570a Sus pat (#507) 2025-05-01 17:23:56 +10:00
RichardAH
5e005cd6ee remove false positives from sus pat finder (#506) 2025-05-01 09:54:41 +10:00
Denis Angell
80a7197590 fix warnings (#505) 2025-04-30 11:51:58 +02:00
tequ
7b581443d1 Suppress build warning introduced in Catalogue (#499) 2025-04-29 08:25:55 +10:00
tequ
5400f43359 Supress logs for Catalogue_test, Import_test (#495) 2025-04-24 17:46:09 +10:00
Denis Angell
8cf7d485ab fix: ledger_index (#498) 2025-04-24 16:45:01 +10:00
tequ
372f25d09b Remove #ifndef DEBUG guards and exception handling wrappers (#496) 2025-04-24 16:38:14 +10:00
Denis Angell
401395a204 patch remarks (#497) 2025-04-24 16:36:57 +10:00
tequ
4221dcf568 Add tests for SetRemarks (#491) 2025-04-18 09:34:44 +10:00
tequ
989532702d Update clang-format workflow (#490) 2025-04-17 16:16:59 +10:00
RichardAH
f9cd2e0d21 Remarks amendment (#301)
Co-authored-by: Denis Angell <dangell@transia.co>
2025-04-16 08:42:04 +10:00
tequ
59e334c099 fixRewardClaimFlags (#487) 2025-04-15 20:08:19 +10:00
tequ
9018596532 HookCanEmit (#392) 2025-04-15 13:32:35 +10:00
Niq Dudfield
b827f0170d feat(catalogue): add cli commands and fix file_size (#486)
* feat(catalogue): add cli commands and fix file_size

* feat(catalogue): add cli commands and fix file_size

* feat(catalogue): fix tests

* feat(catalogue): fix tests

* feat(catalogue): use formatBytesIEC

* feat: add file_size_estimated

* feat: add file_size_estimated

* feat: add file_size_estimated
2025-04-15 08:50:15 +10:00
tequ
e4b7e8f0f2 Update sfcodes script (#479) 2025-04-10 09:44:31 +10:00
tequ
1485078d91 Update CHooks build script (#465) 2025-04-09 20:22:34 +10:00
tequ
6625d2be92 Add xpop_slot test (#470) 2025-04-09 20:20:23 +10:00
tequ
2fb5c92140 feat: Run unittests in parallel with Github Actions (#483)
Implement parallel execution for unit tests using Github Actions to improve CI pipeline efficiency and reduce build times.
2025-04-04 19:32:47 +02:00
Niq Dudfield
c4b5ae3787 Fix missing includes in Catalogue.cpp for non-unity builds (#485) 2025-04-04 12:53:45 +10:00
Nicholas Dudfield
cce9d372e7 [CONAN] Disable not working static containers 2025-04-04 09:09:46 +07:00
Nicholas Dudfield
aa571df467 Fix missing includes in Catalogue.cpp for non-unity builds 2025-04-04 09:00:43 +07:00
Nicholas Dudfield
ae8f6a16ed Merge remote-tracking branch 'origin/dev' into jshooks 2025-04-04 08:40:04 +07:00
Niq Dudfield
d546d761ce Fix using using Status with rpcError (#484) 2025-04-01 21:00:13 +10:00
RichardAH
e84a36867b Catalogue (#443) 2025-04-01 16:47:48 +10:00
Denis Angell
64441f7f40 Merge branch 'tmp-conan' into jshooks 2025-03-30 16:50:43 +02:00
Denis Angell
0bf50c5dc7 eof 2025-03-30 16:48:43 +02:00
Denis Angell
8b0592ce06 Update xahau-sh-build-in-docker.yml 2025-03-29 04:22:35 +01:00
Denis Angell
c27e2a9c05 Update xahau-sh-build-in-docker.yml 2025-03-29 03:26:09 +01:00
Denis Angell
f8d22bbc24 add caching 2025-03-29 03:08:58 +01:00
Denis Angell
95ab35a185 Update release-builder.sh 2025-03-29 02:43:43 +01:00
Denis Angell
313ad7134b test workflow 2025-03-29 02:40:38 +01:00
Denis Angell
859dcbcabf remove EXIT_IF_CONTAINER_RUNNING 2025-03-29 02:26:01 +01:00
Denis Angell
a8e9448b1a revert docker dependency cache 2025-03-29 02:15:13 +01:00
Denis Angell
cab4d63a07 revert some cmake builds 2025-03-28 20:44:09 +01:00
Denis Angell
9a90a7ffdc optional release builder 2025-03-28 20:42:18 +01:00
Denis Angell
ddbbe91e5a attempt fix builder 2025-03-28 19:32:37 +01:00
Denis Angell
2d9ac91cd1 fix build dir 2025-03-28 14:35:41 +01:00
Denis Angell
9532ea7dec tmp fix docker release builder 2025-03-28 12:01:56 +01:00
Denis Angell
ed243745f8 fix checkpatterns 2025-03-28 11:49:45 +01:00
Denis Angell
5eac2d3e44 change on fields 2025-03-28 11:44:22 +01:00
Denis Angell
245cf4a676 refactor checkpatterns remove comments 2025-03-28 10:44:18 +01:00
Denis Angell
864734f607 Update xahau-sh-build-in-docker.yml 2025-03-28 10:35:21 +01:00
Niq Dudfield
689740d818 Use GA runners with conan/ccache caches (#482) 2025-03-28 10:29:55 +01:00
Nicholas Dudfield
a8c80e99c0 [CONAN] GA only needs to declare push with ignore-branches 2025-03-28 13:57:38 +07:00
Nicholas Dudfield
486003f1a8 [CONAN] Do not build on sh runner for PRs targeting dev 2025-03-28 13:39:04 +07:00
Nicholas Dudfield
c9f0fe02a1 [CONAN] Namespace xahau actions/workflows for easier upstream 2025-03-28 13:27:03 +07:00
Nicholas Dudfield
a9c096e59c Add :log-test-names: target for --unittest-arg 2025-03-28 08:47:07 +07:00
Nicholas Dudfield
a83a157058 [CONAN] Remove straggling .build_deps mention 2025-03-28 08:46:40 +07:00
Nicholas Dudfield
5e255e560f [CONAN] Fix Claude's mess 2025-03-28 08:09:25 +07:00
Nicholas Dudfield
c953ee326d [CONAN] Move caching steps into build/dependencies actions 2025-03-28 07:52:08 +07:00
Nicholas Dudfield
053a10a236 [CONAN] clean up comments 2025-03-27 12:38:22 +07:00
Nicholas Dudfield
c53dcf1422 feat: add RUN_TARGET_PATTERN macro with --unittest-arg regex 2025-03-27 12:38:10 +07:00
Nicholas Dudfield
34b148bda0 [CONAN] better ccache keys 2025-03-26 08:06:12 +07:00
Nicholas Dudfield
19111a3739 [CONAN] use always() and step conclusion 2025-03-25 21:03:12 +07:00
Nicholas Dudfield
3f98c15910 [CONAN] use step conclusion 2025-03-25 20:44:32 +07:00
Nicholas Dudfield
942227f8c3 [CONAN] stable fallback cache key 2025-03-25 20:17:53 +07:00
Nicholas Dudfield
e9461c827c [CONAN] prime .ccache 2025-03-25 19:47:37 +07:00
Nicholas Dudfield
3d9423dda6 [CONAN] use dummy jobs 2025-03-25 19:24:06 +07:00
Nicholas Dudfield
5d41688e36 [CONAN] fallback cache key with run_id 2025-03-25 19:03:55 +07:00
Nicholas Dudfield
9bd6d2244e [CONAN] dummy tests for now 2025-03-25 17:47:00 +07:00
Denis Angell
48919f028c [GA] Remove build caching 2025-03-25 11:40:18 +01:00
Nicholas Dudfield
46d745b43f [CONAN] include-hidden-folders: true 2025-03-25 17:34:57 +07:00
Nicholas Dudfield
5365bbcfe8 [CONAN] fix MacOS ccache folder 2025-03-25 16:45:44 +07:00
Denis Angell
9c26f1f213 [GA] revert 2025-03-25 10:45:28 +01:00
Denis Angell
69b7728b2d [GA] tmp disable build cache 2025-03-25 10:37:17 +01:00
Nicholas Dudfield
15b679b1a7 [CONAN] cache ccache folder 2025-03-25 16:32:35 +07:00
Denis Angell
9178aa9d8a [GA] remove unused workflows 2025-03-25 10:17:33 +01:00
Denis Angell
17fdd09640 [GA] update conan profile 2025-03-25 10:13:05 +01:00
Denis Angell
40dc69d642 [GA] conan mac os build 2025-03-25 10:06:17 +01:00
Nicholas Dudfield
e8560c2198 [CONAN] try using glob 2025-03-25 15:50:18 +07:00
tequ
ca7533c14a fix zero XFL (#481) 2025-03-25 14:52:52 +07:00
Nicholas Dudfield
eba913a68e [CONAN] try using abs path 2025-03-25 14:42:24 +07:00
Nicholas Dudfield
ec849e0899 [CONAN] cache build directory too 2025-03-25 14:09:24 +07:00
Nicholas Dudfield
314fb6c9e0 [CONAN] cache build directory too 2025-03-25 14:03:09 +07:00
Nicholas Dudfield
643cd9fef1 Mark header file as generated 2025-03-25 13:24:25 +07:00
Nicholas Dudfield
3593d67df9 [CONAN] manually handle cache saving step in MacOS 2025-03-25 13:24:13 +07:00
Nicholas Dudfield
5571827be2 Merge branch 'tequdev/jshooks-date' into jshooks 2025-03-25 13:07:25 +07:00
Nicholas Dudfield
cfbfd762e8 [CONAN] manually handle cache saving step 2025-03-25 12:40:58 +07:00
Nicholas Dudfield
c25fd875a8 [CONAN] no access to 8 core runner 2025-03-25 12:31:31 +07:00
Nicholas Dudfield
043f1e96b6 [CONAN] install nproc 2025-03-25 12:26:15 +07:00
tequ
17dfca6e61 add Emit tests (#478)
* add tests for emits

* clang-format

* fix otxn_burden

* remove std:cout

* fix tests
2025-03-25 11:53:41 +07:00
Nicholas Dudfield
74681718dd [CONAN] fix typo and redundant deps step 2025-03-25 11:35:46 +07:00
Nicholas Dudfield
167417bfed [CONAN] remove redundant step 2025-03-25 09:35:29 +07:00
Nicholas Dudfield
2dd22648e8 [CONAN] use v4 -artifacts 2025-03-25 09:32:14 +07:00
Nicholas Dudfield
e89aa05a2a [CONAN] use simpler GA runners with conan cache 2025-03-25 09:26:32 +07:00
Nicholas Dudfield
8a5ccbf870 [CONAN] use simpler GA runners with conan cache 2025-03-25 09:09:18 +07:00
Nicholas Dudfield
f6f87e468a [CONAN] use simpler GA runners with conan cache 2025-03-25 09:06:22 +07:00
Nicholas Dudfield
d7167a9ebe [CONAN] use macos-15 2025-03-25 08:15:03 +07:00
Nicholas Dudfield
7446dddddb [CONAN] simplify matrix 2025-03-24 19:13:35 +07:00
Nicholas Dudfield
d9388e1e51 [CONAN] fix typo 2025-03-24 19:03:16 +07:00
Nicholas Dudfield
73c1748241 [CONAN] simplify matrix 2025-03-24 19:00:54 +07:00
Denis Angell
58e3840345 remove cxxflags for macos action 2025-03-24 12:02:01 +01:00
Nicholas Dudfield
61135c0ecb [CONAN] clean up conf experiments 2025-03-24 17:09:39 +07:00
Nicholas Dudfield
42a44d0cb8 [CONAN] clear the tools.build:cxxflags 2025-03-24 16:54:12 +07:00
Nicholas Dudfield
d37039897e [CONAN] clear the tools.build:cxxflags 2025-03-24 16:50:33 +07:00
Nicholas Dudfield
2061d6d44c [CONAN] clear cache 2025-03-24 16:40:59 +07:00
Nicholas Dudfield
8ea35ace02 [CONAN] remove DBOOST_ASIO_DISABLE_CONCEPTS define 2025-03-24 16:34:41 +07:00
Nicholas Dudfield
a203314c68 [CONAN] check clang --version 2025-03-24 16:32:47 +07:00
Nicholas Dudfield
092a29cd18 [CONAN] Use self-hosted runner again 2025-03-24 16:26:37 +07:00
Nicholas Dudfield
1ba18875ac [CONAN] Do not build cobalt 2025-03-24 16:12:34 +07:00
Nicholas Dudfield
2da58fe18f [CONAN] Run MacOS builds on GH runners 2025-03-24 15:57:05 +07:00
Nicholas Dudfield
8d7cc68bda Merge remote-tracking branch 'origin/tmp-conan' into jshooks 2025-03-23 11:09:17 +07:00
Denis Angell
b73dd584e7 Merge branch 'dev' into tmp-conan 2025-03-21 15:15:03 +01:00
Denis Angell
0726789d77 update conan to 1.86 2025-03-21 15:09:59 +01:00
Niq Dudfield
0b675465b4 Fix ServerDefinitions_test regression intro in #475 (#477) 2025-03-19 12:32:27 +10:00
Nicholas Dudfield
05bd9c6ea8 Use official shell script 2025-03-18 17:25:10 +07:00
Nicholas Dudfield
f9e7ea95fd Test for NO_FREE_SLOTS 2025-03-18 17:08:43 +07:00
tequ
618a933241 Add xpop_slot test (#476)
* add xpop_slot test

* clang-format
2025-03-18 17:07:12 +07:00
Niq Dudfield
d088ad61a9 Prevent dangling reference in getHash() (#475)
Replace temporary uint256 with static variable when returning fallback hash
to avoid returning a const reference to a local temporary object.
2025-03-18 18:37:18 +10:00
Nicholas Dudfield
752dbf34ee Automatically add MacOS gsed/ggrep paths to PATH if exist 2025-03-18 15:04:50 +07:00
tequ
fcf3848814 Add tests for fee_base, ledger_keylet, meta_slot (#469)
* add tests for fee_base, ledger_keylet, meta_slot

* clang-format

* clang-format

* update SetJSHook_wasm.h
2025-03-18 15:01:36 +07:00
Nicholas Dudfield
e4a6aecc18 Bump numFeatures 2025-03-18 14:55:50 +07:00
tequ
1c4ebfe3ad Updated the jshook build script so that it works on macOS and Ubuntu (#464) 2025-03-18 13:18:30 +07:00
Nicholas Dudfield
f97165e4bc Return DOESNT_EXIST in JSHooks sto_erase #463 2025-03-18 13:16:53 +07:00
Nicholas Dudfield
fc50c0fb0a Free out array in slot before returning special case int64 #467 2025-03-18 13:15:38 +07:00
Nicholas Dudfield
1b12b400d7 Add missing JS_FreeValue calls for early returns #468 2025-03-18 13:14:23 +07:00
Nicholas Dudfield
f3ee0dd322 Fix validate exception handling #473 2025-03-18 13:08:40 +07:00
Nicholas Dudfield
d9659dc226 Merge remote-tracking branch 'origin/dev' into jshooks 2025-03-18 13:03:10 +07:00
Nicholas Dudfield
fb7af36cef Update jshooks header 2025-03-18 11:46:22 +07:00
tequ
4bfe27d11f Enable JS Date on using parent ledger close time 2025-03-17 13:40:59 +09:00
tequ
eaa2cc9e5c [JSHooks] Add sto tests (#460) 2025-03-12 11:56:37 +01:00
tequ
6aa1ff87b9 add tests for float_sto, float_sto_set, float_sum (#462) 2025-03-12 11:39:12 +01:00
Niq Dudfield
ef77b02d7f CI Release Builder (#455) 2025-03-11 13:19:28 +01:00
Denis Angell
5ef3795cea [fix] release build issue 2025-03-06 08:47:01 +01:00
Denis Angell
da5f1d189b Merge branch 'dev' into tmp-conan 2025-03-05 08:22:27 +01:00
Denis Angell
6fdf788b13 Merge branch 'dev' into tmp-conan 2025-02-28 10:22:52 +01:00
Niq Dudfield
61f45055a7 feat(quickjs): add test_sto_emplace (#448) 2025-02-27 07:42:14 +01:00
Denis Angell
f9e7fed929 [revert] typo 2025-02-26 11:38:12 +01:00
Denis Angell
5cfe566489 [fold] update test wasm 2025-02-24 10:13:44 +01:00
Denis Angell
04409616ed [fold] clang-format 2025-02-24 10:02:09 +01:00
Denis Angell
ca04c2a802 float_sto_set return bigint
Co-authored-by: tequ <git@tequ.dev>
2025-02-24 09:58:45 +01:00
Denis Angell
f868b4d6e6 reorder free context
Co-authored-by: tequ <git@tequ.dev>
2025-02-24 09:58:15 +01:00
Denis Angell
5502453de8 [fold] clang-format 2025-02-24 09:49:19 +01:00
Denis Angell
359ab70ba0 Merge branch 'dev' into jshooks 2025-02-24 09:31:28 +01:00
tequ
d82f60705d add replacer for Stringify bigint value (#437) 2025-02-24 09:28:12 +01:00
tequ
15515b84f8 fix sto_from_json error (#438) 2025-02-24 09:27:21 +01:00
tequ
8b29fc5ee1 Add bytecode validity check on SetHook (#439) 2025-02-24 09:26:31 +01:00
tequ
92be8146e8 fix JSHooks tests (#446) 2025-02-24 09:25:45 +01:00
Denis Angell
c0f55d0b00 Merge branch 'dev' into jshooks 2025-02-21 11:08:02 +01:00
Denis Angell
802ea6c568 [temp] remove negative rate test 2025-02-11 14:32:29 +01:00
Denis Angell
ecc779346e Merge branch 'dev' into tmp-conan 2025-02-11 12:11:27 +01:00
Denis Angell
680c6095d4 Update macos.yml 2025-02-11 12:06:20 +01:00
Denis Angell
6858861660 fix failing test 2025-02-07 11:01:20 +01:00
Denis Angell
9faef17407 fix bad commit 2025-02-06 11:13:29 +01:00
Denis Angell
ee68cc2cd2 clang-format 2025-02-05 11:31:06 +01:00
Denis Angell
7c360bad33 add optional include 2025-02-05 11:31:00 +01:00
Denis Angell
26a66bc2ef fix misc warnings 2025-02-04 12:24:34 +01:00
Denis Angell
4b93e1657f fix macos github action 2025-02-04 12:18:32 +01:00
Denis Angell
cd45285cab include optional 2025-02-04 12:18:25 +01:00
Denis Angell
b7acfb9803 fix misc warnings 2025-02-04 12:18:09 +01:00
Denis Angell
97a10d6556 [fold] fix test 2025-02-04 12:08:12 +01:00
Denis Angell
fe43029272 [fold] clang-format 2025-02-02 23:13:25 +01:00
Denis Angell
bf33b6f637 [fold] update conan 2025-02-02 22:25:33 +01:00
Denis Angell
c27518b846 [fold] use rippleci docker image 2025-02-02 22:23:26 +01:00
Denis Angell
7d8f5de93d [fold] remove conan patch 2025-02-02 22:23:15 +01:00
Denis Angell
858ea1bf25 [fold] add external snappy 2025-02-02 21:46:08 +01:00
Denis Angell
7162fe0497 [fold] upgrade artifact@v4 2025-02-02 21:09:52 +01:00
Denis Angell
56c0e0dd5f [fold] fix bad assert 2025-02-02 21:07:09 +01:00
Denis Angell
20ca066454 [fold] update workflow 2025-02-02 21:06:55 +01:00
Denis Angell
171610d1a9 [release] add release build 2025-02-01 16:54:35 +01:00
Denis Angell
2f6cf0ab4b [patch] remit transfer rate 2025-02-01 13:11:56 +01:00
Denis Angell
71884ad48a sync 2025-02-01 12:11:01 +01:00
Denis Angell
799a056313 conan 2025-02-01 12:00:35 +01:00
tequ
eec61f16c9 JSHooks Instruction Count (#423) 2025-01-22 08:39:20 +10:00
tequ
1bed7f1196 fix jshooks build error (#410) 2024-12-16 12:58:40 -05:00
RichardAH
211e63c568 Merge pull request #386 from tequdev/fix-jshooks-at-macos-build
Co-authored-by: Denis Angell <dangell@transia.co>
2024-12-11 11:36:06 +10:00
RichardAH
81413a5ce8 Merge branch 'jshooks' into fix-jshooks-at-macos-build 2024-12-11 11:32:39 +10:00
RichardAH
36d630bed3 Merge branch 'dev' into jshooks 2024-11-15 08:38:14 +10:00
Denis Angell
4f901788f4 [fold] preprocessor macros 2024-11-11 11:13:57 +01:00
tequ
72e773cbff fix: not to use std::lexicographical_compare_three_way 2024-10-28 16:02:56 +09:00
tequ
39ec8fb901 fix: build error no type named 'Reader' in namespace 'Json' 2024-10-28 16:02:16 +09:00
Denis Angell
534870f2f0 Merge branch 'dev' into jshooks 2024-10-23 12:39:44 +02:00
Denis Angell
db245d237c build for mac 2024-10-23 12:37:19 +02:00
Denis Angell
f3118ef8fa fix return error 2024-09-19 13:27:16 +02:00
Denis Angell
ee21449757 float_sign should be int not bigint 2024-09-19 11:30:11 +02:00
Denis Angell
9e7bee5564 fix slot_float return 2024-09-19 11:26:33 +02:00
Wietse Wind
8cb2bbb693 Workaround CentOS7 EOL 2024-08-18 02:20:43 +02:00
Richard Holland
c240c1553b rename HooksV1 feature to JSHooks feature 2024-08-04 10:11:11 +10:00
Denis Angell
a498ebeac4 update tests 2024-07-30 12:25:51 +02:00
Denis Angell
b13cab4ced add proper error handling 2024-07-30 12:18:49 +02:00
Denis Angell
783bff75a0 add feature 2024-07-30 12:17:00 +02:00
Denis Angell
c1610a6dda fix v1 errors 2024-07-29 11:27:21 +02:00
Richard Holland
f829a79d54 better exit handling accept/rollback/exception/instruction limit 2024-07-17 15:14:03 +10:00
Denis Angell
f35704c91f add tests 2024-07-16 12:58:01 +02:00
Richard Holland
9db9ad2123 add error logging for qjs 2024-07-16 12:31:02 +10:00
Richard Holland
f96daa0014 TextEncoder/Decoder working in jshooks 2024-07-15 15:57:05 +10:00
Denis Angell
5c7ec5f36f more testing 2024-07-12 22:51:35 +02:00
Denis Angell
c662a8b0d2 comment out debug 2024-07-12 22:47:38 +02:00
Denis Angell
a983120b5d patch state_foreign_set delete 2024-07-12 22:36:44 +02:00
Richard Holland
f12b8cbb2d qjs modules, compiling not tested 2024-07-11 11:31:29 +10:00
Richard Holland
f591290589 first iteration of adding an instruction limit to jshooks 2024-07-08 12:49:36 +10:00
Richard Holland
f2becaf140 remove promise, date and proxy from the jsvm 2024-07-04 11:50:54 +10:00
Richard Holland
e4c6add794 make accept/rollback actually exit the jsvm 2024-07-04 10:50:01 +10:00
Denis Angell
78280e4b8c fix sto_subarray 2024-06-03 11:06:56 +02:00
Denis Angell
178fdbaff6 remove dummy arg causes INVALID_ARGUMENT for keylets without args 2024-05-31 12:05:10 +02:00
Denis Angell
34d7435ff3 cont. tests 2024-05-30 15:41:38 +02:00
Denis Angell
6429ec609d cont. tests 2024-05-30 15:39:05 +02:00
Wietse Wind
bea1697baa Fix JS float_int return JS instead of JSXFL 2024-05-30 12:06:15 +02:00
Wietse Wind
2b111b7f23 Fix account_tx sluggishness as per https://github.com/XRPLF/rippled/commit/2e9261cb (#330) 2024-05-30 11:47:05 +02:00
Denis Angell
5254595063 add tests 2024-05-30 09:30:19 +02:00
Wietse Wind
52456a2d51 CI Split jobs with prev job dependency & CI on jshooks (#320) (#328)
* CI on `jshooks` branch

* CI Split jobs with prev job dependency

* No multi branch worker in parallel

---------

Co-authored-by: Denis Angell <dangell@transia.co>
2024-05-29 13:48:39 +02:00
Wietse Wind
b340824711 Merge pull request #326 from Xahau/dev
CI on `jshooks` branch (#317)
2024-05-29 13:45:06 +02:00
Denis Angell
f5bb779f61 nit: reorder fields 2024-05-28 17:02:11 +02:00
Denis Angell
bf99a1b05d fix sto_emplace 2024-05-28 15:34:09 +02:00
Denis Angell
d1e5eb87f5 Revert "dump"
This reverts commit b650d72f0b.
2024-05-28 15:32:44 +02:00
Denis Angell
b650d72f0b dump 2024-05-28 15:30:07 +02:00
Denis Angell
7567277dd8 [fold] denis error 2024-05-25 16:28:31 +02:00
Denis Angell
13719a1357 fix_float 2024-05-25 13:52:15 +02:00
Denis Angell
033dedf979 fix float_set 2024-05-24 14:23:01 +02:00
Richard Holland
6973540d52 fix account type on js otxn_field 2024-05-24 10:07:05 +10:00
Richard Holland
c9dcff90fa fix js otxn_id hook_account bugs 2024-05-24 10:07:05 +10:00
Richard Holland
71675c4fed js slot_json sto_to_json sto_from_json meta_slot xpop_slot 2024-05-24 10:07:05 +10:00
Denis Angell
70bc2d3283 more js hook tests 2024-05-24 10:07:05 +10:00
Denis Angell
c4d0fc0e0f [fold] tmp use hsov1
Will remove later just did this to avoid to many updates
2024-05-24 10:07:05 +10:00
Denis Angell
5d61eea709 clean up test code 2024-05-24 10:07:05 +10:00
Denis Angell
f4ffe4a3e0 add set js hook tests 2024-05-24 10:07:05 +10:00
Denis Angell
59ecbd9932 add hso w/ api version 2024-05-24 10:07:05 +10:00
Richard Holland
6c3da46a1b js prepare/emit working 2024-05-24 10:07:05 +10:00
Richard Holland
46308e33b0 js prepare otxn_json, compiling not tested 2024-05-24 10:07:05 +10:00
Richard Holland
1f7355719d js emit 2024-05-24 10:07:05 +10:00
Richard Holland
7cc395b284 js float_set float_multiply float_mulratio float_negate float_compare float_sum float_sto float_sto_set float_invert float_divide float_one float_mantissa float_sign float_int float_log float_root 2024-05-24 10:07:05 +10:00
Richard Holland
a634318e8d js sto_validate sto_subfield sto_subarray sto_emplace sto_erase, compiling not tested 2024-05-24 10:07:05 +10:00
Denis Angell
82e754d180 Update quickjs.cmake 2024-05-24 10:07:05 +10:00
Denis Angell
9e72931bbb fix quickjs build 2024-05-24 10:07:05 +10:00
Richard Holland
842a0388d1 enable js slot apis 2024-05-24 10:07:05 +10:00
Richard Holland
280ba7d5de js slot slot_clear slot_count slot_set slot_size slot_subarray slot_subfield slot_type slot_float compiling not tested 2024-05-24 10:07:05 +10:00
Richard Holland
7b0bc67242 js state, state_foreign, state_set, state_foreign_set, compiling untested 2024-05-24 10:07:05 +10:00
Richard Holland
8e172e1846 js hook_param hook_param_set hook_skip hook_pos 2024-05-24 10:07:05 +10:00
Richard Holland
7497d619bf js hook_hash, hook_again, fee_base, ledger_seq, ledger_last_hash, ledger_last_time, ledger_nonce, ledger_keylet 2024-05-24 10:07:05 +10:00
Richard Holland
34a159b662 js etxn_fee_base/details/reserve/generation/nonce hook_account 2024-05-24 10:07:05 +10:00
Richard Holland
663910c78a js otxn_field otxn_generation otxn_burden etxn_burden 2024-05-24 10:07:05 +10:00
Richard Holland
40b9aa7aed js otxn_param otxn_slot 2024-05-24 10:07:05 +10:00
Richard Holland
ec7d603bf9 js otxn_type 2024-05-24 10:07:05 +10:00
Richard Holland
f9137000e3 js util_keylet untested compiling 2024-05-24 10:07:05 +10:00
Richard Holland
c3cf4b5999 start of js util_keylet 2024-05-24 10:07:05 +10:00
Richard Holland
6954abdd04 bug fix, debugging print 2024-05-24 10:07:05 +10:00
Richard Holland
38a4b3c1b9 js util_sha512h 2024-05-24 10:07:05 +10:00
Richard Holland
7e12b46169 js util_verify 2024-05-24 10:07:05 +10:00
Richard Holland
4e91d5887f js util_accid 2024-05-24 10:07:05 +10:00
Richard Holland
f051b87176 js util_raddr 2024-05-24 10:07:05 +10:00
Richard Holland
98d39db305 otxnid, trace apis for js hooks 2024-05-24 10:07:05 +10:00
Richard Holland
80df3adac7 hookjs rollback 2024-05-24 10:07:05 +10:00
Richard Holland
a2c3567caf first js hookapi working (accept) 2024-05-24 10:07:05 +10:00
Richard Holland
206773dcf4 debug 2024-05-24 10:07:05 +10:00
Richard Holland
54c00d0364 bug fixes 2024-05-24 10:07:05 +10:00
Richard Holland
71a6f9c4d5 compiling 2024-05-24 10:07:05 +10:00
Richard Holland
9ab33d580d more progress on jsvm 2024-05-24 10:07:05 +10:00
Richard Holland
0bd65bbb56 quickjs running inside xahaud 2024-05-24 10:07:05 +10:00
266 changed files with 146654 additions and 10565 deletions

3
.gitattributes vendored
View File

@@ -11,3 +11,6 @@ LICENSE binary
*.vcxproj text eol=crlf
*.props text eol=crlf
*.filters text eol=crlf
# Mark it as generated and folded out by default
src/test/app/SetJSHook_wasm.h linguist-generated=true

12
.githooks/pre-commit Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
# Pre-commit hook that runs the suspicious patterns check on staged files
# Get the repository's root directory
repo_root=$(git rev-parse --show-toplevel)
# Run the suspicious patterns script in pre-commit mode
"$repo_root/suspicious_patterns.sh" --pre-commit
# Exit with the same code as the script
exit $?

4
.githooks/setup.sh Normal file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
echo "Configuring git to use .githooks directory..."
git config core.hooksPath .githooks

View File

@@ -0,0 +1,31 @@
name: 'Configure ccache'
description: 'Sets up ccache with consistent configuration'
inputs:
max_size:
description: 'Maximum cache size'
required: false
default: '2G'
hash_dir:
description: 'Whether to include directory paths in hash'
required: false
default: 'true'
compiler_check:
description: 'How to check compiler for changes'
required: false
default: 'content'
runs:
using: 'composite'
steps:
- name: Configure ccache
shell: bash
run: |
mkdir -p ~/.ccache
export CONF_PATH="${CCACHE_CONFIGPATH:-${CCACHE_DIR:-$HOME/.ccache}/ccache.conf}"
mkdir -p $(dirname "$CONF_PATH")
echo "max_size = ${{ inputs.max_size }}" > "$CONF_PATH"
echo "hash_dir = ${{ inputs.hash_dir }}" >> "$CONF_PATH"
echo "compiler_check = ${{ inputs.compiler_check }}" >> "$CONF_PATH"
ccache -p # Print config for verification
ccache -z # Zero statistics before the build

View File

@@ -0,0 +1,108 @@
name: build
description: 'Builds the project with ccache integration'
inputs:
generator:
description: 'CMake generator to use'
required: true
configuration:
description: 'Build configuration (Debug, Release, etc.)'
required: true
build_dir:
description: 'Directory to build in'
required: false
default: '.build'
cc:
description: 'C compiler to use'
required: false
default: ''
cxx:
description: 'C++ compiler to use'
required: false
default: ''
compiler-id:
description: 'Unique identifier for compiler/version combination used for cache keys'
required: false
default: ''
cache_version:
description: 'Cache version for invalidation'
required: false
default: '1'
ccache_enabled:
description: 'Whether to use ccache'
required: false
default: 'true'
main_branch:
description: 'Main branch name for restore keys'
required: false
default: 'dev'
runs:
using: 'composite'
steps:
- name: Generate safe branch name
if: inputs.ccache_enabled == 'true'
id: safe-branch
shell: bash
run: |
SAFE_BRANCH=$(echo "${{ github.ref_name }}" | tr -c 'a-zA-Z0-9_.-' '-')
echo "name=${SAFE_BRANCH}" >> $GITHUB_OUTPUT
- name: Restore ccache directory
if: inputs.ccache_enabled == 'true'
id: ccache-restore
uses: actions/cache/restore@v4
with:
path: ~/.ccache
key: ${{ runner.os }}-ccache-v${{ inputs.cache_version }}-${{ inputs.compiler-id }}-${{ inputs.configuration }}-${{ steps.safe-branch.outputs.name }}
restore-keys: |
${{ runner.os }}-ccache-v${{ inputs.cache_version }}-${{ inputs.compiler-id }}-${{ inputs.configuration }}-${{ inputs.main_branch }}
${{ runner.os }}-ccache-v${{ inputs.cache_version }}-${{ inputs.compiler-id }}-${{ inputs.configuration }}-
${{ runner.os }}-ccache-v${{ inputs.cache_version }}-${{ inputs.compiler-id }}-
${{ runner.os }}-ccache-v${{ inputs.cache_version }}-
- name: Configure project
shell: bash
run: |
mkdir -p ${{ inputs.build_dir }}
cd ${{ inputs.build_dir }}
# Set compiler environment variables if provided
if [ -n "${{ inputs.cc }}" ]; then
export CC="${{ inputs.cc }}"
fi
if [ -n "${{ inputs.cxx }}" ]; then
export CXX="${{ inputs.cxx }}"
fi
# Configure ccache launcher args
CCACHE_ARGS=""
if [ "${{ inputs.ccache_enabled }}" = "true" ]; then
CCACHE_ARGS="-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
fi
# Run CMake configure
cmake .. \
-G "${{ inputs.generator }}" \
$CCACHE_ARGS \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE=${{ inputs.configuration }}
- name: Build project
shell: bash
run: |
cd ${{ inputs.build_dir }}
cmake --build . --config ${{ inputs.configuration }} --parallel $(nproc)
- name: Show ccache statistics
if: inputs.ccache_enabled == 'true'
shell: bash
run: ccache -s
- name: Save ccache directory
if: inputs.ccache_enabled == 'true'
uses: actions/cache/save@v4
with:
path: ~/.ccache
key: ${{ steps.ccache-restore.outputs.cache-primary-key }}

View File

@@ -0,0 +1,86 @@
name: dependencies
description: 'Installs build dependencies with caching'
inputs:
configuration:
description: 'Build configuration (Debug, Release, etc.)'
required: true
build_dir:
description: 'Directory to build dependencies in'
required: false
default: '.build'
compiler-id:
description: 'Unique identifier for compiler/version combination used for cache keys'
required: false
default: ''
cache_version:
description: 'Cache version for invalidation'
required: false
default: '1'
cache_enabled:
description: 'Whether to use caching'
required: false
default: 'true'
main_branch:
description: 'Main branch name for restore keys'
required: false
default: 'dev'
outputs:
cache-hit:
description: 'Whether there was a cache hit'
value: ${{ steps.cache-restore-conan.outputs.cache-hit }}
runs:
using: 'composite'
steps:
- name: Generate safe branch name
if: inputs.cache_enabled == 'true'
id: safe-branch
shell: bash
run: |
SAFE_BRANCH=$(echo "${{ github.ref_name }}" | tr -c 'a-zA-Z0-9_.-' '-')
echo "name=${SAFE_BRANCH}" >> $GITHUB_OUTPUT
- name: Restore Conan cache
if: inputs.cache_enabled == 'true'
id: cache-restore-conan
uses: actions/cache/restore@v4
with:
path: |
~/.conan
~/.conan2
key: ${{ runner.os }}-conan-v${{ inputs.cache_version }}-${{ inputs.compiler-id }}-${{ hashFiles('**/conanfile.txt', '**/conanfile.py') }}-${{ inputs.configuration }}
restore-keys: |
${{ runner.os }}-conan-v${{ inputs.cache_version }}-${{ inputs.compiler-id }}-${{ hashFiles('**/conanfile.txt', '**/conanfile.py') }}-
${{ runner.os }}-conan-v${{ inputs.cache_version }}-${{ inputs.compiler-id }}-
${{ runner.os }}-conan-v${{ inputs.cache_version }}-
- name: Export custom recipes
shell: bash
run: |
conan export external/snappy snappy/1.1.9@
conan export external/soci soci/4.0.3@
- name: Install dependencies
shell: bash
run: |
# Create build directory
mkdir -p ${{ inputs.build_dir }}
cd ${{ inputs.build_dir }}
# Install dependencies using conan
conan install \
--output-folder . \
--build missing \
--settings build_type=${{ inputs.configuration }} \
..
- name: Save Conan cache
if: inputs.cache_enabled == 'true' && steps.cache-restore-conan.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
~/.conan
~/.conan2
key: ${{ steps.cache-restore-conan.outputs.cache-primary-key }}

View File

@@ -1,38 +0,0 @@
name: Build using Docker
on:
push:
branches: [ "dev", "candidate", "release", "jshooks" ]
pull_request:
branches: [ "dev", "candidate", "release", "jshooks" ]
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
jobs:
checkout:
runs-on: [self-hosted, vanity]
steps:
- uses: actions/checkout@v4
with:
clean: false
checkpatterns:
runs-on: [self-hosted, vanity]
needs: checkout
steps:
- name: Check for suspicious patterns
run: /bin/bash suspicious_patterns.sh
build:
runs-on: [self-hosted, vanity]
needs: checkpatterns
steps:
- name: Build using Docker
run: /bin/bash release-builder.sh
tests:
runs-on: [self-hosted, vanity]
needs: build
steps:
- name: Unit tests
run: /bin/bash docker-unit-tests.sh

View File

@@ -4,21 +4,32 @@ on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
env:
CLANG_VERSION: 10
steps:
- uses: actions/checkout@v3
- name: Install clang-format
# - name: Install clang-format
# run: |
# codename=$( lsb_release --codename --short )
# sudo tee /etc/apt/sources.list.d/llvm.list >/dev/null <<EOF
# deb http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${CLANG_VERSION} main
# deb-src http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${CLANG_VERSION} main
# EOF
# wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add
# sudo apt-get update -y
# sudo apt-get install -y clang-format-${CLANG_VERSION}
# Temporary fix until this commit is merged
# https://github.com/XRPLF/rippled/commit/552377c76f55b403a1c876df873a23d780fcc81c
- name: Download and install clang-format
run: |
codename=$( lsb_release --codename --short )
sudo tee /etc/apt/sources.list.d/llvm.list >/dev/null <<EOF
deb http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${CLANG_VERSION} main
deb-src http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${CLANG_VERSION} main
EOF
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add
sudo apt-get update
sudo apt-get install clang-format-${CLANG_VERSION}
sudo apt-get update -y
sudo apt-get install -y libtinfo5
curl -LO https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz
tar -xf clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz
sudo mv clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04 /opt/clang-10
sudo ln -s /opt/clang-10/bin/clang-format /usr/local/bin/clang-format-10
- name: Format src/ripple
run: find src/ripple -type f \( -name '*.cpp' -o -name '*.h' -o -name '*.ipp' \) -print0 | xargs -0 clang-format-${CLANG_VERSION} -i
- name: Format src/test

View File

@@ -1,25 +0,0 @@
name: Build and publish Doxygen documentation
on:
push:
branches:
- dev
jobs:
job:
runs-on: ubuntu-latest
container:
image: docker://rippleci/rippled-ci-builder:2944b78d22db
steps:
- name: checkout
uses: actions/checkout@v2
- name: build
run: |
mkdir build
cd build
cmake -DBoost_NO_BOOST_CMAKE=ON ..
cmake --build . --target docs --parallel $(nproc)
- name: publish
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: build/docs/html

116
.github/workflows/xahau-ga-macos.yml vendored Normal file
View File

@@ -0,0 +1,116 @@
name: MacOS - GA Runner
on:
push:
branches: ["dev", "candidate", "release"]
pull_request:
branches: ["dev", "candidate", "release"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
strategy:
matrix:
generator:
- Ninja
configuration:
- Debug
runs-on: macos-15
env:
build_dir: .build
# Bump this number to invalidate all caches globally.
CACHE_VERSION: 1
MAIN_BRANCH_NAME: dev
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Conan
run: |
brew install conan@1
# Add Conan 1 to the PATH for this job
echo "$(brew --prefix conan@1)/bin" >> $GITHUB_PATH
- name: Install Coreutils
run: |
brew install coreutils
echo "Num proc: $(nproc)"
- name: Install Ninja
if: matrix.generator == 'Ninja'
run: brew install ninja
- name: Install Python
run: |
if which python3 > /dev/null 2>&1; then
echo "Python 3 executable exists"
python3 --version
else
brew install python@3.12
fi
# Create 'python' symlink if it doesn't exist (for tools expecting 'python')
if ! which python > /dev/null 2>&1; then
sudo ln -sf $(which python3) /usr/local/bin/python
fi
- name: Install CMake
run: |
if which cmake > /dev/null 2>&1; then
echo "cmake executable exists"
cmake --version
else
brew install cmake
fi
- name: Install ccache
run: brew install ccache
- name: Configure ccache
uses: ./.github/actions/xahau-configure-ccache
with:
max_size: 2G
hash_dir: true
compiler_check: content
- name: Check environment
run: |
echo "PATH:"
echo "${PATH}" | tr ':' '\n'
which python && python --version || echo "Python not found"
which conan && conan --version || echo "Conan not found"
which cmake && cmake --version || echo "CMake not found"
clang --version
ccache --version
echo "---- Full Environment ----"
env
- name: Configure Conan
run: |
conan profile new default --detect || true # Ignore error if profile exists
conan profile update settings.compiler.cppstd=20 default
- name: Install dependencies
uses: ./.github/actions/xahau-ga-dependencies
with:
configuration: ${{ matrix.configuration }}
build_dir: ${{ env.build_dir }}
compiler-id: clang
cache_version: ${{ env.CACHE_VERSION }}
main_branch: ${{ env.MAIN_BRANCH_NAME }}
- name: Build
uses: ./.github/actions/xahau-ga-build
with:
generator: ${{ matrix.generator }}
configuration: ${{ matrix.configuration }}
build_dir: ${{ env.build_dir }}
compiler-id: clang
cache_version: ${{ env.CACHE_VERSION }}
main_branch: ${{ env.MAIN_BRANCH_NAME }}
- name: Test
run: |
${{ env.build_dir }}/rippled --unittest --unittest-jobs $(nproc)

123
.github/workflows/xahau-ga-nix.yml vendored Normal file
View File

@@ -0,0 +1,123 @@
name: Nix - GA Runner
on:
push:
branches: ["dev", "candidate", "release"]
pull_request:
branches: ["dev", "candidate", "release"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-job:
runs-on: ubuntu-latest
outputs:
artifact_name: ${{ steps.set-artifact-name.outputs.artifact_name }}
strategy:
fail-fast: false
matrix:
compiler: [gcc]
configuration: [Debug]
include:
- compiler: gcc
cc: gcc-11
cxx: g++-11
compiler_id: gcc-11
env:
build_dir: .build
# Bump this number to invalidate all caches globally.
CACHE_VERSION: 1
MAIN_BRANCH_NAME: dev
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y ninja-build ${{ matrix.cc }} ${{ matrix.cxx }} ccache
# Install specific Conan version needed
pip install --upgrade "conan<2"
- name: Configure ccache
uses: ./.github/actions/xahau-configure-ccache
with:
max_size: 2G
hash_dir: true
compiler_check: content
- name: Configure Conan
run: |
conan profile new default --detect || true # Ignore error if profile exists
conan profile update settings.compiler.cppstd=20 default
conan profile update settings.compiler=${{ matrix.compiler }} default
conan profile update settings.compiler.libcxx=libstdc++11 default
conan profile update env.CC=/usr/bin/${{ matrix.cc }} default
conan profile update env.CXX=/usr/bin/${{ matrix.cxx }} default
conan profile update conf.tools.build:compiler_executables='{"c": "/usr/bin/${{ matrix.cc }}", "cpp": "/usr/bin/${{ matrix.cxx }}"}' default
# Set correct compiler version based on matrix.compiler
if [ "${{ matrix.compiler }}" = "gcc" ]; then
conan profile update settings.compiler.version=11 default
elif [ "${{ matrix.compiler }}" = "clang" ]; then
conan profile update settings.compiler.version=14 default
fi
# Display profile for verification
conan profile show default
- name: Check environment
run: |
echo "PATH:"
echo "${PATH}" | tr ':' '\n'
which conan && conan --version || echo "Conan not found"
which cmake && cmake --version || echo "CMake not found"
which ${{ matrix.cc }} && ${{ matrix.cc }} --version || echo "${{ matrix.cc }} not found"
which ${{ matrix.cxx }} && ${{ matrix.cxx }} --version || echo "${{ matrix.cxx }} not found"
which ccache && ccache --version || echo "ccache not found"
echo "---- Full Environment ----"
env
- name: Install dependencies
uses: ./.github/actions/xahau-ga-dependencies
with:
configuration: ${{ matrix.configuration }}
build_dir: ${{ env.build_dir }}
compiler-id: ${{ matrix.compiler_id }}
cache_version: ${{ env.CACHE_VERSION }}
main_branch: ${{ env.MAIN_BRANCH_NAME }}
- name: Build
uses: ./.github/actions/xahau-ga-build
with:
generator: Ninja
configuration: ${{ matrix.configuration }}
build_dir: ${{ env.build_dir }}
cc: ${{ matrix.cc }}
cxx: ${{ matrix.cxx }}
compiler-id: ${{ matrix.compiler_id }}
cache_version: ${{ env.CACHE_VERSION }}
main_branch: ${{ env.MAIN_BRANCH_NAME }}
- name: Set artifact name
id: set-artifact-name
run: |
ARTIFACT_NAME="build-output-nix-${{ github.run_id }}-${{ matrix.compiler }}-${{ matrix.configuration }}"
echo "artifact_name=${ARTIFACT_NAME}" >> "$GITHUB_OUTPUT"
echo "Using artifact name: ${ARTIFACT_NAME}"
- name: Debug build directory
run: |
echo "Checking build directory contents: ${{ env.build_dir }}"
ls -la ${{ env.build_dir }} || echo "Build directory not found or empty"
- name: Run tests
run: |
# Ensure the binary exists before trying to run
if [ -f "${{ env.build_dir }}/rippled" ]; then
${{ env.build_dir }}/rippled --unittest --unittest-jobs $(nproc)
else
echo "Error: rippled executable not found in ${{ env.build_dir }}"
exit 1
fi

View File

@@ -0,0 +1,85 @@
name: Release - SH Runner
on:
push:
branches: [ "dev", "candidate", "release", "jshooks"]
pull_request:
branches: [ "dev", "candidate", "release", "jshooks"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
DEBUG_CONTAINERS: 1
REMOVE_CONTAINERS: 0
jobs:
build-and-test:
runs-on: [self-hosted, vanity]
steps:
- name: Prepare workspace
run: |
SAFE_BRANCH=$(echo "${{ github.ref_name }}" | sed -e 's/[^a-zA-Z0-9._-]/-/g')
CHECKOUT_PATH="${SAFE_BRANCH}-${{ github.sha }}"
echo "CHECKOUT_PATH=${CHECKOUT_PATH}" >> $GITHUB_ENV
mkdir -p "$CHECKOUT_PATH"
- name: Checkout code
uses: actions/checkout@v4
with:
path: ${{ env.CHECKOUT_PATH }}
clean: true
fetch-depth: 2
- name: Set Cleanup Script Path
run: |
echo "JOB_CLEANUP_SCRIPT=$(mktemp)" >> $GITHUB_ENV
- name: Build using Docker
working-directory: ${{ env.CHECKOUT_PATH }}
run: /bin/bash release-builder.sh
- name: Stop Container (Cleanup after build)
if: always()
working-directory: ${{ env.CHECKOUT_PATH }}
run: |
echo "Running cleanup script: $JOB_CLEANUP_SCRIPT"
/bin/bash -e -x "$JOB_CLEANUP_SCRIPT"
CLEANUP_EXIT_CODE=$?
if [[ "$CLEANUP_EXIT_CODE" -eq 0 ]]; then
echo "Cleanup script succeeded."
rm -f "$JOB_CLEANUP_SCRIPT"
echo "Cleanup script removed."
else
echo "⚠️ Cleanup script failed! Keeping for debugging: $JOB_CLEANUP_SCRIPT"
fi
if [[ "${DEBUG_CONTAINERS}" == "1" ]]; then
echo "🔍 Checking for leftover containers..."
BUILD_CONTAINERS=$(docker ps --format '{{.Names}}' | grep '^xahaud_cached_builder' || echo "")
CONTAINER_NAME="xahaud_cached_builder_${{ github.workflow }}-${{ github.ref_name }}"
if [[ -n "$BUILD_CONTAINERS" && "${REMOVE_CONTAINERS}" == "1" ]]; then
echo "⚠️ WARNING: Some build containers are still running"
echo "$BUILD_CONTAINERS"
echo "Attempting to stop build containers.."
echo "Stopping container: $CONTAINER_NAME"
docker stop "$CONTAINER_NAME" || echo "Failed to stop container: $CONTAINER_NAME"
echo "Removing container: $CONTAINER_NAME"
docker rm -f "$CONTAINER_NAME" || echo "Failed to remove container: $CONTAINER_NAME"
echo "✅ Build container stopped and removed"
else
echo "✅ No build containers found"
fi
fi
- name: Run unit tests
working-directory: ${{ env.CHECKOUT_PATH }}
run: /bin/bash docker-unit-tests.sh
- name: Cleanup workspace
if: always()
run: |
echo "Cleaning workspace for ${CHECKOUT_PATH}"
rm -rf "${{ github.workspace }}/${CHECKOUT_PATH}"

4
.gitignore vendored
View File

@@ -114,3 +114,7 @@ pkg_out
pkg
CMakeUserPresets.json
bld.rippled/
# binary
qjsc
generated

442
BUILD.md Normal file
View File

@@ -0,0 +1,442 @@
> These instructions assume you have a C++ development environment ready
> with Git, Python, Conan, CMake, and a C++ compiler. For help setting one up
> on Linux, macOS, or Windows, see [our guide](./docs/build/environment.md).
>
> These instructions also assume a basic familiarity with Conan and CMake.
> If you are unfamiliar with Conan,
> you can read our [crash course](./docs/build/conan.md)
> or the official [Getting Started][3] walkthrough.
## Branches
For a stable release, choose the `master` branch or one of the [tagged
releases](https://github.com/ripple/rippled/releases).
```
git checkout master
```
For the latest release candidate, choose the `release` branch.
```
git checkout release
```
For the latest set of untested features, or to contribute, choose the `develop`
branch.
```
git checkout develop
```
## Minimum Requirements
- [Python 3.7](https://www.python.org/downloads/)
- [Conan 1.55](https://conan.io/downloads.html)
- [CMake 3.16](https://cmake.org/download/)
`rippled` is written in the C++20 dialect and includes the `<concepts>` header.
The [minimum compiler versions][2] required are:
| Compiler | Version |
|-------------|---------|
| GCC | 10 |
| Clang | 13 |
| Apple Clang | 13.1.6 |
| MSVC | 19.23 |
We don't recommend Windows for `rippled` production at this time. As of
January 2023, Ubuntu has the highest level of quality assurance, testing,
and support.
Windows developers should use Visual Studio 2019. `rippled` isn't
compatible with [Boost](https://www.boost.org/) 1.78 or 1.79, and Conan
can't build earlier Boost versions.
**Note:** 32-bit Windows development isn't supported.
## Steps
### Set Up Conan
1. (Optional) If you've never used Conan, use autodetect to set up a default profile.
```
conan profile new default --detect
```
2. Update the compiler settings.
```
conan profile update settings.compiler.cppstd=20 default
```
Linux developers will commonly have a default Conan [profile][] that compiles
with GCC and links with libstdc++.
If you are linking with libstdc++ (see profile setting `compiler.libcxx`),
then you will need to choose the `libstdc++11` ABI.
```
conan profile update settings.compiler.libcxx=libstdc++11 default
```
On Windows, you should use the x64 native build tools.
An easy way to do that is to run the shortcut "x64 Native Tools Command
Prompt" for the version of Visual Studio that you have installed.
Windows developers must also build `rippled` and its dependencies for the x64
architecture.
```
conan profile update settings.arch=x86_64 default
```
3. (Optional) If you have multiple compilers installed on your platform,
make sure that Conan and CMake select the one you want to use.
This setting will set the correct variables (`CMAKE_<LANG>_COMPILER`)
in the generated CMake toolchain file.
```
conan profile update 'conf.tools.build:compiler_executables={"c": "<path>", "cpp": "<path>"}' default
```
It should choose the compiler for dependencies as well,
but not all of them have a Conan recipe that respects this setting (yet).
For the rest, you can set these environment variables:
```
conan profile update env.CC=<path> default
conan profile update env.CXX=<path> default
```
4. Export our [Conan recipe for Snappy](./external/snappy).
It doesn't explicitly link the C++ standard library,
which allows you to statically link it with GCC, if you want.
```
conan export external/snappy snappy/1.1.9@
```
5. Export our [Conan recipe for SOCI](./external/soci).
It patches their CMake to correctly import its dependencies.
```
conan export external/soci soci/4.0.3@
```
### Build and Test
1. Create a build directory and move into it.
```
mkdir .build
cd .build
```
You can use any directory name. Conan treats your working directory as an
install folder and generates files with implementation details.
You don't need to worry about these files, but make sure to change
your working directory to your build directory before calling Conan.
**Note:** You can specify a directory for the installation files by adding
the `install-folder` or `-if` option to every `conan install` command
in the next step.
2. Generate CMake files for every configuration you want to build.
```
conan install .. --output-folder . --build missing --settings build_type=Release
conan install .. --output-folder . --build missing --settings build_type=Debug
```
For a single-configuration generator, e.g. `Unix Makefiles` or `Ninja`,
you only need to run this command once.
For a multi-configuration generator, e.g. `Visual Studio`, you may want to
run it more than once.
Each of these commands should also have a different `build_type` setting.
A second command with the same `build_type` setting will overwrite the files
generated by the first. You can pass the build type on the command line with
`--settings build_type=$BUILD_TYPE` or in the profile itself,
under the section `[settings]` with the key `build_type`.
If you are using a Microsoft Visual C++ compiler,
then you will need to ensure consistency between the `build_type` setting
and the `compiler.runtime` setting.
When `build_type` is `Release`, `compiler.runtime` should be `MT`.
When `build_type` is `Debug`, `compiler.runtime` should be `MTd`.
```
conan install .. --output-folder . --build missing --settings build_type=Release --settings compiler.runtime=MT
conan install .. --output-folder . --build missing --settings build_type=Debug --settings compiler.runtime=MTd
```
3. Configure CMake and pass the toolchain file generated by Conan, located at
`$OUTPUT_FOLDER/build/generators/conan_toolchain.cmake`.
Single-config generators:
```
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
```
Pass the CMake variable [`CMAKE_BUILD_TYPE`][build_type]
and make sure it matches the `build_type` setting you chose in the previous
step.
Multi-config gnerators:
```
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake ..
```
**Note:** You can pass build options for `rippled` in this step.
4. Build `rippled`.
For a single-configuration generator, it will build whatever configuration
you passed for `CMAKE_BUILD_TYPE`. For a multi-configuration generator,
you must pass the option `--config` to select the build configuration.
Single-config generators:
```
cmake --build .
```
Multi-config generators:
```
cmake --build . --config Release
cmake --build . --config Debug
```
5. Test rippled.
Single-config generators:
```
./rippled --unittest
```
Multi-config generators:
```
./Release/rippled --unittest
./Debug/rippled --unittest
```
The location of `rippled` in your build directory depends on your CMake
generator. Pass `--help` to see the rest of the command line options.
## Options
| Option | Default Value | Description |
| --- | ---| ---|
| `assert` | OFF | Enable assertions.
| `reporting` | OFF | Build the reporting mode feature. |
| `tests` | ON | Build tests. |
| `unity` | ON | Configure a unity build. |
| `san` | N/A | Enable a sanitizer with Clang. Choices are `thread` and `address`. |
[Unity builds][5] may be faster for the first build
(at the cost of much more memory) since they concatenate sources into fewer
translation units. Non-unity builds may be faster for incremental builds,
and can be helpful for detecting `#include` omissions.
## Troubleshooting
### Conan
If you have trouble building dependencies after changing Conan settings,
try removing the Conan cache.
```
rm -rf ~/.conan/data
```
### no std::result_of
If your compiler version is recent enough to have removed `std::result_of` as
part of C++20, e.g. Apple Clang 15.0, then you might need to add a preprocessor
definition to your build.
```
conan profile update 'options.boost:extra_b2_flags="define=BOOST_ASIO_HAS_STD_INVOKE_RESULT"' default
conan profile update 'env.CFLAGS="-DBOOST_ASIO_HAS_STD_INVOKE_RESULT"' default
conan profile update 'env.CXXFLAGS="-DBOOST_ASIO_HAS_STD_INVOKE_RESULT"' default
conan profile update 'conf.tools.build:cflags+=["-DBOOST_ASIO_HAS_STD_INVOKE_RESULT"]' default
conan profile update 'conf.tools.build:cxxflags+=["-DBOOST_ASIO_HAS_STD_INVOKE_RESULT"]' default
```
### recompile with -fPIC
If you get a linker error suggesting that you recompile Boost with
position-independent code, such as:
```
/usr/bin/ld.gold: error: /home/username/.conan/data/boost/1.77.0/_/_/package/.../lib/libboost_container.a(alloc_lib.o):
requires unsupported dynamic reloc 11; recompile with -fPIC
```
Conan most likely downloaded a bad binary distribution of the dependency.
This seems to be a [bug][1] in Conan just for Boost 1.77.0 compiled with GCC
for Linux. The solution is to build the dependency locally by passing
`--build boost` when calling `conan install`.
```
/usr/bin/ld.gold: error: /home/username/.conan/data/boost/1.77.0/_/_/package/dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978/lib/libboost_container.a(alloc_lib.o): requires unsupported dynamic reloc 11; recompile with -fPIC
```
## Add a Dependency
If you want to experiment with a new package, follow these steps:
1. Search for the package on [Conan Center](https://conan.io/center/).
2. Modify [`conanfile.py`](./conanfile.py):
- Add a version of the package to the `requires` property.
- Change any default options for the package by adding them to the
`default_options` property (with syntax `'$package:$option': $value`).
3. Modify [`CMakeLists.txt`](./CMakeLists.txt):
- Add a call to `find_package($package REQUIRED)`.
- Link a library from the package to the target `ripple_libs`
(search for the existing call to `target_link_libraries(ripple_libs INTERFACE ...)`).
4. Start coding! Don't forget to include whatever headers you need from the package.
## A crash course in CMake and Conan
To better understand how to use Conan,
we should first understand _why_ we use Conan,
and to understand that,
we need to understand how we use CMake.
### CMake
Technically, you don't need CMake to build this project.
You could manually compile every translation unit into an object file,
using the right compiler options,
and then manually link all those objects together,
using the right linker options.
However, that is very tedious and error-prone,
which is why we lean on tools like CMake.
We have written CMake configuration files
([`CMakeLists.txt`](./CMakeLists.txt) and friends)
for this project so that CMake can be used to correctly compile and link
all of the translation units in it.
Or rather, CMake will generate files for a separate build system
(e.g. Make, Ninja, Visual Studio, Xcode, etc.)
that compile and link all of the translation units.
Even then, CMake has parameters, some of which are platform-specific.
In CMake's parlance, parameters are specially-named **variables** like
[`CMAKE_BUILD_TYPE`][build_type] or
[`CMAKE_MSVC_RUNTIME_LIBRARY`][runtime].
Parameters include:
- what build system to generate files for
- where to find the compiler and linker
- where to find dependencies, e.g. libraries and headers
- how to link dependencies, e.g. any special compiler or linker flags that
need to be used with them, including preprocessor definitions
- how to compile translation units, e.g. with optimizations, debug symbols,
position-independent code, etc.
- on Windows, which runtime library to link with
For some of these parameters, like the build system and compiler,
CMake goes through a complicated search process to choose default values.
For others, like the dependencies,
_we_ had written in the CMake configuration files of this project
our own complicated process to choose defaults.
For most developers, things "just worked"... until they didn't, and then
you were left trying to debug one of these complicated processes, instead of
choosing and manually passing the parameter values yourself.
You can pass every parameter to CMake on the command line,
but writing out these parameters every time we want to configure CMake is
a pain.
Most humans prefer to put them into a configuration file, once, that
CMake can read every time it is configured.
For CMake, that file is a [toolchain file][toolchain].
### Conan
These next few paragraphs on Conan are going to read much like the ones above
for CMake.
Technically, you don't need Conan to build this project.
You could manually download, configure, build, and install all of the
dependencies yourself, and then pass all of the parameters necessary for
CMake to link to those dependencies.
To guarantee ABI compatibility, you must be sure to use the same set of
compiler and linker options for all dependencies _and_ this project.
However, that is very tedious and error-prone, which is why we lean on tools
like Conan.
We have written a Conan configuration file ([`conanfile.py`](./conanfile.py))
so that Conan can be used to correctly download, configure, build, and install
all of the dependencies for this project,
using a single set of compiler and linker options for all of them.
It generates files that contain almost all of the parameters that CMake
expects.
Those files include:
- A single toolchain file.
- For every dependency, a CMake [package configuration file][pcf],
[package version file][pvf], and for every build type, a package
targets file.
Together, these files implement version checking and define `IMPORTED`
targets for the dependencies.
The toolchain file itself amends the search path
([`CMAKE_PREFIX_PATH`][prefix_path]) so that [`find_package()`][find_package]
will [discover][search] the generated package configuration files.
**Nearly all we must do to properly configure CMake is pass the toolchain
file.**
What CMake parameters are left out?
You'll still need to pick a build system generator,
and if you choose a single-configuration generator,
you'll need to pass the `CMAKE_BUILD_TYPE`,
which should match the `build_type` setting you gave to Conan.
Even then, Conan has parameters, some of which are platform-specific.
In Conan's parlance, parameters are either settings or options.
**Settings** are shared by all packages, e.g. the build type.
**Options** are specific to a given package, e.g. whether to build and link
OpenSSL as a shared library.
For settings, Conan goes through a complicated search process to choose
defaults.
For options, each package recipe defines its own defaults.
You can pass every parameter to Conan on the command line,
but it is more convenient to put them in a [profile][profile].
**All we must do to properly configure Conan is edit and pass the profile.**
[1]: https://github.com/conan-io/conan-center-index/issues/13168
[5]: https://en.wikipedia.org/wiki/Unity_build
[build_type]: https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
[runtime]: https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
[toolchain]: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html
[pcf]: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#package-configuration-file
[pvf]: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#package-version-file
[find_package]: https://cmake.org/cmake/help/latest/command/find_package.html
[search]: https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure
[prefix_path]: https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html
[profile]: https://docs.conan.io/en/latest/reference/profiles.html

View File

@@ -23,6 +23,11 @@ else()
message(STATUS "ACL not found, continuing without ACL support")
endif()
add_library(libxrpl INTERFACE)
target_link_libraries(libxrpl INTERFACE xrpl_core)
add_library(xrpl::libxrpl ALIAS libxrpl)
#[===============================[
beast/legacy FILES:
TODO: review these sources for removal or replacement
@@ -144,10 +149,11 @@ target_link_libraries (xrpl_core
PUBLIC
OpenSSL::Crypto
Ripple::boost
NIH::WasmEdge
wasmedge::wasmedge
NIH::quickjs
Ripple::syslibs
NIH::secp256k1
NIH::ed25519-donna
secp256k1::secp256k1
ed25519::ed25519
date::date
Ripple::opts)
#[=================================[
@@ -435,6 +441,7 @@ target_sources (rippled PRIVATE
src/ripple/app/tx/impl/CashCheck.cpp
src/ripple/app/tx/impl/Change.cpp
src/ripple/app/tx/impl/ClaimReward.cpp
src/ripple/app/tx/impl/Clawback.cpp
src/ripple/app/tx/impl/CreateCheck.cpp
src/ripple/app/tx/impl/CreateOffer.cpp
src/ripple/app/tx/impl/CreateTicket.cpp
@@ -456,6 +463,7 @@ target_sources (rippled PRIVATE
src/ripple/app/tx/impl/Remit.cpp
src/ripple/app/tx/impl/SetAccount.cpp
src/ripple/app/tx/impl/SetHook.cpp
src/ripple/app/tx/impl/SetRemarks.cpp
src/ripple/app/tx/impl/SetRegularKey.cpp
src/ripple/app/tx/impl/SetSignerList.cpp
src/ripple/app/tx/impl/SetTrust.cpp
@@ -606,6 +614,7 @@ target_sources (rippled PRIVATE
src/ripple/rpc/handlers/BlackList.cpp
src/ripple/rpc/handlers/BookOffers.cpp
src/ripple/rpc/handlers/CanDelete.cpp
src/ripple/rpc/handlers/Catalogue.cpp
src/ripple/rpc/handlers/Connect.cpp
src/ripple/rpc/handlers/ConsensusInfo.cpp
src/ripple/rpc/handlers/CrawlShards.cpp
@@ -661,6 +670,7 @@ target_sources (rippled PRIVATE
src/ripple/rpc/handlers/ValidatorListSites.cpp
src/ripple/rpc/handlers/Validators.cpp
src/ripple/rpc/handlers/WalletPropose.cpp
src/ripple/rpc/handlers/Catalogue.cpp
src/ripple/rpc/impl/DeliveredAmount.cpp
src/ripple/rpc/impl/Handler.cpp
src/ripple/rpc/impl/LegacyPathFind.cpp
@@ -713,6 +723,7 @@ if (tests)
src/test/app/BaseFee_test.cpp
src/test/app/Check_test.cpp
src/test/app/ClaimReward_test.cpp
src/test/app/Clawback_test.cpp
src/test/app/CrossingLimits_test.cpp
src/test/app/DeliverMin_test.cpp
src/test/app/DepositAuth_test.cpp
@@ -743,6 +754,7 @@ if (tests)
src/test/app/Path_test.cpp
src/test/app/PayChan_test.cpp
src/test/app/PayStrand_test.cpp
src/test/app/PreviousTxn_test.cpp
src/test/app/PseudoTx_test.cpp
src/test/app/RCLCensorshipDetector_test.cpp
src/test/app/RCLValidations_test.cpp
@@ -750,7 +762,10 @@ if (tests)
src/test/app/Remit_test.cpp
src/test/app/SHAMapStore_test.cpp
src/test/app/SetAuth_test.cpp
src/test/app/SetHook_test.cpp
src/test/app/SetHookTSH_test.cpp
src/test/app/SetRegularKey_test.cpp
src/test/app/SetRemarks_test.cpp
src/test/app/SetTrust_test.cpp
src/test/app/Taker_test.cpp
src/test/app/TheoreticalQuality_test.cpp
@@ -764,6 +779,7 @@ if (tests)
src/test/app/ValidatorList_test.cpp
src/test/app/ValidatorSite_test.cpp
src/test/app/SetHook_test.cpp
src/test/app/SetJSHook_test.cpp
src/test/app/SetHookTSH_test.cpp
src/test/app/Wildcard_test.cpp
src/test/app/XahauGenesis_test.cpp
@@ -898,11 +914,13 @@ if (tests)
src/test/jtx/impl/rate.cpp
src/test/jtx/impl/regkey.cpp
src/test/jtx/impl/reward.cpp
src/test/jtx/impl/remarks.cpp
src/test/jtx/impl/remit.cpp
src/test/jtx/impl/sendmax.cpp
src/test/jtx/impl/seq.cpp
src/test/jtx/impl/sig.cpp
src/test/jtx/impl/tag.cpp
src/test/jtx/impl/TestHelpers.cpp
src/test/jtx/impl/ticket.cpp
src/test/jtx/impl/token.cpp
src/test/jtx/impl/trust.cpp
@@ -995,6 +1013,7 @@ if (tests)
src/test/rpc/AccountTx_test.cpp
src/test/rpc/AmendmentBlocked_test.cpp
src/test/rpc/Book_test.cpp
src/test/rpc/Catalogue_test.cpp
src/test/rpc/DepositAuthorized_test.cpp
src/test/rpc/DeliveredAmount_test.cpp
src/test/rpc/Feature_test.cpp

View File

@@ -1,6 +1,13 @@
#[===================================================================[
docs target (optional)
#]===================================================================]
# Early return if the `docs` directory is missing,
# e.g. when we are building a Conan package.
if(NOT EXISTS docs)
return()
endif()
if (tests)
find_package (Doxygen)
if (NOT TARGET Doxygen::doxygen)

View File

@@ -4,7 +4,7 @@
install (
TARGETS
ed25519-donna
quickjs
common
opts
ripple_syslibs
@@ -16,17 +16,6 @@ install (
RUNTIME DESTINATION bin
INCLUDES DESTINATION include)
if(${INSTALL_SECP256K1})
install (
TARGETS
secp256k1
EXPORT RippleExports
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include)
endif()
install (EXPORT RippleExports
FILE RippleTargets.cmake
NAMESPACE Ripple::

View File

@@ -14,7 +14,7 @@ if (is_multiconfig)
file(GLOB md_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS
*.md)
LIST(APPEND all_sources ${md_files})
foreach (_target secp256k1 ed25519-donna pbufs xrpl_core rippled)
foreach (_target secp256k1::secp256k1 ed25519::ed25519 pbufs xrpl_core rippled)
get_target_property (_type ${_target} TYPE)
if(_type STREQUAL "INTERFACE_LIBRARY")
continue()

View File

@@ -0,0 +1,52 @@
find_package(Boost 1.83 REQUIRED
COMPONENTS
chrono
container
context
coroutine
date_time
filesystem
program_options
regex
system
thread
)
add_library(ripple_boost INTERFACE)
add_library(Ripple::boost ALIAS ripple_boost)
if(XCODE)
target_include_directories(ripple_boost BEFORE INTERFACE ${Boost_INCLUDE_DIRS})
target_compile_options(ripple_boost INTERFACE --system-header-prefix="boost/")
else()
target_include_directories(ripple_boost SYSTEM BEFORE INTERFACE ${Boost_INCLUDE_DIRS})
endif()
target_link_libraries(ripple_boost
INTERFACE
Boost::boost
Boost::chrono
Boost::container
Boost::coroutine
Boost::date_time
Boost::filesystem
Boost::program_options
Boost::regex
Boost::system
Boost::iostreams
Boost::thread)
if(Boost_COMPILER)
target_link_libraries(ripple_boost INTERFACE Boost::disable_autolinking)
endif()
if(san AND is_clang)
# TODO: gcc does not support -fsanitize-blacklist...can we do something else
# for gcc ?
if(NOT Boost_INCLUDE_DIRS AND TARGET Boost::headers)
get_target_property(Boost_INCLUDE_DIRS Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
endif()
message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt "src:${Boost_INCLUDE_DIRS}/*")
target_compile_options(opts
INTERFACE
# ignore boost headers for sanitizing
-fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt)
endif()

View File

@@ -0,0 +1,22 @@
find_package(Protobuf 3.8)
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/proto_gen)
set(ccbd ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_BINARY_DIR}/proto_gen)
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS src/ripple/proto/ripple.proto)
set(CMAKE_CURRENT_BINARY_DIR ${ccbd})
add_library(pbufs STATIC ${PROTO_SRCS} ${PROTO_HDRS})
target_include_directories(pbufs SYSTEM PUBLIC
${CMAKE_BINARY_DIR}/proto_gen
${CMAKE_BINARY_DIR}/proto_gen/src/ripple/proto
)
target_link_libraries(pbufs protobuf::libprotobuf)
target_compile_options(pbufs
PUBLIC
$<$<BOOL:${XCODE}>:
--system-header-prefix="google/protobuf"
-Wno-deprecated-dynamic-exception-spec
>
)
add_library(Ripple::pbufs ALIAS pbufs)

View File

@@ -0,0 +1,62 @@
find_package(gRPC 1.23)
#[=================================[
generate protobuf sources for
grpc defs and bundle into a
static lib
#]=================================]
set(GRPC_GEN_DIR "${CMAKE_BINARY_DIR}/proto_gen_grpc")
file(MAKE_DIRECTORY ${GRPC_GEN_DIR})
set(GRPC_PROTO_SRCS)
set(GRPC_PROTO_HDRS)
set(GRPC_PROTO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/src/ripple/proto/org")
file(GLOB_RECURSE GRPC_DEFINITION_FILES LIST_DIRECTORIES false "${GRPC_PROTO_ROOT}/*.proto")
foreach(file ${GRPC_DEFINITION_FILES})
get_filename_component(_abs_file ${file} ABSOLUTE)
get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
get_filename_component(_basename ${file} NAME_WE)
get_filename_component(_proto_inc ${GRPC_PROTO_ROOT} DIRECTORY) # updir one level
file(RELATIVE_PATH _rel_root_file ${_proto_inc} ${_abs_file})
get_filename_component(_rel_root_dir ${_rel_root_file} DIRECTORY)
file(RELATIVE_PATH _rel_dir ${CMAKE_CURRENT_SOURCE_DIR} ${_abs_dir})
set(src_1 "${GRPC_GEN_DIR}/${_rel_root_dir}/${_basename}.grpc.pb.cc")
set(src_2 "${GRPC_GEN_DIR}/${_rel_root_dir}/${_basename}.pb.cc")
set(hdr_1 "${GRPC_GEN_DIR}/${_rel_root_dir}/${_basename}.grpc.pb.h")
set(hdr_2 "${GRPC_GEN_DIR}/${_rel_root_dir}/${_basename}.pb.h")
add_custom_command(
OUTPUT ${src_1} ${src_2} ${hdr_1} ${hdr_2}
COMMAND protobuf::protoc
ARGS --grpc_out=${GRPC_GEN_DIR}
--cpp_out=${GRPC_GEN_DIR}
--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
-I ${_proto_inc} -I ${_rel_dir}
${_abs_file}
DEPENDS ${_abs_file} protobuf::protoc gRPC::grpc_cpp_plugin
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Running gRPC C++ protocol buffer compiler on ${file}"
VERBATIM)
set_source_files_properties(${src_1} ${src_2} ${hdr_1} ${hdr_2} PROPERTIES GENERATED TRUE)
list(APPEND GRPC_PROTO_SRCS ${src_1} ${src_2})
list(APPEND GRPC_PROTO_HDRS ${hdr_1} ${hdr_2})
endforeach()
add_library(grpc_pbufs STATIC ${GRPC_PROTO_SRCS} ${GRPC_PROTO_HDRS})
#target_include_directories(grpc_pbufs PRIVATE src)
target_include_directories(grpc_pbufs SYSTEM PUBLIC ${GRPC_GEN_DIR})
target_link_libraries(grpc_pbufs
"gRPC::grpc++"
# libgrpc is missing references.
absl::random_random
)
target_compile_options(grpc_pbufs
PRIVATE
$<$<BOOL:${MSVC}>:-wd4065>
$<$<NOT:$<BOOL:${MSVC}>>:-Wno-deprecated-declarations>
PUBLIC
$<$<BOOL:${MSVC}>:-wd4996>
$<$<BOOL:${XCODE}>:
--system-header-prefix="google/protobuf"
-Wno-deprecated-dynamic-exception-spec
>)
add_library(Ripple::grpc_pbufs ALIAS grpc_pbufs)

View File

@@ -1,14 +1,16 @@
#[===================================================================[
NIH dep: boost
#]===================================================================]
if((NOT DEFINED BOOST_ROOT) AND(DEFINED ENV{BOOST_ROOT}))
set(BOOST_ROOT $ENV{BOOST_ROOT})
endif()
if((NOT DEFINED BOOST_LIBRARYDIR) AND(DEFINED ENV{BOOST_LIBRARYDIR}))
set(BOOST_LIBRARYDIR $ENV{BOOST_LIBRARYDIR})
endif()
file(TO_CMAKE_PATH "${BOOST_ROOT}" BOOST_ROOT)
if(WIN32 OR CYGWIN)
# Workaround for MSVC having two boost versions - x86 and x64 on same PC in stage folders
if(DEFINED BOOST_ROOT)
if((NOT DEFINED BOOST_LIBRARYDIR) AND (DEFINED BOOST_ROOT))
if(IS_DIRECTORY ${BOOST_ROOT}/stage64/lib)
set(BOOST_LIBRARYDIR ${BOOST_ROOT}/stage64/lib)
elseif(IS_DIRECTORY ${BOOST_ROOT}/stage/lib)
@@ -55,6 +57,7 @@ find_package(Boost 1.86 REQUIRED
program_options
regex
system
iostreams
thread)
add_library(ripple_boost INTERFACE)
@@ -74,6 +77,7 @@ target_link_libraries(ripple_boost
Boost::coroutine
Boost::date_time
Boost::filesystem
Boost::iostreams
Boost::program_options
Boost::regex
Boost::system

View File

@@ -248,6 +248,7 @@ include(FindPackageHandleStandardArgs)
# Save project's policies
cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW) # if IN_LIST
#cmake_policy(SET CMP0144 NEW)
#-------------------------------------------------------------------------------
# Before we go searching, check whether a boost cmake package is available, unless
@@ -969,7 +970,24 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
endif()
if(NOT Boost_VERSION_STRING VERSION_LESS 1.77.0)
# Special handling for Boost 1.86.0 and higher
if(NOT Boost_VERSION_STRING VERSION_LESS 1.86.0)
# Explicitly set these for Boost 1.86
set(_Boost_IOSTREAMS_DEPENDENCIES "") # No dependencies for iostreams in 1.86
# Debug output to help diagnose the issue
if(Boost_DEBUG)
message(STATUS "Using special dependency settings for Boost 1.86.0+")
message(STATUS "Component: ${component}, uppercomponent: ${uppercomponent}")
message(STATUS "Boost_VERSION_STRING: ${Boost_VERSION_STRING}")
message(STATUS "BOOST_ROOT: $ENV{BOOST_ROOT}")
message(STATUS "BOOST_LIBRARYDIR: $ENV{BOOST_LIBRARYDIR}")
endif()
endif()
# Only show warning for versions beyond what we've defined
if(NOT Boost_VERSION_STRING VERSION_LESS 1.87.0)
message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
endif()
endif()
@@ -1879,6 +1897,18 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS})
list(INSERT _boost_LIBRARY_SEARCH_DIRS_RELEASE 0 ${Boost_LIBRARY_DIR_DEBUG})
endif()
if(NOT Boost_VERSION_STRING VERSION_LESS 1.86.0)
if(BOOST_LIBRARYDIR AND EXISTS "${BOOST_LIBRARYDIR}")
# Clear existing search paths and use only BOOST_LIBRARYDIR
set(_boost_LIBRARY_SEARCH_DIRS_RELEASE "${BOOST_LIBRARYDIR}" NO_DEFAULT_PATH)
set(_boost_LIBRARY_SEARCH_DIRS_DEBUG "${BOOST_LIBRARYDIR}" NO_DEFAULT_PATH)
if(Boost_DEBUG)
message(STATUS "Boost 1.86: Setting library search dirs to BOOST_LIBRARYDIR: ${BOOST_LIBRARYDIR}")
endif()
endif()
endif()
# Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing.
string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_RELEASE}")

View File

@@ -80,6 +80,7 @@ if (local_rocksdb)
-DCMAKE_DEBUG_POSTFIX=_d
$<$<NOT:$<BOOL:${is_multiconfig}>>:-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}>
-DBUILD_SHARED_LIBS=OFF
-DROCKSDB_BUILD_SHARED=OFF
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
-DWITH_JEMALLOC=$<IF:$<BOOL:${jemalloc}>,ON,OFF>
-DWITH_SNAPPY=ON

View File

@@ -81,4 +81,4 @@ if(XAR_LIBRARY)
else()
message(WARNING "xar library not found... (only important for mac builds)")
endif()
add_library (NIH::WasmEdge ALIAS wasmedge)
add_library (wasmedge::wasmedge ALIAS wasmedge)

View File

@@ -74,7 +74,11 @@ else ()
if (NOT _location)
message (FATAL_ERROR "using pkg-config for grpc, can't find c-ares")
endif ()
add_library (c-ares::cares ${_static} IMPORTED GLOBAL)
if(${_location} MATCHES "\\.a$")
add_library(c-ares::cares STATIC IMPORTED GLOBAL)
else()
add_library(c-ares::cares SHARED IMPORTED GLOBAL)
endif()
set_target_properties (c-ares::cares PROPERTIES
IMPORTED_LOCATION ${_location}
INTERFACE_INCLUDE_DIRECTORIES "${${_prefix}_INCLUDE_DIRS}"
@@ -204,6 +208,7 @@ else ()
CMAKE_ARGS
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_STANDARD=17
$<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:-DCMAKE_VERBOSE_MAKEFILE=ON>
$<$<BOOL:${CMAKE_TOOLCHAIN_FILE}>:-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}>
$<$<BOOL:${VCPKG_TARGET_TRIPLET}>:-DVCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}>

View File

@@ -0,0 +1,52 @@
# QuickJS source files
set(QUICKJS_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libutf.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/qsort_r.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/tutf8e.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/vector.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/char-utils.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/buffer-utils.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/utils.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/ringbuffer.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libregexp.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/quickjs.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libregexp.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libunicode.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/cutils.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/quickjs-libc.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/libbf.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/quickjs-textcode.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/quickjs-internal.c
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/debug.c
)
# QuickJS include directories
set(QUICKJS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs)
# RHTODO: Fix this to be dynamic
set(QUICKJS_VERSION "2023-01-01")
# QuickJS compile definitions
set(QUICKJS_COMPILE_DEFINITIONS
_GNU_SOURCE
CONFIG_VERSION="${QUICKJS_VERSION}"
CONFIG_BIGNUM
)
# Create static library
add_library(quickjs STATIC ${QUICKJS_SOURCES})
target_include_directories(quickjs
PUBLIC
$<BUILD_INTERFACE:${QUICKJS_INCLUDE_DIRS}>
$<INSTALL_INTERFACE:include/quickjs>
)
target_compile_definitions(quickjs PUBLIC ${QUICKJS_COMPILE_DEFINITIONS})
add_library(NIH::quickjs ALIAS quickjs)
target_link_libraries(ripple_libs INTERFACE NIH::quickjs)
install(
FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/quickjs/*.h
DESTINATION include/quickjs
)

View File

@@ -1,14 +1,24 @@
cmake_minimum_required (VERSION 3.16)
if (POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif ()
project (rippled)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif()
if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
# Fix "unrecognized escape" issues when passing CMAKE_MODULE_PATH on Windows.
file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Builds/CMake")
if(POLICY CMP0144)
cmake_policy(SET CMP0144 NEW)
endif()
project (rippled)
set(Boost_NO_BOOST_CMAKE ON)
# make GIT_COMMIT_HASH define available to all sources
@@ -23,14 +33,27 @@ if(Git_FOUND)
endif()
endif() #git
if (thread_safety_analysis)
if(thread_safety_analysis)
add_compile_options(-Wthread-safety -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -DRIPPLE_ENABLE_THREAD_SAFETY_ANNOTATIONS)
add_compile_options("-stdlib=libc++")
add_link_options("-stdlib=libc++")
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Builds/CMake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Builds/CMake/deps")
option(USE_CONAN "Use Conan package manager for dependencies" OFF)
# Then, auto-detect if conan_toolchain.cmake is being used
if(CMAKE_TOOLCHAIN_FILE)
# Check if the toolchain file path contains "conan_toolchain"
if(CMAKE_TOOLCHAIN_FILE MATCHES "conan_toolchain")
set(USE_CONAN ON CACHE BOOL "Using Conan detected from toolchain file" FORCE)
message(STATUS "Conan toolchain detected: ${CMAKE_TOOLCHAIN_FILE}")
message(STATUS "Building with Conan dependencies")
endif()
endif()
if (NOT USE_CONAN)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Builds/CMake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Builds/CMake/deps")
endif()
include (CheckCXXCompilerFlag)
include (FetchContent)
@@ -44,7 +67,9 @@ endif ()
include(RippledSanity)
include(RippledVersion)
include(RippledSettings)
include(RippledNIH)
if (NOT USE_CONAN)
include(RippledNIH)
endif()
# this check has to remain in the top-level cmake
# because of the early return statement
if (packages_only)
@@ -57,24 +82,87 @@ include(RippledCompiler)
include(RippledInterface)
###
if (NOT USE_CONAN)
add_subdirectory(src/secp256k1)
add_subdirectory(src/ed25519-donna)
include(deps/Boost)
include(deps/OpenSSL)
# include(deps/Secp256k1)
# include(deps/Ed25519-donna)
include(deps/Lz4)
include(deps/Libarchive)
include(deps/Sqlite)
include(deps/Soci)
include(deps/Snappy)
include(deps/Rocksdb)
include(deps/Nudb)
include(deps/date)
include(deps/Protobuf)
include(deps/gRPC)
include(deps/cassandra)
include(deps/Postgres)
include(deps/WasmEdge)
else()
include(conan/Boost)
find_package(OpenSSL 1.1.1 REQUIRED)
set_target_properties(OpenSSL::SSL PROPERTIES
INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2
)
add_subdirectory(src/secp256k1)
add_subdirectory(src/ed25519-donna)
find_package(lz4 REQUIRED)
# Target names with :: are not allowed in a generator expression.
# We need to pull the include directories and imported location properties
# from separate targets.
find_package(LibArchive REQUIRED)
find_package(SOCI REQUIRED)
find_package(SQLite3 REQUIRED)
find_package(Snappy REQUIRED)
find_package(wasmedge REQUIRED)
option(rocksdb "Enable RocksDB" ON)
if(rocksdb)
find_package(RocksDB REQUIRED)
set_target_properties(RocksDB::rocksdb PROPERTIES
INTERFACE_COMPILE_DEFINITIONS RIPPLE_ROCKSDB_AVAILABLE=1
)
target_link_libraries(ripple_libs INTERFACE RocksDB::rocksdb)
endif()
find_package(nudb REQUIRED)
find_package(date REQUIRED)
include(conan/Protobuf)
include(conan/gRPC)
if(TARGET nudb::core)
set(nudb nudb::core)
elseif(TARGET NuDB::nudb)
set(nudb NuDB::nudb)
else()
message(FATAL_ERROR "unknown nudb target")
endif()
target_link_libraries(ripple_libs INTERFACE ${nudb})
include(deps/Boost)
include(deps/OpenSSL)
include(deps/Secp256k1)
include(deps/Ed25519-donna)
include(deps/Lz4)
include(deps/Libarchive)
include(deps/Sqlite)
include(deps/Soci)
include(deps/Snappy)
include(deps/Rocksdb)
include(deps/Nudb)
include(deps/date)
include(deps/Protobuf)
include(deps/gRPC)
include(deps/cassandra)
include(deps/Postgres)
include(deps/WasmEdge)
if(reporting)
find_package(cassandra-cpp-driver REQUIRED)
find_package(PostgreSQL REQUIRED)
target_link_libraries(ripple_libs INTERFACE
cassandra-cpp-driver::cassandra-cpp-driver
PostgreSQL::PostgreSQL
)
endif()
target_link_libraries(ripple_libs INTERFACE
ed25519::ed25519
LibArchive::LibArchive
lz4::lz4
OpenSSL::Crypto
OpenSSL::SSL
Ripple::grpc_pbufs
Ripple::pbufs
secp256k1::secp256k1
soci::soci
SQLite::SQLite3
)
endif()
include(deps/quickjs)
###

View File

@@ -8,6 +8,130 @@ This document contains the release notes for `rippled`, the reference server imp
Have new ideas? Need help with setting up your node? [Please open an issue here](https://github.com/xrplf/rippled/issues/new/choose).
# Introducing XRP Ledger version 1.11.0
Version 1.11.0 of `rippled`, the reference server implementation of the XRP Ledger protocol, is now available.
This release reduces memory usage, introduces the `fixNFTokenRemint` amendment, and adds new features and bug fixes. For example, the new NetworkID field in transactions helps to prevent replay attacks with side-chains.
[Sign Up for Future Release Announcements](https://groups.google.com/g/ripple-server)
<!-- BREAK -->
## Action Required
The `fixNFTokenRemint` amendment is now open for voting according to the XRP Ledger's [amendment process](https://xrpl.org/amendments.html), which enables protocol changes following two weeks of >80% support from trusted validators.
If you operate an XRP Ledger server, upgrade to version 1.11.0 by July 5 to ensure service continuity. The exact time that protocol changes take effect depends on the voting decisions of the decentralized network.
## Install / Upgrade
On supported platforms, see the [instructions on installing or updating `rippled`](https://xrpl.org/install-rippled.html).
## What's Changed
### New Features and Improvements
* Allow port numbers be be specified using a either a colon or a space by @RichardAH in https://github.com/XRPLF/rippled/pull/4328
* Eliminate memory allocation from critical path: by @nbougalis in https://github.com/XRPLF/rippled/pull/4353
* Make it easy for projects to depend on libxrpl by @thejohnfreeman in https://github.com/XRPLF/rippled/pull/4449
* Add the ability to mark amendments as obsolete by @ximinez in https://github.com/XRPLF/rippled/pull/4291
* Always create the FeeSettings object in genesis ledger by @ximinez in https://github.com/XRPLF/rippled/pull/4319
* Log exception messages in several locations by @drlongle in https://github.com/XRPLF/rippled/pull/4400
* Parse flags in account_info method by @drlongle in https://github.com/XRPLF/rippled/pull/4459
* Add NFTokenPages to account_objects RPC by @RichardAH in https://github.com/XRPLF/rippled/pull/4352
* add jss fields used by clio `nft_info` by @ledhed2222 in https://github.com/XRPLF/rippled/pull/4320
* Introduce a slab-based memory allocator and optimize SHAMapItem by @nbougalis in https://github.com/XRPLF/rippled/pull/4218
* Add NetworkID field to transactions to help prevent replay attacks on and from side-chains by @RichardAH in https://github.com/XRPLF/rippled/pull/4370
* If present, set quorum based on command line. by @mtrippled in https://github.com/XRPLF/rippled/pull/4489
* API does not accept seed or public key for account by @drlongle in https://github.com/XRPLF/rippled/pull/4404
* Add `nftoken_id`, `nftoken_ids` and `offer_id` meta fields into NFT `Tx` responses by @shawnxie999 in https://github.com/XRPLF/rippled/pull/4447
### Bug Fixes
* fix(gateway_balances): handle overflow exception by @RichardAH in https://github.com/XRPLF/rippled/pull/4355
* fix(ValidatorSite): handle rare null pointer dereference in timeout by @ximinez in https://github.com/XRPLF/rippled/pull/4420
* RPC commands understand markers derived from all ledger object types by @ximinez in https://github.com/XRPLF/rippled/pull/4361
* `fixNFTokenRemint`: prevent NFT re-mint: by @shawnxie999 in https://github.com/XRPLF/rippled/pull/4406
* Fix a case where ripple::Expected returned a json array, not a value by @scottschurr in https://github.com/XRPLF/rippled/pull/4401
* fix: Ledger data returns an empty list (instead of null) when all entries are filtered out by @drlongle in https://github.com/XRPLF/rippled/pull/4398
* Fix unit test ripple.app.LedgerData by @drlongle in https://github.com/XRPLF/rippled/pull/4484
* Fix the fix for std::result_of by @thejohnfreeman in https://github.com/XRPLF/rippled/pull/4496
* Fix errors for Clang 16 by @thejohnfreeman in https://github.com/XRPLF/rippled/pull/4501
* Ensure that switchover vars are initialized before use: by @seelabs in https://github.com/XRPLF/rippled/pull/4527
* Move faulty assert by @ximinez in https://github.com/XRPLF/rippled/pull/4533
* Fix unaligned load and stores: (#4528) by @seelabs in https://github.com/XRPLF/rippled/pull/4531
* fix node size estimation by @dangell7 in https://github.com/XRPLF/rippled/pull/4536
* fix: remove redundant moves by @ckeshava in https://github.com/XRPLF/rippled/pull/4565
### Code Cleanup and Testing
* Replace compare() with the three-way comparison operator in base_uint, Issue and Book by @drlongle in https://github.com/XRPLF/rippled/pull/4411
* Rectify the import paths of boost::function_output_iterator by @ckeshava in https://github.com/XRPLF/rippled/pull/4293
* Expand Linux test matrix by @thejohnfreeman in https://github.com/XRPLF/rippled/pull/4454
* Add patched recipe for SOCI by @thejohnfreeman in https://github.com/XRPLF/rippled/pull/4510
* Switch to self-hosted runners for macOS by @thejohnfreeman in https://github.com/XRPLF/rippled/pull/4511
* [TRIVIAL] Add missing includes by @seelabs in https://github.com/XRPLF/rippled/pull/4555
### Docs
* Refactor build instructions by @thejohnfreeman in https://github.com/XRPLF/rippled/pull/4381
* Add install instructions for package managers by @thejohnfreeman in https://github.com/XRPLF/rippled/pull/4472
* Fix typo by @solmsted in https://github.com/XRPLF/rippled/pull/4508
* Update environment.md by @sappenin in https://github.com/XRPLF/rippled/pull/4498
* Update BUILD.md by @oeggert in https://github.com/XRPLF/rippled/pull/4514
* Trivial: add comments for NFToken-related invariants by @scottschurr in https://github.com/XRPLF/rippled/pull/4558
## New Contributors
* @drlongle made their first contribution in https://github.com/XRPLF/rippled/pull/4411
* @ckeshava made their first contribution in https://github.com/XRPLF/rippled/pull/4293
* @solmsted made their first contribution in https://github.com/XRPLF/rippled/pull/4508
* @sappenin made their first contribution in https://github.com/XRPLF/rippled/pull/4498
* @oeggert made their first contribution in https://github.com/XRPLF/rippled/pull/4514
**Full Changelog**: https://github.com/XRPLF/rippled/compare/1.10.1...1.11.0
### GitHub
The public source code repository for `rippled` is hosted on GitHub at <https://github.com/XRPLF/rippled>.
We welcome all contributions and invite everyone to join the community of XRP Ledger developers to help build the Internet of Value.
### Credits
The following people contributed directly to this release:
- Alloy Networks <45832257+alloynetworks@users.noreply.github.com>
- Brandon Wilson <brandon@coil.com>
- Chenna Keshava B S <21219765+ckeshava@users.noreply.github.com>
- David Fuelling <sappenin@gmail.com>
- Denis Angell <dangell@transia.co>
- Ed Hennis <ed@ripple.com>
- Elliot Lee <github.public@intelliot.com>
- John Freeman <jfreeman08@gmail.com>
- Mark Travis <mtrippled@users.noreply.github.com>
- Nik Bougalis <nikb@bougalis.net>
- RichardAH <richard.holland@starstone.co.nz>
- Scott Determan <scott.determan@yahoo.com>
- Scott Schurr <scott@ripple.com>
- Shawn Xie <35279399+shawnxie999@users.noreply.github.com>
- drlongle <drlongle@gmail.com>
- ledhed2222 <ledhed2222@users.noreply.github.com>
- oeggert <117319296+oeggert@users.noreply.github.com>
- solmsted <steven.olm@gmail.com>
Bug Bounties and Responsible Disclosures:
We welcome reviews of the rippled code and urge researchers to
responsibly disclose any issues they may find.
To report a bug, please send a detailed report to:
bugs@xrpl.org
# Introducing XRP Ledger version 1.10.1
Version 1.10.1 of `rippled`, the reference server implementation of the XRP Ledger protocol, is now available. This release restores packages for Ubuntu 18.04.

View File

@@ -61,13 +61,12 @@ For these complaints or reports, please [contact our support team](mailto:bugs@x
### The following type of security problems are excluded
- (D)DOS attacks
- Error messages or error pages without sensitive data
- Tests & sample data as publicly available in our repositories at Github
- Common issues like browser header warnings or DNS configuration, identified by vulnerability scans
- Vulnerability scan reports for software we publicly use
- Security issues related to outdated OS's, browsers or plugins
- Reports for security problems that we have been notified of before
1. **In scope**. Only bugs in software under the scope of the program qualify. Currently, that means `xahaud` and `xahau-lib`.
2. **Relevant**. A security issue, posing a danger to user funds, privacy or the operation of the Xahau Ledger.
3. **Original and previously unknown**. Bugs that are already known and discussed in public do not qualify. Previously reported bugs, even if publicly unknown, are not eligible.
4. **Specific**. We welcome general security advice or recommendations, but we cannot pay bounties for that.
5. **Fixable**. There has to be something we can do to permanently fix the problem. Note that bugs in other peoples software may still qualify in some cases. For example, if you find a bug in a library that we use which can compromise the security of software that is in scope and we can get it fixed, you may qualify for a bounty.
6. **Unused**. If you use the exploit to attack the Xahau Ledger, you do not qualify for a bounty. If you report a vulnerability used in an ongoing or past attack and there is specific, concrete evidence that suggests you are the attacker we reserve the right not to pay a bounty.
Please note: Reports that are lacking any proof (such as screenshots or other data), detailed information or details on how to reproduce any unexpected result will be investigated but will not be eligible for any reward.

View File

@@ -35,7 +35,7 @@ message(STATUS \"Using LLVMConfig.cmake in: \${LLVM_DIR}\")
add_library (wasmedge STATIC IMPORTED GLOBAL)
set_target_properties(wasmedge PROPERTIES IMPORTED_LOCATION \${WasmEdge_LIB})
target_link_libraries (ripple_libs INTERFACE wasmedge)
add_library (NIH::WasmEdge ALIAS wasmedge)
add_library (wasmedge::wasmedge ALIAS wasmedge)
message(\"WasmEdge DONE\")
" > Builds/CMake/deps/WasmEdge.cmake &&
git checkout src/ripple/protocol/impl/BuildInfo.cpp &&

0
build-full.sh Executable file → Normal file
View File

View File

@@ -62,7 +62,8 @@
"3C43D9A973AA4443EF3FC38E42DD306160FBFFDAB901CD8BAA15D09F2597EB87",
"0285B7E5E08E1A8E4C15636F0591D87F73CB6A7B6452A932AD72BBC8E5D1CBE3",
"6E739F4F8B07BED29FC9FF440DA3C301CD14A180DF45819F658FEC2F7DE31427",
"36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6"
"36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6",
"DD4F86291F142A20761B32B4D0CE4291F86CA33F0B46F0D04171482FBA52E536"
],
"Flags": 0,
"LedgerEntryType": "Amendments",

View File

@@ -1,4 +1,4 @@
# standalone: ./rippled -a --ledgerfile config/genesis.json --conf config/rippled-standalone.cfg
# standalone: ./rippled -a --ledgerfile cfg/genesis.json --conf cfg/rippled-standalone.cfg
[server]
port_rpc_admin_local
port_ws_public
@@ -153,3 +153,4 @@ D686F2538F410C9D0D856788E98E3579595DAF7B38D38887F81ECAC934B06040 HooksUpdate1
EDB4EE4C524E16BDD91D9A529332DED08DCAAA51CC6DC897ACFA1A0ED131C5B6 fix240819
8063140E9260799D6716756B891CEC3E7006C4E4F277AB84670663A88F94B9C4 fixPageCap
88693F108C3CD8A967F3F4253A32DEF5E35F9406ACD2A11B88B11D90865763A9 fix240911
DD4F86291F142A20761B32B4D0CE4291F86CA33F0B46F0D04171482FBA52E536 JsHooks

155
conanfile.py Normal file
View File

@@ -0,0 +1,155 @@
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
import re
class Xrpl(ConanFile):
name = 'xrpl'
license = 'ISC'
author = 'John Freeman <jfreeman@ripple.com>'
url = 'https://github.com/xrplf/rippled'
description = 'The XRP Ledger'
settings = 'os', 'compiler', 'build_type', 'arch'
options = {
'assertions': [True, False],
'coverage': [True, False],
'fPIC': [True, False],
'jemalloc': [True, False],
'reporting': [True, False],
'rocksdb': [True, False],
'shared': [True, False],
'static': [True, False],
'tests': [True, False],
'unity': [True, False],
}
requires = [
'boost/1.86.0',
'date/3.0.1',
'libarchive/3.6.0',
'lz4/1.9.3',
'grpc/1.50.1',
'nudb/2.0.8',
'openssl/1.1.1u',
'protobuf/3.21.9',
'snappy/1.1.10',
'soci/4.0.3',
'sqlite3/3.42.0',
'zlib/1.2.13',
'wasmedge/0.11.2',
]
default_options = {
'assertions': False,
'coverage': False,
'fPIC': True,
'jemalloc': False,
'reporting': False,
'rocksdb': True,
'shared': False,
'static': True,
'tests': True,
'unity': False,
'cassandra-cpp-driver:shared': False,
'date:header_only': True,
'grpc:shared': False,
'grpc:secure': True,
'libarchive:shared': False,
'libarchive:with_acl': False,
'libarchive:with_bzip2': False,
'libarchive:with_cng': False,
'libarchive:with_expat': False,
'libarchive:with_iconv': False,
'libarchive:with_libxml2': False,
'libarchive:with_lz4': True,
'libarchive:with_lzma': False,
'libarchive:with_lzo': False,
'libarchive:with_nettle': False,
'libarchive:with_openssl': False,
'libarchive:with_pcreposix': False,
'libarchive:with_xattr': False,
'libarchive:with_zlib': False,
'libpq:shared': False,
'lz4:shared': False,
'openssl:shared': False,
'protobuf:shared': False,
'protobuf:with_zlib': True,
'rocksdb:enable_sse': False,
'rocksdb:lite': False,
'rocksdb:shared': False,
'rocksdb:use_rtti': True,
'rocksdb:with_jemalloc': False,
'rocksdb:with_lz4': True,
'rocksdb:with_snappy': True,
'snappy:shared': False,
'soci:shared': False,
'soci:with_sqlite3': True,
'soci:with_boost': True,
}
def set_version(self):
path = f'{self.recipe_folder}/src/ripple/protocol/impl/BuildInfo.cpp'
regex = r'versionString\s?=\s?\"(.*)\"'
with open(path, 'r') as file:
matches = (re.search(regex, line) for line in file)
match = next(m for m in matches if m)
self.version = match.group(1)
def configure(self):
if self.settings.compiler == 'apple-clang':
self.options['boost'].visibility = 'global'
def requirements(self):
if self.options.jemalloc:
self.requires('jemalloc/5.2.1')
if self.options.reporting:
self.requires('cassandra-cpp-driver/2.15.3')
self.requires('libpq/13.6')
if self.options.rocksdb:
self.requires('rocksdb/6.27.3')
exports_sources = (
'CMakeLists.txt', 'Builds/*', 'bin/getRippledInfo', 'src/*', 'cfg/*'
)
def layout(self):
cmake_layout(self)
# Fix this setting to follow the default introduced in Conan 1.48
# to align with our build instructions.
self.folders.generators = 'build/generators'
generators = 'CMakeDeps'
def generate(self):
tc = CMakeToolchain(self)
tc.variables['tests'] = self.options.tests
tc.variables['assert'] = self.options.assertions
tc.variables['coverage'] = self.options.coverage
tc.variables['jemalloc'] = self.options.jemalloc
tc.variables['reporting'] = self.options.reporting
tc.variables['rocksdb'] = self.options.rocksdb
tc.variables['BUILD_SHARED_LIBS'] = self.options.shared
tc.variables['static'] = self.options.static
tc.variables['unity'] = self.options.unity
tc.generate()
def build(self):
cmake = CMake(self)
cmake.verbose = True
cmake.configure()
cmake.build()
def package(self):
cmake = CMake(self)
cmake.verbose = True
cmake.install()
def package_info(self):
libxrpl = self.cpp_info.components['libxrpl']
libxrpl.libs = [
'libxrpl_core.a',
'libed25519.a',
'libsecp256k1.a',
]
libxrpl.includedirs = ['include']
libxrpl.requires = ['boost::boost']

11
docker-unit-tests.sh Normal file → Executable file
View File

@@ -1,4 +1,11 @@
#!/bin/bash
#!/bin/bash -x
docker run --rm -i -v $(pwd):/io ubuntu sh -c '/io/release-build/xahaud -u'
BUILD_CORES=$(echo "scale=0 ; `nproc` / 1.337" | bc)
if [[ "$GITHUB_REPOSITORY" == "" ]]; then
#Default
BUILD_CORES=8
fi
echo "Mounting $(pwd)/io in ubuntu and running unit tests"
docker run --rm -i -v $(pwd):/io -e BUILD_CORES=$BUILD_CORES ubuntu sh -c '/io/release-build/xahaud --unittest-jobs $BUILD_CORES -u'

84
docs/build/environment.md vendored Normal file
View File

@@ -0,0 +1,84 @@
Our [build instructions][BUILD.md] assume you have a C++ development
environment complete with Git, Python, Conan, CMake, and a C++ compiler.
This document exists to help readers set one up on any of the Big Three
platforms: Linux, macOS, or Windows.
[BUILD.md]: ../../BUILD.md
## Linux
Package ecosystems vary across Linux distributions,
so there is no one set of instructions that will work for every Linux user.
These instructions are written for Ubuntu 22.04.
They are largely copied from the [script][1] used to configure our Docker
container for continuous integration.
That script handles many more responsibilities.
These instructions are just the bare minimum to build one configuration of
rippled.
You can check that codebase for other Linux distributions and versions.
If you cannot find yours there,
then we hope that these instructions can at least guide you in the right
direction.
```
apt update
apt install --yes curl git libssl-dev python3.10-dev python3-pip make g++-11
curl --location --remote-name \
"https://github.com/Kitware/CMake/releases/download/v3.25.1/cmake-3.25.1.tar.gz"
tar -xzf cmake-3.25.1.tar.gz
rm cmake-3.25.1.tar.gz
cd cmake-3.25.1
./bootstrap --parallel=$(nproc)
make --jobs $(nproc)
make install
cd ..
pip3 install 'conan<2'
```
[1]: https://github.com/thejohnfreeman/rippled-docker/blob/master/ubuntu-22.04/install.sh
## macOS
Open a Terminal and enter the below command to bring up a dialog to install
the command line developer tools.
Once it is finished, this command should return a version greater than the
minimum required (see [BUILD.md][]).
```
clang --version
```
The command line developer tools should include Git too:
```
git --version
```
Install [Homebrew][],
use it to install [pyenv][],
use it to install Python,
and use it to install Conan:
[Homebrew]: https://brew.sh/
[pyenv]: https://github.com/pyenv/pyenv
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew update
brew install xz
brew install pyenv
pyenv install 3.10-dev
pyenv global 3.10-dev
eval "$(pyenv init -)"
pip install 'conan<2'
```
Install CMake with Homebrew too:
```
brew install cmake
```

159
docs/build/install.md vendored Normal file
View File

@@ -0,0 +1,159 @@
This document contains instructions for installing rippled.
The APT package manager is common on Debian-based Linux distributions like
Ubuntu,
while the YUM package manager is common on Red Hat-based Linux distributions
like CentOS.
Installing from source is an option for all platforms,
and the only supported option for installing custom builds.
## From source
From a source build, you can install rippled and libxrpl using CMake's
`--install` mode:
```
cmake --install . --prefix /opt/local
```
The default [prefix][1] is typically `/usr/local` on Linux and macOS and
`C:/Program Files/rippled` on Windows.
[1]: https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html
## With the APT package manager
1. Update repositories:
sudo apt update -y
2. Install utilities:
sudo apt install -y apt-transport-https ca-certificates wget gnupg
3. Add Ripple's package-signing GPG key to your list of trusted keys:
sudo mkdir /usr/local/share/keyrings/
wget -q -O - "https://repos.ripple.com/repos/api/gpg/key/public" | gpg --dearmor > ripple-key.gpg
sudo mv ripple-key.gpg /usr/local/share/keyrings
4. Check the fingerprint of the newly-added key:
gpg /usr/local/share/keyrings/ripple-key.gpg
The output should include an entry for Ripple such as the following:
gpg: WARNING: no command supplied. Trying to guess what you mean ...
pub rsa3072 2019-02-14 [SC] [expires: 2026-02-17]
C0010EC205B35A3310DC90DE395F97FFCCAFD9A2
uid TechOps Team at Ripple <techops+rippled@ripple.com>
sub rsa3072 2019-02-14 [E] [expires: 2026-02-17]
In particular, make sure that the fingerprint matches. (In the above example, the fingerprint is on the third line, starting with `C001`.)
4. Add the appropriate Ripple repository for your operating system version:
echo "deb [signed-by=/usr/local/share/keyrings/ripple-key.gpg] https://repos.ripple.com/repos/rippled-deb focal stable" | \
sudo tee -a /etc/apt/sources.list.d/ripple.list
The above example is appropriate for **Ubuntu 20.04 Focal Fossa**. For other operating systems, replace the word `focal` with one of the following:
- `jammy` for **Ubuntu 22.04 Jammy Jellyfish**
- `bionic` for **Ubuntu 18.04 Bionic Beaver**
- `bullseye` for **Debian 11 Bullseye**
- `buster` for **Debian 10 Buster**
If you want access to development or pre-release versions of `rippled`, use one of the following instead of `stable`:
- `unstable` - Pre-release builds ([`release` branch](https://github.com/ripple/rippled/tree/release))
- `nightly` - Experimental/development builds ([`develop` branch](https://github.com/ripple/rippled/tree/develop))
**Warning:** Unstable and nightly builds may be broken at any time. Do not use these builds for production servers.
5. Fetch the Ripple repository.
sudo apt -y update
6. Install the `rippled` software package:
sudo apt -y install rippled
7. Check the status of the `rippled` service:
systemctl status rippled.service
The `rippled` service should start automatically. If not, you can start it manually:
sudo systemctl start rippled.service
8. Optional: allow `rippled` to bind to privileged ports.
This allows you to serve incoming API requests on port 80 or 443. (If you want to do so, you must also update the config file's port settings.)
sudo setcap 'cap_net_bind_service=+ep' /opt/ripple/bin/rippled
## With the YUM package manager
1. Install the Ripple RPM repository:
Choose the appropriate RPM repository for the stability of releases you want:
- `stable` for the latest production release (`master` branch)
- `unstable` for pre-release builds (`release` branch)
- `nightly` for experimental/development builds (`develop` branch)
*Stable*
cat << REPOFILE | sudo tee /etc/yum.repos.d/ripple.repo
[ripple-stable]
name=XRP Ledger Packages
enabled=1
gpgcheck=0
repo_gpgcheck=1
baseurl=https://repos.ripple.com/repos/rippled-rpm/stable/
gpgkey=https://repos.ripple.com/repos/rippled-rpm/stable/repodata/repomd.xml.key
REPOFILE
*Unstable*
cat << REPOFILE | sudo tee /etc/yum.repos.d/ripple.repo
[ripple-unstable]
name=XRP Ledger Packages
enabled=1
gpgcheck=0
repo_gpgcheck=1
baseurl=https://repos.ripple.com/repos/rippled-rpm/unstable/
gpgkey=https://repos.ripple.com/repos/rippled-rpm/unstable/repodata/repomd.xml.key
REPOFILE
*Nightly*
cat << REPOFILE | sudo tee /etc/yum.repos.d/ripple.repo
[ripple-nightly]
name=XRP Ledger Packages
enabled=1
gpgcheck=0
repo_gpgcheck=1
baseurl=https://repos.ripple.com/repos/rippled-rpm/nightly/
gpgkey=https://repos.ripple.com/repos/rippled-rpm/nightly/repodata/repomd.xml.key
REPOFILE
2. Fetch the latest repo updates:
sudo yum -y update
3. Install the new `rippled` package:
sudo yum install -y rippled
4. Configure the `rippled` service to start on boot:
sudo systemctl enable rippled.service
5. Start the `rippled` service:
sudo systemctl start rippled.service

193
external/rocksdb/conanfile.py vendored Normal file
View File

@@ -0,0 +1,193 @@
import os
import shutil
from conans import ConanFile, CMake
from conan.tools import microsoft as ms
class RocksDB(ConanFile):
name = 'rocksdb'
version = '6.27.3'
license = ('GPL-2.0-only', 'Apache-2.0')
url = 'https://github.com/conan-io/conan-center-index'
description = 'A library that provides an embeddable, persistent key-value store for fast storage'
topics = ('rocksdb', 'database', 'leveldb', 'facebook', 'key-value')
settings = 'os', 'compiler', 'build_type', 'arch'
options = {
'enable_sse': [False, 'sse42', 'avx2'],
'fPIC': [True, False],
'lite': [True, False],
'shared': [True, False],
'use_rtti': [True, False],
'with_gflags': [True, False],
'with_jemalloc': [True, False],
'with_lz4': [True, False],
'with_snappy': [True, False],
'with_tbb': [True, False],
'with_zlib': [True, False],
'with_zstd': [True, False],
}
default_options = {
'enable_sse': False,
'fPIC': True,
'lite': False,
'shared': False,
'use_rtti': False,
'with_gflags': False,
'with_jemalloc': False,
'with_lz4': False,
'with_snappy': False,
'with_tbb': False,
'with_zlib': False,
'with_zstd': False,
}
def requirements(self):
if self.options.with_gflags:
self.requires('gflags/2.2.2')
if self.options.with_jemalloc:
self.requires('jemalloc/5.2.1')
if self.options.with_lz4:
self.requires('lz4/1.9.3')
if self.options.with_snappy:
self.requires('snappy/1.1.9')
if self.options.with_tbb:
self.requires('onetbb/2020.3')
if self.options.with_zlib:
self.requires('zlib/1.2.11')
if self.options.with_zstd:
self.requires('zstd/1.5.2')
def config_options(self):
if self.settings.os == 'Windows':
del self.options.fPIC
def configure(self):
if self.options.shared:
del self.options.fPIC
generators = 'cmake', 'cmake_find_package'
scm = {
'type': 'git',
'url': 'https://github.com/facebook/rocksdb.git',
'revision': 'v6.27.3',
}
exports_sources = 'thirdparty.inc'
# For out-of-source build.
no_copy_source = True
_cmake = None
def _configure_cmake(self):
if self._cmake:
return
self._cmake = CMake(self)
self._cmake.definitions['CMAKE_POSITION_INDEPENDENT_CODE'] = True
self._cmake.definitions['DISABLE_STALL_NOTIF'] = False
self._cmake.definitions['FAIL_ON_WARNINGS'] = False
self._cmake.definitions['OPTDBG'] = True
self._cmake.definitions['WITH_TESTS'] = False
self._cmake.definitions['WITH_TOOLS'] = False
self._cmake.definitions['WITH_GFLAGS'] = self.options.with_gflags
self._cmake.definitions['WITH_JEMALLOC'] = self.options.with_jemalloc
self._cmake.definitions['WITH_LZ4'] = self.options.with_lz4
self._cmake.definitions['WITH_SNAPPY'] = self.options.with_snappy
self._cmake.definitions['WITH_TBB'] = self.options.with_tbb
self._cmake.definitions['WITH_ZLIB'] = self.options.with_zlib
self._cmake.definitions['WITH_ZSTD'] = self.options.with_zstd
self._cmake.definitions['USE_RTTI'] = self.options.use_rtti
self._cmake.definitions['ROCKSDB_LITE'] = self.options.lite
self._cmake.definitions['ROCKSDB_INSTALL_ON_WINDOWS'] = (
self.settings.os == 'Windows'
)
if not self.options.enable_sse:
self._cmake.definitions['PORTABLE'] = True
self._cmake.definitions['FORCE_SSE42'] = False
elif self.options.enable_sse == 'sse42':
self._cmake.definitions['PORTABLE'] = True
self._cmake.definitions['FORCE_SSE42'] = True
elif self.options.enable_sse == 'avx2':
self._cmake.definitions['PORTABLE'] = False
self._cmake.definitions['FORCE_SSE42'] = False
self._cmake.definitions['WITH_ASAN'] = False
self._cmake.definitions['WITH_BZ2'] = False
self._cmake.definitions['WITH_JNI'] = False
self._cmake.definitions['WITH_LIBRADOS'] = False
if ms.is_msvc(self):
self._cmake.definitions['WITH_MD_LIBRARY'] = (
ms.msvc_runtime_flag(self).startswith('MD')
)
self._cmake.definitions['WITH_RUNTIME_DEBUG'] = (
ms.msvc_runtime_flag(self).endswith('d')
)
self._cmake.definitions['WITH_NUMA'] = False
self._cmake.definitions['WITH_TSAN'] = False
self._cmake.definitions['WITH_UBSAN'] = False
self._cmake.definitions['WITH_WINDOWS_UTF8_FILENAMES'] = False
self._cmake.definitions['WITH_XPRESS'] = False
self._cmake.definitions['WITH_FALLOCATE'] = True
def build(self):
if ms.is_msvc(self):
file = os.path.join(
self.recipe_folder, '..', 'export_source', 'thirdparty.inc'
)
shutil.copy(file, self.build_folder)
self._configure_cmake()
self._cmake.configure()
self._cmake.build()
def package(self):
self._configure_cmake()
self._cmake.install()
def package_info(self):
self.cpp_info.filenames['cmake_find_package'] = 'RocksDB'
self.cpp_info.filenames['cmake_find_package_multi'] = 'RocksDB'
self.cpp_info.set_property('cmake_file_name', 'RocksDB')
self.cpp_info.names['cmake_find_package'] = 'RocksDB'
self.cpp_info.names['cmake_find_package_multi'] = 'RocksDB'
self.cpp_info.components['librocksdb'].names['cmake_find_package'] = 'rocksdb'
self.cpp_info.components['librocksdb'].names['cmake_find_package_multi'] = 'rocksdb'
self.cpp_info.components['librocksdb'].set_property(
'cmake_target_name', 'RocksDB::rocksdb'
)
self.cpp_info.components['librocksdb'].libs = ['rocksdb']
if self.settings.os == "Windows":
self.cpp_info.components["librocksdb"].system_libs = ["shlwapi", "rpcrt4"]
if self.options.shared:
self.cpp_info.components["librocksdb"].defines = ["ROCKSDB_DLL"]
elif self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["librocksdb"].system_libs = ["pthread", "m"]
if self.options.lite:
self.cpp_info.components["librocksdb"].defines.append("ROCKSDB_LITE")
if self.options.with_gflags:
self.cpp_info.components["librocksdb"].requires.append("gflags::gflags")
if self.options.with_jemalloc:
self.cpp_info.components["librocksdb"].requires.append("jemalloc::jemalloc")
if self.options.with_lz4:
self.cpp_info.components["librocksdb"].requires.append("lz4::lz4")
if self.options.with_snappy:
self.cpp_info.components["librocksdb"].requires.append("snappy::snappy")
if self.options.with_tbb:
self.cpp_info.components["librocksdb"].requires.append("onetbb::onetbb")
if self.options.with_zlib:
self.cpp_info.components["librocksdb"].requires.append("zlib::zlib")
if self.options.with_zstd:
self.cpp_info.components["librocksdb"].requires.append("zstd::zstd")

62
external/rocksdb/thirdparty.inc vendored Normal file
View File

@@ -0,0 +1,62 @@
if(WITH_GFLAGS)
# Config with namespace available since gflags 2.2.2
find_package(gflags REQUIRED)
set(GFLAGS_LIB gflags::gflags)
list(APPEND THIRDPARTY_LIBS ${GFLAGS_LIB})
add_definitions(-DGFLAGS=1)
endif()
if(WITH_SNAPPY)
find_package(Snappy REQUIRED)
add_definitions(-DSNAPPY)
list(APPEND THIRDPARTY_LIBS Snappy::snappy)
endif()
if(WITH_LZ4)
find_package(lz4 REQUIRED)
add_definitions(-DLZ4)
list(APPEND THIRDPARTY_LIBS lz4::lz4)
endif()
if(WITH_ZLIB)
find_package(ZLIB REQUIRED)
add_definitions(-DZLIB)
list(APPEND THIRDPARTY_LIBS ZLIB::ZLIB)
endif()
option(WITH_BZ2 "build with bzip2" OFF)
if(WITH_BZ2)
find_package(BZip2 REQUIRED)
add_definitions(-DBZIP2)
list(APPEND THIRDPARTY_LIBS BZip2::BZip2)
endif()
if(WITH_ZSTD)
find_package(zstd REQUIRED)
add_definitions(-DZSTD)
list(APPEND THIRDPARTY_LIBS zstd::zstd)
endif()
# ================================================== XPRESS ==================================================
# This makes use of built-in Windows API, no additional includes, links to a system lib
if(WITH_XPRESS)
message(STATUS "XPRESS is enabled")
add_definitions(-DXPRESS)
# We are using the implementation provided by the system
list(APPEND SYSTEM_LIBS Cabinet.lib)
else()
message(STATUS "XPRESS is disabled")
endif()
# ================================================== JEMALLOC ==================================================
if(WITH_JEMALLOC)
message(STATUS "JEMALLOC library is enabled")
add_definitions(-DROCKSDB_JEMALLOC -DJEMALLOC_EXPORT= -DJEMALLOC_NO_RENAME)
list(APPEND THIRDPARTY_LIBS jemalloc::jemalloc)
set(ARTIFACT_SUFFIX "_je")
else ()
set(ARTIFACT_SUFFIX "")
message(STATUS "JEMALLOC library is disabled")
endif ()

40
external/snappy/conandata.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
sources:
"1.1.10":
url: "https://github.com/google/snappy/archive/1.1.10.tar.gz"
sha256: "49d831bffcc5f3d01482340fe5af59852ca2fe76c3e05df0e67203ebbe0f1d90"
"1.1.9":
url: "https://github.com/google/snappy/archive/1.1.9.tar.gz"
sha256: "75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7"
"1.1.8":
url: "https://github.com/google/snappy/archive/1.1.8.tar.gz"
sha256: "16b677f07832a612b0836178db7f374e414f94657c138e6993cbfc5dcc58651f"
"1.1.7":
url: "https://github.com/google/snappy/archive/1.1.7.tar.gz"
sha256: "3dfa02e873ff51a11ee02b9ca391807f0c8ea0529a4924afa645fbf97163f9d4"
patches:
"1.1.10":
- patch_file: "patches/1.1.10-0001-fix-inlining-failure.patch"
patch_description: "disable inlining for compilation error"
patch_type: "portability"
- patch_file: "patches/1.1.9-0002-no-Werror.patch"
patch_description: "disable 'warning as error' options"
patch_type: "portability"
- patch_file: "patches/1.1.10-0003-fix-clobber-list-older-llvm.patch"
patch_description: "disable inline asm on apple-clang"
patch_type: "portability"
- patch_file: "patches/1.1.9-0004-rtti-by-default.patch"
patch_description: "remove 'disable rtti'"
patch_type: "conan"
"1.1.9":
- patch_file: "patches/1.1.9-0001-fix-inlining-failure.patch"
patch_description: "disable inlining for compilation error"
patch_type: "portability"
- patch_file: "patches/1.1.9-0002-no-Werror.patch"
patch_description: "disable 'warning as error' options"
patch_type: "portability"
- patch_file: "patches/1.1.9-0003-fix-clobber-list-older-llvm.patch"
patch_description: "disable inline asm on apple-clang"
patch_type: "portability"
- patch_file: "patches/1.1.9-0004-rtti-by-default.patch"
patch_description: "remove 'disable rtti'"
patch_type: "conan"

89
external/snappy/conanfile.py vendored Normal file
View File

@@ -0,0 +1,89 @@
from conan import ConanFile
from conan.tools.build import check_min_cppstd
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, rmdir
from conan.tools.scm import Version
import os
required_conan_version = ">=1.54.0"
class SnappyConan(ConanFile):
name = "snappy"
description = "A fast compressor/decompressor"
topics = ("google", "compressor", "decompressor")
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/google/snappy"
license = "BSD-3-Clause"
package_type = "library"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
}
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == 'Windows':
del self.options.fPIC
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
def layout(self):
cmake_layout(self, src_folder="src")
def validate(self):
if self.settings.compiler.get_safe("cppstd"):
check_min_cppstd(self, 11)
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
tc = CMakeToolchain(self)
tc.variables["SNAPPY_BUILD_TESTS"] = False
if Version(self.version) >= "1.1.8":
tc.variables["SNAPPY_FUZZING_BUILD"] = False
tc.variables["SNAPPY_REQUIRE_AVX"] = False
tc.variables["SNAPPY_REQUIRE_AVX2"] = False
tc.variables["SNAPPY_INSTALL"] = True
if Version(self.version) >= "1.1.9":
tc.variables["SNAPPY_BUILD_BENCHMARKS"] = False
tc.generate()
def build(self):
apply_conandata_patches(self)
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
copy(self, "COPYING", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
cmake = CMake(self)
cmake.install()
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
def package_info(self):
self.cpp_info.set_property("cmake_file_name", "Snappy")
self.cpp_info.set_property("cmake_target_name", "Snappy::snappy")
# TODO: back to global scope in conan v2 once cmake_find_package* generators removed
self.cpp_info.components["snappylib"].libs = ["snappy"]
if not self.options.shared:
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["snappylib"].system_libs.append("m")
# TODO: to remove in conan v2 once cmake_find_package* generators removed
self.cpp_info.names["cmake_find_package"] = "Snappy"
self.cpp_info.names["cmake_find_package_multi"] = "Snappy"
self.cpp_info.components["snappylib"].names["cmake_find_package"] = "snappy"
self.cpp_info.components["snappylib"].names["cmake_find_package_multi"] = "snappy"
self.cpp_info.components["snappylib"].set_property("cmake_target_name", "Snappy::snappy")

View File

@@ -0,0 +1,13 @@
diff --git a/snappy-stubs-internal.h b/snappy-stubs-internal.h
index 1548ed7..3b4a9f3 100644
--- a/snappy-stubs-internal.h
+++ b/snappy-stubs-internal.h
@@ -100,7 +100,7 @@
// Inlining hints.
#if HAVE_ATTRIBUTE_ALWAYS_INLINE
-#define SNAPPY_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
+#define SNAPPY_ATTRIBUTE_ALWAYS_INLINE
#else
#define SNAPPY_ATTRIBUTE_ALWAYS_INLINE
#endif // HAVE_ATTRIBUTE_ALWAYS_INLINE

View File

@@ -0,0 +1,13 @@
diff --git a/snappy.cc b/snappy.cc
index d414718..e4efb59 100644
--- a/snappy.cc
+++ b/snappy.cc
@@ -1132,7 +1132,7 @@ inline size_t AdvanceToNextTagX86Optimized(const uint8_t** ip_p, size_t* tag) {
size_t literal_len = *tag >> 2;
size_t tag_type = *tag;
bool is_literal;
-#if defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(__x86_64__)
+#if defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(__x86_64__) && ( (!defined(__clang__) && !defined(__APPLE__)) || (!defined(__APPLE__) && defined(__clang__) && (__clang_major__ >= 9)) || (defined(__APPLE__) && defined(__clang__) && (__clang_major__ > 11)) )
// TODO clang misses the fact that the (c & 3) already correctly
// sets the zero flag.
asm("and $3, %k[tag_type]\n\t"

View File

@@ -0,0 +1,14 @@
Fixes the following error:
error: inlining failed in call to always_inline size_t snappy::AdvanceToNextTag(const uint8_t**, size_t*): function body can be overwritten at link time
--- snappy-stubs-internal.h
+++ snappy-stubs-internal.h
@@ -100,7 +100,7 @@
// Inlining hints.
#ifdef HAVE_ATTRIBUTE_ALWAYS_INLINE
-#define SNAPPY_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
+#define SNAPPY_ATTRIBUTE_ALWAYS_INLINE
#else
#define SNAPPY_ATTRIBUTE_ALWAYS_INLINE
#endif

View File

@@ -0,0 +1,12 @@
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -69,7 +69,7 @@
- # Use -Werror for clang only.
+if(0)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
-
+endif()

View File

@@ -0,0 +1,12 @@
asm clobbers do not work for clang < 9 and apple-clang < 11 (found by SpaceIm)
--- snappy.cc
+++ snappy.cc
@@ -1026,7 +1026,7 @@
size_t literal_len = *tag >> 2;
size_t tag_type = *tag;
bool is_literal;
-#if defined(__GNUC__) && defined(__x86_64__)
+#if defined(__GNUC__) && defined(__x86_64__) && ( (!defined(__clang__) && !defined(__APPLE__)) || (!defined(__APPLE__) && defined(__clang__) && (__clang_major__ >= 9)) || (defined(__APPLE__) && defined(__clang__) && (__clang_major__ > 11)) )
// TODO clang misses the fact that the (c & 3) already correctly
// sets the zero flag.
asm("and $3, %k[tag_type]\n\t"

View File

@@ -0,0 +1,20 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -53,8 +53,6 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_definitions(-D_HAS_EXCEPTIONS=0)
# Disable RTTI.
- string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# Use -Wall for clang and gcc.
if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
@@ -78,8 +76,6 @@ endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
# Disable RTTI.
- string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make

12
external/soci/conandata.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
sources:
"4.0.3":
url: "https://github.com/SOCI/soci/archive/v4.0.3.tar.gz"
sha256: "4b1ff9c8545c5d802fbe06ee6cd2886630e5c03bf740e269bb625b45cf934928"
patches:
"4.0.3":
- patch_file: "patches/0001-Remove-hardcoded-INSTALL_NAME_DIR-for-relocatable-li.patch"
patch_description: "Generate relocatable libraries on MacOS"
patch_type: "portability"
- patch_file: "patches/0002-Fix-soci_backend.patch"
patch_description: "Fix variable names for dependencies"
patch_type: "conan"

212
external/soci/conanfile.py vendored Normal file
View File

@@ -0,0 +1,212 @@
from conan import ConanFile
from conan.tools.build import check_min_cppstd
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, rmdir
from conan.tools.microsoft import is_msvc
from conan.tools.scm import Version
from conan.errors import ConanInvalidConfiguration
import os
required_conan_version = ">=1.55.0"
class SociConan(ConanFile):
name = "soci"
homepage = "https://github.com/SOCI/soci"
url = "https://github.com/conan-io/conan-center-index"
description = "The C++ Database Access Library "
topics = ("mysql", "odbc", "postgresql", "sqlite3")
license = "BSL-1.0"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
"empty": [True, False],
"with_sqlite3": [True, False],
"with_db2": [True, False],
"with_odbc": [True, False],
"with_oracle": [True, False],
"with_firebird": [True, False],
"with_mysql": [True, False],
"with_postgresql": [True, False],
"with_boost": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
"empty": False,
"with_sqlite3": False,
"with_db2": False,
"with_odbc": False,
"with_oracle": False,
"with_firebird": False,
"with_mysql": False,
"with_postgresql": False,
"with_boost": False,
}
def export_sources(self):
export_conandata_patches(self)
def layout(self):
cmake_layout(self, src_folder="src")
def config_options(self):
if self.settings.os == "Windows":
self.options.rm_safe("fPIC")
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
def requirements(self):
if self.options.with_sqlite3:
self.requires("sqlite3/3.41.1")
if self.options.with_odbc and self.settings.os != "Windows":
self.requires("odbc/2.3.11")
if self.options.with_mysql:
self.requires("libmysqlclient/8.0.31")
if self.options.with_postgresql:
self.requires("libpq/14.7")
if self.options.with_boost:
self.requires("boost/1.81.0")
@property
def _minimum_compilers_version(self):
return {
"Visual Studio": "14",
"gcc": "4.8",
"clang": "3.8",
"apple-clang": "8.0"
}
def validate(self):
if self.settings.compiler.get_safe("cppstd"):
check_min_cppstd(self, 11)
compiler = str(self.settings.compiler)
compiler_version = Version(self.settings.compiler.version.value)
if compiler not in self._minimum_compilers_version:
self.output.warning("{} recipe lacks information about the {} compiler support.".format(self.name, self.settings.compiler))
elif compiler_version < self._minimum_compilers_version[compiler]:
raise ConanInvalidConfiguration("{} requires a {} version >= {}".format(self.name, compiler, compiler_version))
prefix = "Dependencies for"
message = "not configured in this conan package."
if self.options.with_db2:
# self.requires("db2/0.0.0") # TODO add support for db2
raise ConanInvalidConfiguration("{} DB2 {} ".format(prefix, message))
if self.options.with_oracle:
# self.requires("oracle_db/0.0.0") # TODO add support for oracle
raise ConanInvalidConfiguration("{} ORACLE {} ".format(prefix, message))
if self.options.with_firebird:
# self.requires("firebird/0.0.0") # TODO add support for firebird
raise ConanInvalidConfiguration("{} firebird {} ".format(prefix, message))
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
tc = CMakeToolchain(self)
tc.variables["SOCI_SHARED"] = self.options.shared
tc.variables["SOCI_STATIC"] = not self.options.shared
tc.variables["SOCI_TESTS"] = False
tc.variables["SOCI_CXX11"] = True
tc.variables["SOCI_EMPTY"] = self.options.empty
tc.variables["WITH_SQLITE3"] = self.options.with_sqlite3
tc.variables["WITH_DB2"] = self.options.with_db2
tc.variables["WITH_ODBC"] = self.options.with_odbc
tc.variables["WITH_ORACLE"] = self.options.with_oracle
tc.variables["WITH_FIREBIRD"] = self.options.with_firebird
tc.variables["WITH_MYSQL"] = self.options.with_mysql
tc.variables["WITH_POSTGRESQL"] = self.options.with_postgresql
tc.variables["WITH_BOOST"] = self.options.with_boost
tc.generate()
deps = CMakeDeps(self)
deps.generate()
def build(self):
apply_conandata_patches(self)
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
copy(self, "LICENSE_1_0.txt", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
cmake = CMake(self)
cmake.install()
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
def package_info(self):
self.cpp_info.set_property("cmake_file_name", "SOCI")
target_suffix = "" if self.options.shared else "_static"
lib_prefix = "lib" if is_msvc(self) and not self.options.shared else ""
version = Version(self.version)
lib_suffix = "_{}_{}".format(version.major, version.minor) if self.settings.os == "Windows" else ""
# soci_core
self.cpp_info.components["soci_core"].set_property("cmake_target_name", "SOCI::soci_core{}".format(target_suffix))
self.cpp_info.components["soci_core"].libs = ["{}soci_core{}".format(lib_prefix, lib_suffix)]
if self.options.with_boost:
self.cpp_info.components["soci_core"].requires.append("boost::boost")
# soci_empty
if self.options.empty:
self.cpp_info.components["soci_empty"].set_property("cmake_target_name", "SOCI::soci_empty{}".format(target_suffix))
self.cpp_info.components["soci_empty"].libs = ["{}soci_empty{}".format(lib_prefix, lib_suffix)]
self.cpp_info.components["soci_empty"].requires = ["soci_core"]
# soci_sqlite3
if self.options.with_sqlite3:
self.cpp_info.components["soci_sqlite3"].set_property("cmake_target_name", "SOCI::soci_sqlite3{}".format(target_suffix))
self.cpp_info.components["soci_sqlite3"].libs = ["{}soci_sqlite3{}".format(lib_prefix, lib_suffix)]
self.cpp_info.components["soci_sqlite3"].requires = ["soci_core", "sqlite3::sqlite3"]
# soci_odbc
if self.options.with_odbc:
self.cpp_info.components["soci_odbc"].set_property("cmake_target_name", "SOCI::soci_odbc{}".format(target_suffix))
self.cpp_info.components["soci_odbc"].libs = ["{}soci_odbc{}".format(lib_prefix, lib_suffix)]
self.cpp_info.components["soci_odbc"].requires = ["soci_core"]
if self.settings.os == "Windows":
self.cpp_info.components["soci_odbc"].system_libs.append("odbc32")
else:
self.cpp_info.components["soci_odbc"].requires.append("odbc::odbc")
# soci_mysql
if self.options.with_mysql:
self.cpp_info.components["soci_mysql"].set_property("cmake_target_name", "SOCI::soci_mysql{}".format(target_suffix))
self.cpp_info.components["soci_mysql"].libs = ["{}soci_mysql{}".format(lib_prefix, lib_suffix)]
self.cpp_info.components["soci_mysql"].requires = ["soci_core", "libmysqlclient::libmysqlclient"]
# soci_postgresql
if self.options.with_postgresql:
self.cpp_info.components["soci_postgresql"].set_property("cmake_target_name", "SOCI::soci_postgresql{}".format(target_suffix))
self.cpp_info.components["soci_postgresql"].libs = ["{}soci_postgresql{}".format(lib_prefix, lib_suffix)]
self.cpp_info.components["soci_postgresql"].requires = ["soci_core", "libpq::libpq"]
# TODO: to remove in conan v2 once cmake_find_package* generators removed
self.cpp_info.names["cmake_find_package"] = "SOCI"
self.cpp_info.names["cmake_find_package_multi"] = "SOCI"
self.cpp_info.components["soci_core"].names["cmake_find_package"] = "soci_core{}".format(target_suffix)
self.cpp_info.components["soci_core"].names["cmake_find_package_multi"] = "soci_core{}".format(target_suffix)
if self.options.empty:
self.cpp_info.components["soci_empty"].names["cmake_find_package"] = "soci_empty{}".format(target_suffix)
self.cpp_info.components["soci_empty"].names["cmake_find_package_multi"] = "soci_empty{}".format(target_suffix)
if self.options.with_sqlite3:
self.cpp_info.components["soci_sqlite3"].names["cmake_find_package"] = "soci_sqlite3{}".format(target_suffix)
self.cpp_info.components["soci_sqlite3"].names["cmake_find_package_multi"] = "soci_sqlite3{}".format(target_suffix)
if self.options.with_odbc:
self.cpp_info.components["soci_odbc"].names["cmake_find_package"] = "soci_odbc{}".format(target_suffix)
self.cpp_info.components["soci_odbc"].names["cmake_find_package_multi"] = "soci_odbc{}".format(target_suffix)
if self.options.with_mysql:
self.cpp_info.components["soci_mysql"].names["cmake_find_package"] = "soci_mysql{}".format(target_suffix)
self.cpp_info.components["soci_mysql"].names["cmake_find_package_multi"] = "soci_mysql{}".format(target_suffix)
if self.options.with_postgresql:
self.cpp_info.components["soci_postgresql"].names["cmake_find_package"] = "soci_postgresql{}".format(target_suffix)
self.cpp_info.components["soci_postgresql"].names["cmake_find_package_multi"] = "soci_postgresql{}".format(target_suffix)

View File

@@ -0,0 +1,39 @@
From d491bf7b5040d314ffd0c6310ba01f78ff44c85e Mon Sep 17 00:00:00 2001
From: Rasmus Thomsen <rasmus.thomsen@dampsoft.de>
Date: Fri, 14 Apr 2023 09:16:29 +0200
Subject: [PATCH] Remove hardcoded INSTALL_NAME_DIR for relocatable libraries
on MacOS
---
cmake/SociBackend.cmake | 2 +-
src/core/CMakeLists.txt | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/cmake/SociBackend.cmake b/cmake/SociBackend.cmake
index 5d4ef0df..39fe1f77 100644
--- a/cmake/SociBackend.cmake
+++ b/cmake/SociBackend.cmake
@@ -171,7 +171,7 @@ macro(soci_backend NAME)
set_target_properties(${THIS_BACKEND_TARGET}
PROPERTIES
SOVERSION ${${PROJECT_NAME}_SOVERSION}
- INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/lib)
+ )
if(APPLE)
set_target_properties(${THIS_BACKEND_TARGET}
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3e7deeae..f9eae564 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -59,7 +59,6 @@ if (SOCI_SHARED)
PROPERTIES
VERSION ${SOCI_VERSION}
SOVERSION ${SOCI_SOVERSION}
- INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/lib
CLEAN_DIRECT_OUTPUT 1)
endif()
--
2.25.1

View File

@@ -0,0 +1,24 @@
diff --git a/cmake/SociBackend.cmake b/cmake/SociBackend.cmake
index 0a664667..3fa2ed95 100644
--- a/cmake/SociBackend.cmake
+++ b/cmake/SociBackend.cmake
@@ -31,14 +31,13 @@ macro(soci_backend_deps_found NAME DEPS SUCCESS)
if(NOT DEPEND_FOUND)
list(APPEND DEPS_NOT_FOUND ${dep})
else()
- string(TOUPPER "${dep}" DEPU)
- if( ${DEPU}_INCLUDE_DIR )
- list(APPEND DEPS_INCLUDE_DIRS ${${DEPU}_INCLUDE_DIR})
+ if( ${dep}_INCLUDE_DIR )
+ list(APPEND DEPS_INCLUDE_DIRS ${${dep}_INCLUDE_DIR})
endif()
- if( ${DEPU}_INCLUDE_DIRS )
- list(APPEND DEPS_INCLUDE_DIRS ${${DEPU}_INCLUDE_DIRS})
+ if( ${dep}_INCLUDE_DIRS )
+ list(APPEND DEPS_INCLUDE_DIRS ${${dep}_INCLUDE_DIRS})
endif()
- list(APPEND DEPS_LIBRARIES ${${DEPU}_LIBRARIES})
+ list(APPEND DEPS_LIBRARIES ${${dep}_LIBRARIES})
endif()
endforeach()

194
external/wasmedge/conandata.yml vendored Normal file
View File

@@ -0,0 +1,194 @@
sources:
"0.13.5":
Windows:
"x86_64":
Visual Studio:
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.13.5/WasmEdge-0.13.5-windows.zip"
sha256: "db533289ba26ec557b5193593c9ed03db75be3bc7aa737e2caa5b56b8eef888a"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.13.5/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Linux:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.13.5/WasmEdge-0.13.5-manylinux2014_x86_64.tar.gz"
sha256: "3686e0226871bf17b62ec57e1c15778c2947834b90af0dfad14f2e0202bf9284"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.13.5/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.13.5/WasmEdge-0.13.5-manylinux2014_aarch64.tar.gz"
sha256: "472de88e0257c539c120b33fdd1805e1e95063121acc2df1d5626e4676b93529"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Macos:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.13.5/WasmEdge-0.13.5-darwin_x86_64.tar.gz"
sha256: "b7fdfaf59805951241f47690917b501ddfa06d9b6f7e0262e44e784efe4a7b33"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.13.5/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.13.5/WasmEdge-0.13.5-darwin_arm64.tar.gz"
sha256: "acc93721210294ced0887352f360e42e46dcc05332e6dd78c1452fb3a35d5255"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.13.5/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Android:
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.13.5/WasmEdge-0.13.5-android_aarch64.tar.gz"
sha256: "59a0d68a0c7368b51cc65cb5a44a68037d79fd449883ef42792178d57c8784a8"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.13.5/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"0.11.2":
Windows:
"x86_64":
Visual Studio:
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.2/WasmEdge-0.11.2-windows.zip"
sha256: "ca49b98c0cf5f187e08c3ba71afc8d71365fde696f10b4219379a4a4d1a91e6d"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.2/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Linux:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.2/WasmEdge-0.11.2-manylinux2014_x86_64.tar.gz"
sha256: "784bf1eb25928e2cf02aa88e9372388fad682b4a188485da3cd9162caeedf143"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.2/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.2/WasmEdge-0.11.2-manylinux2014_aarch64.tar.gz"
sha256: "a2766a4c1edbaea298a30e5431a4e795003a10d8398a933d923f23d4eb4fa5d1"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Macos:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.2/WasmEdge-0.11.2-darwin_x86_64.tar.gz"
sha256: "aedec53f29b1e0b657e46e67dba3e2f32a2924f4d9136e60073ea1aba3073e70"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.2/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.2/WasmEdge-0.11.2-darwin_arm64.tar.gz"
sha256: "fe391df90e1eee69cf1e976f5ddf60c20f29b651710aaa4fc03e2ab4fe52c0d3"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.2/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Android:
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.2/WasmEdge-0.11.2-android_aarch64.tar.gz"
sha256: "69e308f5927c753b2bb5639569d10219b60598174d8b304bdf310093fd7b2464"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.2/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"0.11.1":
Windows:
"x86_64":
Visual Studio:
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.1/WasmEdge-0.11.1-windows.zip"
sha256: "c86f6384555a0484a5dd81faba5636bba78f5e3d6eaf627d880e34843f9e24bf"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Linux:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.1/WasmEdge-0.11.1-manylinux2014_x86_64.tar.gz"
sha256: "76ce4ea0eb86adfa52c73f6c6b44383626d94990e0923cae8b1e6f060ef2bf5b"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.1/WasmEdge-0.11.1-manylinux2014_aarch64.tar.gz"
sha256: "cb9ea32932360463991cfda80e09879b2cf6c69737f12f3f2b371cd0af4e9ce8"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Macos:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.1/WasmEdge-0.11.1-darwin_x86_64.tar.gz"
sha256: "56df2b00669c25b8143ea2c17370256cd6a33f3b316d3b47857dd38d603cb69a"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.1/WasmEdge-0.11.1-darwin_arm64.tar.gz"
sha256: "82f7da1a7a36ec1923fb045193784dd090a03109e84da042af97297205a71f08"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Android:
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.11.1/WasmEdge-0.11.1-android_aarch64.tar.gz"
sha256: "af8694e93bf72ac5506450d4caebccc340fbba254dca3d58ec0712e96ec9dedd"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.11.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"0.10.0":
Windows:
"x86_64":
Visual Studio:
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.10.0/WasmEdge-0.10.0-windows.zip"
sha256: "63b8a02cced52a723aa283dba02bbe887656256ecca69bb0fff17872c0fb5ebc"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.10.0/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Linux:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.10.0/WasmEdge-0.10.0-manylinux2014_x86_64.tar.gz"
sha256: "4c1ffca9fd8cbdeb8f0951ddaffbbefe81ae123d5b80f61e80ea8d9b56853cde"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.10.0/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.10.0/WasmEdge-0.10.0-manylinux2014_aarch64.tar.gz"
sha256: "c000bf96d0a73a1d360659246c0806c2ce78620b6f78c1147fbf9e2be0280bd9"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.10.0/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"0.9.1":
Windows:
"x86_64":
Visual Studio:
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.9.1/WasmEdge-0.9.1-windows.zip"
sha256: "68240d8aee23d44db5cc252d8c1cf5d0c77ab709a122af2747a4b836ba461671"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.9.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Linux:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.9.1/WasmEdge-0.9.1-manylinux2014_x86_64.tar.gz"
sha256: "bcb6fe3d6e30db0d0aa267ec3bd9b7248f8c8c387620cef4049d682d293c8371"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.9.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.9.1/WasmEdge-0.9.1-manylinux2014_aarch64.tar.gz"
sha256: "515bcac3520cd546d9d14372b7930ab48b43f1c5dc258a9f61a82b22c0107eef"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.9.1/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"0.9.0":
Windows:
"x86_64":
Visual Studio:
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.9.0/WasmEdge-0.9.0-windows.zip"
sha256: "f81bfea4cf09053510e3e74c16c1ee010fc93def8a7e78744443b950f0011c3b"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.9.0/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Linux:
"x86_64":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.9.0/WasmEdge-0.9.0-manylinux2014_x86_64.tar.gz"
sha256: "27847f15e4294e707486458e857d7cb11806481bb67a26f076a717a1446827ed"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.9.0/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.9.0/WasmEdge-0.9.0-manylinux2014_aarch64.tar.gz"
sha256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.9.0/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
Macos:
"armv8":
"gcc":
- url: "https://github.com/WasmEdge/WasmEdge/releases/download/0.9.0/WasmEdge-0.9.0-darwin_arm64.tar.gz"
sha256: "236a407a646f746ab78a1d0a39fa4e85fe28eae219b1635ba49f908d7944686d"
- url: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/0.9.0/LICENSE"
sha256: "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"

92
external/wasmedge/conanfile.py vendored Normal file
View File

@@ -0,0 +1,92 @@
from conan import ConanFile
from conan.tools.files import get, copy, download
from conan.tools.scm import Version
from conan.errors import ConanInvalidConfiguration
import os
required_conan_version = ">=1.53.0"
class WasmedgeConan(ConanFile):
name = "wasmedge"
description = ("WasmEdge is a lightweight, high-performance, and extensible WebAssembly runtime"
"for cloud native, edge, and decentralized applications."
"It powers serverless apps, embedded functions, microservices, smart contracts, and IoT devices.")
license = "Apache-2.0"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/WasmEdge/WasmEdge/"
topics = ("webassembly", "wasm", "wasi", "emscripten")
package_type = "shared-library"
settings = "os", "arch", "compiler", "build_type"
@property
def _compiler_alias(self):
return {
"Visual Studio": "Visual Studio",
# "Visual Studio": "msvc",
"msvc": "msvc",
}.get(str(self.info.settings.compiler), "gcc")
def configure(self):
self.settings.compiler.rm_safe("libcxx")
self.settings.compiler.rm_safe("cppstd")
def validate(self):
try:
self.conan_data["sources"][self.version][str(self.settings.os)][str(self.settings.arch)][self._compiler_alias]
except KeyError:
raise ConanInvalidConfiguration("Binaries for this combination of version/os/arch/compiler are not available")
def package_id(self):
del self.info.settings.compiler.version
self.info.settings.compiler = self._compiler_alias
def build(self):
# This is packaging binaries so the download needs to be in build
get(self, **self.conan_data["sources"][self.version][str(self.settings.os)][str(self.settings.arch)][self._compiler_alias][0],
destination=self.source_folder, strip_root=True)
download(self, filename="LICENSE",
**self.conan_data["sources"][self.version][str(self.settings.os)][str(self.settings.arch)][self._compiler_alias][1])
def package(self):
copy(self, pattern="*.h", dst=os.path.join(self.package_folder, "include"), src=os.path.join(self.source_folder, "include"), keep_path=True)
copy(self, pattern="*.inc", dst=os.path.join(self.package_folder, "include"), src=os.path.join(self.source_folder, "include"), keep_path=True)
srclibdir = os.path.join(self.source_folder, "lib64" if self.settings.os == "Linux" else "lib")
srcbindir = os.path.join(self.source_folder, "bin")
dstlibdir = os.path.join(self.package_folder, "lib")
dstbindir = os.path.join(self.package_folder, "bin")
if Version(self.version) >= "0.11.1":
copy(self, pattern="wasmedge.lib", src=srclibdir, dst=dstlibdir, keep_path=False)
copy(self, pattern="wasmedge.dll", src=srcbindir, dst=dstbindir, keep_path=False)
copy(self, pattern="libwasmedge.so*", src=srclibdir, dst=dstlibdir, keep_path=False)
copy(self, pattern="libwasmedge*.dylib", src=srclibdir, dst=dstlibdir, keep_path=False)
else:
copy(self, pattern="wasmedge_c.lib", src=srclibdir, dst=dstlibdir, keep_path=False)
copy(self, pattern="wasmedge_c.dll", src=srcbindir, dst=dstbindir, keep_path=False)
copy(self, pattern="libwasmedge_c.so*", src=srclibdir, dst=dstlibdir, keep_path=False)
copy(self, pattern="libwasmedge_c*.dylib", src=srclibdir, dst=dstlibdir, keep_path=False)
copy(self, pattern="wasmedge*", src=srcbindir, dst=dstbindir, keep_path=False)
copy(self, pattern="LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"), keep_path=False)
def package_info(self):
if Version(self.version) >= "0.11.1":
self.cpp_info.libs = ["wasmedge"]
else:
self.cpp_info.libs = ["wasmedge_c"]
bindir = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH environment variable: {}".format(bindir))
self.env_info.PATH.append(bindir)
if self.settings.os == "Windows":
self.cpp_info.system_libs.append("ws2_32")
self.cpp_info.system_libs.append("wsock32")
self.cpp_info.system_libs.append("shlwapi")
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.system_libs.append("m")
self.cpp_info.system_libs.append("dl")
self.cpp_info.system_libs.append("rt")
self.cpp_info.system_libs.append("pthread")

View File

@@ -3,27 +3,27 @@ RIPPLED_ROOT="../src/ripple"
echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/'
echo '// Generated using generate_sfcodes.sh'
cat $RIPPLED_ROOT/protocol/impl/SField.cpp | grep -E '^CONSTRUCT_' |
sed 's/UINT16/1/g' |
sed 's/UINT32/2/g' |
sed 's/UINT64/3/g' |
sed 's/HASH128/4/g' |
sed 's/HASH256/5/g' |
sed 's/UINT128/4/g' |
sed 's/UINT256/5/g' |
sed 's/AMOUNT/6/g' |
sed 's/VL/7/g' | sed 's/Import7/ImportVL/g' |
sed 's/ACCOUNT/8/g' |
sed 's/OBJECT/14/g' |
sed 's/ARRAY/15/g' |
sed 's/UINT8/16/g' |
sed 's/HASH160/17/g' |
sed 's/UINT160/17/g' |
sed 's/PATHSET/18/g' |
sed 's/VECTOR256/19/g' |
sed 's/UINT96/20/g' |
sed 's/UINT192/21/g' |
sed 's/UINT384/22/g' |
sed 's/UINT512/23/g' |
sed 's/UINT16,/1,/g' |
sed 's/UINT32,/2,/g' |
sed 's/UINT64,/3,/g' |
sed 's/HASH128,/4,/g' |
sed 's/HASH256,/5,/g' |
sed 's/UINT128,/4,/g' |
sed 's/UINT256,/5,/g' |
sed 's/AMOUNT,/6,/g' |
sed 's/VL,/7,/g' |
sed 's/ACCOUNT,/8,/g' |
sed 's/OBJECT,/14,/g' |
sed 's/ARRAY,/15,/g' |
sed 's/UINT8,/16,/g' |
sed 's/HASH160,/17,/g' |
sed 's/UINT160,/17,/g' |
sed 's/PATHSET,/18,/g' |
sed 's/VECTOR256,/19,/g' |
sed 's/UINT96,/20,/g' |
sed 's/UINT192,/21,/g' |
sed 's/UINT384,/22,/g' |
sed 's/UINT512,/23,/g' |
grep -Eo '"([^"]+)", *([0-9]+), *([0-9]+)' |
sed 's/"//g' | sed 's/ *//g' | sed 's/,/ /g' |
awk '{print ("#define sf"$1" (("$2"U << 16U) + "$3"U)")}'

View File

@@ -637,43 +637,55 @@ int64_t hook(uint32_t r)
{
previous_member[0] = 'V';
for (int i = 1; GUARD(32), i < 32; ++i)
for (int tbl = 1; GUARD(2), tbl <= 2; ++tbl)
{
previous_member[1] = i < 2 ? 'R' : i < 12 ? 'H' : 'S';
previous_member[2] =
i == 0 ? 'R' :
i == 1 ? 'D' :
i < 12 ? i - 2 :
i - 12;
uint8_t vote_key[32];
if (state(SBUF(vote_key), SBUF(previous_member)) == 32)
for (int i = 0; GUARD(66), i < 32; ++i)
{
uint8_t vote_count = 0;
previous_member[1] = i < 2 ? 'R' : i < 12 ? 'H' : 'S';
previous_member[2] =
i == 0 ? 'R' :
i == 1 ? 'D' :
i < 12 ? i - 2 :
i - 12;
previous_member[3] = tbl;
// find and decrement the vote counter
vote_key[0] = 'C';
vote_key[1] = previous_member[1];
vote_key[2] = previous_member[2];
if (state(&vote_count, 1, SBUF(vote_key)) == 1)
uint8_t vote_key[32] = {};
uint8_t ts =
previous_member[1] == 'H' ? 32 : // hook topics are a 32 byte hook hash
previous_member[1] == 'S' ? 20 : // account topics are a 20 byte account ID
8; // reward topics are an 8 byte le xfl
uint8_t padding = 32 - ts;
if (state(vote_key + padding, ts, SBUF(previous_member)) == ts)
{
// if we're down to 1 vote then delete state
if (vote_count <= 1)
{
ASSERT(state_set(0,0, SBUF(vote_key)) == 0);
trace_num(SBUF("Decrement vote count deleted"), vote_count);
}
else // otherwise decrement
{
vote_count--;
ASSERT(state_set(&vote_count, 1, SBUF(vote_key)) == 1);
trace_num(SBUF("Decrement vote count to"), vote_count);
}
}
uint8_t vote_count = 0;
// delete the vote entry
ASSERT(state_set(0,0, SBUF(previous_member)) == 0);
trace(SBUF("Vote entry deleted"), vote_key, 32, 1);
// find and decrement the vote counter
vote_key[0] = 'C';
vote_key[1] = previous_member[1];
vote_key[2] = previous_member[2];
vote_key[3] = tbl;
if (state(&vote_count, 1, SBUF(vote_key)) == 1)
{
// if we're down to 1 vote then delete state
if (vote_count <= 1)
{
ASSERT(state_set(0,0, SBUF(vote_key)) == 0);
trace_num(SBUF("Decrement vote count deleted"), vote_count);
}
else // otherwise decrement
{
vote_count--;
ASSERT(state_set(&vote_count, 1, SBUF(vote_key)) == 1);
trace_num(SBUF("Decrement vote count to"), vote_count);
}
}
// delete the vote entry
ASSERT(state_set(0,0, SBUF(previous_member)) == 0);
trace(SBUF("Vote entry deleted"), vote_key, 32, 1);
}
}
}

View File

@@ -83,14 +83,15 @@
#define sfHookInstructionCount ((3U << 16U) + 17U)
#define sfHookReturnCode ((3U << 16U) + 18U)
#define sfReferenceCount ((3U << 16U) + 19U)
#define sfTouchCount ((3U << 16U) + 97U)
#define sfAccountIndex ((3U << 16U) + 98U)
#define sfAccountCount ((3U << 16U) + 99U)
#define sfRewardAccumulator ((3U << 16U) + 100U)
#define sfEmailHash ((4U << 16U) + 1U)
#define sfTakerPaysCurrency ((10U << 16U) + 1U)
#define sfTakerPaysIssuer ((10U << 16U) + 2U)
#define sfTakerGetsCurrency ((10U << 16U) + 3U)
#define sfTakerGetsIssuer ((10U << 16U) + 4U)
#define sfTakerPaysCurrency ((17U << 16U) + 1U)
#define sfTakerPaysIssuer ((17U << 16U) + 2U)
#define sfTakerGetsCurrency ((17U << 16U) + 3U)
#define sfTakerGetsIssuer ((17U << 16U) + 4U)
#define sfLedgerHash ((5U << 16U) + 1U)
#define sfParentHash ((5U << 16U) + 2U)
#define sfTransactionHash ((5U << 16U) + 3U)

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,6 @@
# debugging.
set -ex
set -e
echo "START BUILDING (HOST)"
echo "Cleaning previously built binary"
@@ -19,7 +17,12 @@ if [[ "$GITHUB_REPOSITORY" == "" ]]; then
BUILD_CORES=8
fi
CONTAINER_NAME=xahaud_cached_builder_$(echo "$GITHUB_ACTOR" | awk '{print tolower($0)}')
# Ensure still works outside of GH Actions by setting these to /dev/null
# GA will run this script and then delete it at the end of the job
JOB_CLEANUP_SCRIPT=${JOB_CLEANUP_SCRIPT:-/dev/null}
NORMALIZED_WORKFLOW=$(echo "$GITHUB_WORKFLOW" | tr -c 'a-zA-Z0-9' '-')
NORMALIZED_REF=$(echo "$GITHUB_REF" | tr -c 'a-zA-Z0-9' '-')
CONTAINER_NAME="xahaud_cached_builder_${NORMALIZED_WORKFLOW}-${NORMALIZED_REF}"
echo "-- BUILD CORES: $BUILD_CORES"
echo "-- GITHUB_REPOSITORY: $GITHUB_REPOSITORY"
@@ -43,7 +46,7 @@ fi
STATIC_CONTAINER=$(docker ps -a | grep $CONTAINER_NAME |wc -l)
#if [[ "$STATIC_CONTAINER" -gt "0" && "$GITHUB_REPOSITORY" != "" ]]; then
# if [[ "$STATIC_CONTAINER" -gt "0" && "$GITHUB_REPOSITORY" != "" ]]; then
if false; then
echo "Static container, execute in static container to have max. cache"
docker start $CONTAINER_NAME
@@ -62,6 +65,8 @@ else
# GH Action, runner
echo "GH Action, runner, clean & re-create create persistent container"
docker rm -f $CONTAINER_NAME
echo "echo 'Stopping container: $CONTAINER_NAME'" >> "$JOB_CLEANUP_SCRIPT"
echo "docker stop --time=15 \"$CONTAINER_NAME\" || echo 'Failed to stop container or container not running'" >> "$JOB_CLEANUP_SCRIPT"
docker run -di --user 0:$(id -g) --name $CONTAINER_NAME -v /data/builds:/data/builds -v `pwd`:/io --network host ghcr.io/foobarwidget/holy-build-box-x64 /hbb_exe/activate-exec bash
docker exec -i $CONTAINER_NAME /hbb_exe/activate-exec bash -x /io/build-full.sh "$GITHUB_REPOSITORY" "$GITHUB_SHA" "$BUILD_CORES" "$GITHUB_RUN_NUMBER"
docker stop $CONTAINER_NAME

View File

@@ -0,0 +1,48 @@
cmake_minimum_required(VERSION 3.11)
project(ed25519
LANGUAGES C
)
if(PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/output/$<CONFIG>/lib")
endif()
if(NOT TARGET OpenSSL::SSL)
find_package(OpenSSL)
endif()
add_library(ed25519 STATIC
ed25519.c
)
add_library(ed25519::ed25519 ALIAS ed25519)
target_link_libraries(ed25519 PUBLIC OpenSSL::SSL)
include(GNUInstallDirs)
#[=========================================================[
NOTE for macos:
https://github.com/floodyberry/ed25519-donna/issues/29
our source for ed25519-donna-portable.h has been
patched to workaround this.
#]=========================================================]
target_include_directories(ed25519 PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)
install(
TARGETS ed25519
EXPORT ${PROJECT_NAME}-exports
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
install(
EXPORT ${PROJECT_NAME}-exports
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
FILE ${PROJECT_NAME}-targets.cmake
NAMESPACE ${PROJECT_NAME}::
)
install(
FILES ed25519.h
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

820
src/quickjs/buffer-utils.c Normal file
View File

@@ -0,0 +1,820 @@
#include "defines.h"
#include "char-utils.h"
#include "buffer-utils.h"
#include "utils.h"
#ifdef _WIN32
#include <windows.h>
#elif defined(HAVE_TERMIOS_H)
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#endif
#include "debug.h"
/**
* \addtogroup buffer-utils
* @{
*/
size_t
ansi_length(const char* str, size_t len) {
size_t i, n = 0, p;
for(i = 0; i < len;) {
if(str[i] == 0x1b && (p = ansi_skip(&str[i], len - i)) > 0) {
i += p;
continue;
}
n++;
i++;
}
return n;
}
size_t
ansi_skip(const char* str, size_t len) {
size_t pos = 0;
if(str[pos] == 0x1b) {
if(++pos < len && str[pos] == '[') {
while(++pos < len)
if(is_alphanumeric_char(str[pos]))
break;
if(++pos < len && str[pos] == '~')
++pos;
return pos;
}
}
return 0;
}
size_t
ansi_truncate(const char* str, size_t len, size_t limit) {
size_t i, n = 0, p;
for(i = 0; i < len;) {
if((p = ansi_skip(&str[i], len - i)) > 0) {
i += p;
continue;
}
n += is_escape_char(str[i]) ? 2 : 1;
i++;
if(n > limit)
break;
}
return i;
}
int64_t
array_search(void* a, size_t m, size_t elsz, void* needle) {
char* ptr = a;
int64_t n, ret;
n = m / elsz;
for(ret = 0; ret < n; ret++) {
if(!memcmp(ptr, needle, elsz))
return ret;
ptr += elsz;
}
return -1;
}
char*
str_escape(const char* s) {
DynBuf dbuf;
dbuf_init2(&dbuf, 0, 0);
dbuf_put_escaped(&dbuf, s, strlen(s));
dbuf_0(&dbuf);
return (char*)dbuf.buf;
}
char*
byte_escape(const void* s, size_t n) {
DynBuf dbuf;
dbuf_init2(&dbuf, 0, 0);
dbuf_put_escaped(&dbuf, s, n);
dbuf_0(&dbuf);
return (char*)dbuf.buf;
}
size_t
byte_findb(const void* haystack, size_t hlen, const void* what, size_t wlen) {
size_t i, last;
const char* s = (const char*)haystack;
if(hlen < wlen)
return hlen;
last = hlen - wlen;
for(i = 0; i <= last; i++) {
if(byte_equal(s, wlen, what))
return i;
s++;
}
return hlen;
}
size_t
byte_finds(const void* haystack, size_t hlen, const char* what) {
return byte_findb(haystack, hlen, what, strlen(what));
}
size_t
byte_equal(const void* s, size_t n, const void* t) {
return memcmp(s, t, n) == 0;
}
void
byte_copy(void* out, size_t len, const void* in) {
char* s = (char*)out;
const char* t = (const char*)in;
size_t i;
for(i = 0; i < len; ++i)
s[i] = t[i];
}
void
byte_copyr(void* out, size_t len, const void* in) {
char* s = (char*)out + len;
const char* t = (const char*)in;
const char* u = t + len;
for(;;) {
if(t >= u)
break;
--u;
--s;
*s = *u;
}
}
size_t
byte_rchrs(const char* in, size_t len, const char needles[], size_t nn) {
const char *s = in, *end = in + len, *found = 0;
size_t i;
for(; s < end; s++) {
for(i = 0; i < nn; ++i) {
if(*s == needles[i])
found = s;
}
}
return (size_t)((found ? found : s) - in);
}
char*
dbuf_at_n(const DynBuf* db, size_t i, size_t* n, char sep) {
size_t p, l = 0;
for(p = 0; p < db->size; ++p) {
if(l == i) {
*n = byte_chr((const char*)&db->buf[p], db->size - p, sep);
return (char*)&db->buf[p];
}
if(db->buf[p] == sep)
++l;
}
*n = 0;
return 0;
}
const char*
dbuf_last_line(DynBuf* db, size_t* len) {
size_t i;
if((i = byte_rchr(db->buf, db->size, '\n')) < db->size)
i++;
else
i = 0;
if(len)
*len = db->size - i;
return (const char*)&db->buf[i];
}
int
dbuf_prepend(DynBuf* s, const uint8_t* data, size_t len) {
int ret;
if(!(ret = dbuf_reserve_start(s, len)))
memcpy(s->buf, data, len);
return 0;
}
void
dbuf_put_colorstr(DynBuf* db, const char* str, const char* color, int with_color) {
if(with_color)
dbuf_putstr(db, color);
dbuf_putstr(db, str);
if(with_color)
dbuf_putstr(db, COLOR_NONE);
}
void
dbuf_put_escaped_pred(DynBuf* db, const char* str, size_t len, int (*pred)(int)) {
size_t i = 0, j;
char c;
while(i < len) {
if((j = predicate_find(&str[i], len - i, pred))) {
dbuf_append(db, (const uint8_t*)&str[i], j);
i += j;
}
if(i == len)
break;
dbuf_putc(db, '\\');
if(str[i] == 0x1b) {
dbuf_append(db, (const uint8_t*)"x1b", 3);
} else {
int r = pred(str[i]);
dbuf_putc(db, (r > 1 && r <= 127) ? r : (c = escape_char_letter(str[i])) ? c : str[i]);
if(r == 'u' || r == 'x')
dbuf_printf(db, r == 'u' ? "%04x" : "%02x", str[i]);
}
i++;
}
}
const uint8_t escape_url_tab[256] = {
'%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%',
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '%',
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%', '%',
};
const uint8_t escape_noquote_tab[256] = {
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0x6e, 0x76, 0x66, 0x72, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
'x', 'x', 'x', 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u',
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
};
const uint8_t escape_singlequote_tab[256] = {
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0x6e, 0x76, 0x66, 0x72, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
'x', 'x', 'x', 'x', 0, 0, 0, 0, 0, 0, 0, 0x27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u',
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
};
const uint8_t escape_doublequote_tab[256] = {
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0x6e, 0x76, 0x66, 0x72, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
'x', 'x', 'x', 'x', 0, 0, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u',
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
};
const uint8_t escape_backquote_tab[256] = {
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0, 0x76, 0x66, 0, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
'x', 'x', 'x', 'x', 0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0x60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u',
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
};
void
dbuf_put_escaped_table(DynBuf* db, const char* str, size_t len, const uint8_t table[256]) {
size_t i = 0, clen;
int32_t c;
const uint8_t *pos, *end, *next;
for(pos = (const uint8_t*)str, end = pos + len; pos < end; pos = next) {
uint8_t r, ch;
if((c = unicode_from_utf8(pos, end - pos, &next)) < 0)
break;
clen = next - pos;
ch = c;
r = (clen >= 2 || c > 0xff) ? 'u' : table[c];
if(r == 'u' && clen > 1 && (c & 0xffffff00) == 0) {
r = 'x';
// ch = c >> 8;
}
if(r == '%') {
static const char hexdigits[] = "0123456789ABCDEF";
dbuf_putc(db, '%');
dbuf_putc(db, hexdigits[c >> 4]);
dbuf_putc(db, hexdigits[c & 0xf]);
} else if(c == 0x1b) {
dbuf_putstr(db, "\\x1b");
} else if(r == 'u') {
dbuf_printf(db, c > 0xffff ? "\\u{%X}" : "\\u%04x", c);
} else if(r == 'x') {
dbuf_printf(db, "\\x%02x", ch);
} else if(r) {
dbuf_putc(db, '\\');
dbuf_putc(db, (r > 1 && r <= 127) ? r : (c = escape_char_letter(ch)) ? c : ch);
} else {
dbuf_put(db, pos, next - pos);
}
i++;
}
}
void
dbuf_put_unescaped_pred(DynBuf* db, const char* str, size_t len, int (*pred)(const char*, size_t*)) {
size_t i = 0, j;
// char c;
while(i < len) {
int r = 0;
if((j = byte_chr(&str[i], len - i, '\\'))) {
dbuf_append(db, (const uint8_t*)&str[i], j);
i += j;
}
if(i == len)
break;
size_t n = 1;
if(pred) {
r = pred(&str[i + 1], &n);
if(!r && n == 1)
dbuf_putc(db, '\\');
}
if(r >= 0)
dbuf_putc(db, /*n > 1 ||*/ r ? /*(r > 1 && r < 256) ?*/ r : str[i]);
i += n;
}
}
static inline int
hexdigit(char c) {
if(c >= '0' && c <= '9')
return c - '0';
if(c >= 'a' && c <= 'f')
c -= 32;
if(c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
void
dbuf_put_unescaped_table(DynBuf* db, const char* str, size_t len, const uint8_t table[256]) {
size_t i = 0, j;
char escape_char = table == escape_url_tab ? '%' : '\\';
while(i < len) {
if((j = byte_chr(&str[i], len - i, escape_char))) {
dbuf_append(db, (const uint8_t*)&str[i], j);
i += j;
}
if(i == len)
break;
if(escape_char == '%') {
int hi = hexdigit(str[i + 1]), lo = hexdigit(str[i + 2]);
uint8_t c = (hi << 4) | (lo & 0xf);
dbuf_putc(db, c);
i += 2;
} else {
++i;
uint8_t c;
switch(str[i]) {
case 'b': c = '\b'; break;
case 't': c = '\t'; break;
case 'n': c = '\n'; break;
case 'v': c = '\v'; break;
case 'f': c = '\f'; break;
case 'r': c = '\r'; break;
default: c = str[i]; break;
}
uint8_t r = table[c];
if(!(r && r != 'x' && r != 'u')) {
dbuf_putc(db, '\\');
dbuf_putc(db, c);
} else {
dbuf_putc(db, str[i] == r ? c : r);
}
}
++i;
}
}
void
dbuf_put_escaped(DynBuf* db, const char* str, size_t len) {
return dbuf_put_escaped_table(db, str, len, escape_noquote_tab);
}
void
dbuf_put_value(DynBuf* db, JSContext* ctx, JSValueConst value) {
const char* str;
size_t len;
str = JS_ToCStringLen(ctx, &len, value);
dbuf_append(db, str, len);
JS_FreeCString(ctx, str);
}
void
dbuf_put_uint32(DynBuf* db, uint32_t num) {
char buf[FMT_ULONG];
dbuf_put(db, (const uint8_t*)buf, fmt_ulong(buf, num));
}
void
dbuf_put_atom(DynBuf* db, JSContext* ctx, JSAtom atom) {
const char* str;
str = JS_AtomToCString(ctx, atom);
dbuf_putstr(db, str);
JS_FreeCString(ctx, str);
}
int
dbuf_reserve_start(DynBuf* s, size_t len) {
if(unlikely((s->size + len) > s->allocated_size)) {
if(dbuf_realloc(s, s->size + len))
return -1;
}
if(s->size > 0)
memcpy(s->buf + len, s->buf, s->size);
s->size += len;
return 0;
}
uint8_t*
dbuf_reserve(DynBuf* s, size_t len) {
if(unlikely((s->size + len) > s->allocated_size))
if(dbuf_realloc(s, s->size + len))
return 0;
return &s->buf[s->size];
}
size_t
dbuf_token_pop(DynBuf* db, char delim) {
size_t n, p, len;
len = db->size;
for(n = db->size; n > 0;) {
if((p = byte_rchr(db->buf, n, delim)) == n) {
db->size = 0;
break;
}
if(p > 0 && db->buf[p - 1] == '\\') {
n = p - 1;
continue;
}
db->size = p;
break;
}
return len - db->size;
}
size_t
dbuf_token_push(DynBuf* db, const char* str, size_t len, char delim) {
size_t pos;
if(db->size)
dbuf_putc(db, delim);
pos = db->size;
dbuf_put_escaped_pred(db, str, len, is_dot_char);
return db->size - pos;
}
JSValue
dbuf_tostring_free(DynBuf* s, JSContext* ctx) {
JSValue r;
r = JS_NewStringLen(ctx, s->buf ? (const char*)s->buf : "", s->buf ? s->size : 0);
dbuf_free(s);
return r;
}
ssize_t
dbuf_load(DynBuf* s, const char* filename) {
FILE* fp;
size_t nbytes = 0;
if((fp = fopen(filename, "rb"))) {
char buf[4096];
size_t r;
while(!feof(fp)) {
if((r = fread(buf, 1, sizeof(buf), fp)) == 0) {
fclose(fp);
return -1;
}
dbuf_put(s, (uint8_t const*)buf, r);
nbytes += r;
}
fclose(fp);
}
return nbytes;
}
int
dbuf_vprintf(DynBuf* s, const char* fmt, va_list ap) {
s->size += vsnprintf((char*)(s->buf + s->size), s->allocated_size - s->size, fmt, ap);
return 0;
}
InputBuffer
js_input_buffer(JSContext* ctx, JSValueConst value) {
InputBuffer ret = {{{0, 0}}, 0, &input_buffer_free_default, JS_UNDEFINED, {0, INT64_MAX}};
if(js_is_typedarray(ctx, value)) {
ret.value = offset_typedarray(&ret.range, value, ctx);
} else if(js_is_arraybuffer(ctx, value) || js_is_sharedarraybuffer(ctx, value)) {
ret.value = JS_DupValue(ctx, value);
}
if(js_is_arraybuffer(ctx, ret.value) || js_is_sharedarraybuffer(ctx, ret.value)) {
block_arraybuffer(&ret.block, ret.value, ctx);
} else {
JS_ThrowTypeError(ctx, "Invalid type (%s) for input buffer", js_value_typestr(ctx, ret.value));
JS_FreeValue(ctx, ret.value);
ret.value = JS_EXCEPTION;
}
return ret;
}
#undef free
InputBuffer
js_input_chars(JSContext* ctx, JSValueConst value) {
InputBuffer ret = {{{0, 0}}, 0, &input_buffer_free_default, JS_UNDEFINED, OFFSET_INIT()};
if(JS_IsString(value)) {
ret.data = (uint8_t*)JS_ToCStringLen(ctx, &ret.size, value);
ret.value = JS_DupValue(ctx, value);
ret.free = &input_buffer_free_default;
} else {
ret = js_input_buffer(ctx, value);
}
return ret;
}
InputBuffer
js_input_args(JSContext* ctx, int argc, JSValueConst argv[]) {
InputBuffer input = js_input_chars(ctx, argv[0]);
if(argc > 1)
js_offset_length(ctx, input.size, argc - 1, argv + 1, &input.range);
return input;
}
InputBuffer
js_output_args(JSContext* ctx, int argc, JSValueConst argv[]) {
InputBuffer output = js_input_buffer(ctx, argv[0]);
if(argc > 1)
js_offset_length(ctx, output.size, argc - 1, argv + 1, &output.range);
return output;
}
BOOL
input_buffer_valid(const InputBuffer* in) {
return !JS_IsException(in->value);
}
InputBuffer
input_buffer_clone(const InputBuffer* in, JSContext* ctx) {
InputBuffer ret = js_input_buffer(ctx, in->value);
ret.pos = in->pos;
ret.size = in->size;
ret.free = in->free;
return ret;
}
void
input_buffer_dump(const InputBuffer* in, DynBuf* db) {
dbuf_printf(db, "(InputBuffer){ .data = %p, .size = %lu, .pos = %lu, .free = %p }", in->data, (unsigned long)in->size, (unsigned long)in->pos, in->free);
}
void
input_buffer_free(InputBuffer* in, JSContext* ctx) {
if(in->data) {
in->free(ctx, (const char*)in->data, in->value);
in->data = 0;
in->size = 0;
in->pos = 0;
in->value = JS_UNDEFINED;
}
}
const uint8_t*
input_buffer_peek(InputBuffer* in, size_t* lenp) {
input_buffer_peekc(in, lenp);
return input_buffer_data(in) + in->pos;
}
const uint8_t*
input_buffer_get(InputBuffer* in, size_t* lenp) {
const uint8_t* ret = input_buffer_peek(in, lenp);
in->pos += *lenp;
return ret;
}
const char*
input_buffer_currentline(InputBuffer* in, size_t* len) {
size_t i;
if((i = byte_rchr(input_buffer_data(in), in->pos, '\n')) < in->pos)
i++;
if(len)
*len = in->pos - i;
return (const char*)&input_buffer_data(in)[i];
}
size_t
input_buffer_column(InputBuffer* in, size_t* len) {
size_t i;
if((i = byte_rchr(input_buffer_data(in), in->pos, '\n')) < in->pos)
i++;
return in->pos - i;
}
int
js_offset_length(JSContext* ctx, int64_t size, int argc, JSValueConst argv[], OffsetLength* off_len_p) {
int ret = 0;
int64_t off = 0, len = size;
if(argc >= 1 && JS_IsNumber(argv[0])) {
if(!JS_ToInt64(ctx, &off, argv[0]))
ret = 1;
if(argc >= 2 && JS_IsNumber(argv[1]))
if(!JS_ToInt64(ctx, &len, argv[1]))
ret = 2;
if(size && off != size)
off = ((off % size) + size) % size;
if(len >= 0)
len = MIN_NUM(len, size - off);
else
len = size - off;
if(off_len_p) {
off_len_p->offset = off;
off_len_p->length = len;
}
}
return ret;
}
int
js_index_range(JSContext* ctx, int64_t size, int argc, JSValueConst argv[], IndexRange* idx_rng_p) {
int ret = 0;
int64_t start = 0, end = size;
if(argc >= 1 && JS_IsNumber(argv[0])) {
if(!JS_ToInt64(ctx, &start, argv[0]))
ret = 1;
if(argc >= 2 && JS_IsNumber(argv[1]))
if(!JS_ToInt64(ctx, &end, argv[1]))
ret = 2;
if(size > 0) {
start = ((start % size) + size) % size;
end = ((end % size) + size) % size;
}
if(end > size)
end = size;
if(idx_rng_p) {
idx_rng_p->start = start;
idx_rng_p->end = end;
}
}
return ret;
}
int
screen_size(int size[2]) {
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
size[0] = csbi.srWindow.Right - csbi.srWindow.Left + 1;
size[1] = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
return 0;
#elif defined(HAVE_TERMIOS_H)
{
struct winsize w = {.ws_col = -1, .ws_row = -1};
if(isatty(STDIN_FILENO))
ioctl(STDIN_FILENO, TIOCGWINSZ, &w);
else if(isatty(STDOUT_FILENO))
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
else if(isatty(STDERR_FILENO))
ioctl(STDERR_FILENO, TIOCGWINSZ, &w);
size[0] = w.ws_col;
size[1] = w.ws_row;
return 0;
}
#else
size[0] = 80;
size[1] = 25;
return 0;
#endif
return -1;
}
#undef js_realloc_rt
void
js_dbuf_allocator(JSContext* ctx, DynBuf* s) {
dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc*)js_realloc_rt);
}
inline int
input_buffer_peekc(InputBuffer* in, size_t* lenp) {
const uint8_t *pos, *end, *next;
int cp;
pos = input_buffer_data(in) + in->pos;
end = input_buffer_data(in) + input_buffer_length(in);
cp = unicode_from_utf8(pos, end - pos, &next);
*lenp = next - pos;
return cp;
}
inline int
input_buffer_putc(InputBuffer* in, unsigned int c, JSContext* ctx) {
int len;
if(in->pos + UTF8_CHAR_LEN_MAX > in->size)
if(block_realloc(&in->block, in->pos + UTF8_CHAR_LEN_MAX, ctx))
return -1;
len = unicode_to_utf8(&in->data[in->pos], c);
in->pos += len;
return len;
}
size_t
dbuf_bitflags(DynBuf* db, uint32_t bits, const char* const names[]) {
size_t i, n = 0;
for(i = 0; i < sizeof(bits) * 8; i++) {
if(bits & (1 << i)) {
size_t len = strlen(names[i]);
if(n) {
n++;
dbuf_putstr(db, "|");
}
dbuf_append(db, names[i], len);
n += len;
}
}
return n;
}
/**
* @}
*/

348
src/quickjs/buffer-utils.h Normal file
View File

@@ -0,0 +1,348 @@
#ifndef BUFFER_UTILS_H
#define BUFFER_UTILS_H
#include <quickjs.h>
#include <cutils.h>
#include <stdarg.h>
#include "char-utils.h"
/**
* \defgroup buffer-utils buffer-utils: Buffer Utilities
* @{
*/
int64_t array_search(void* a, size_t m, size_t elsz, void* needle);
#define array_contains(a, m, elsz, needle) (array_search((a), (m), (elsz), (needle)) != -1)
size_t ansi_length(const char*, size_t);
size_t ansi_skip(const char*, size_t);
size_t ansi_truncate(const char*, size_t, size_t limit);
int64_t array_search(void*, size_t, size_t elsz, void* needle);
char* str_escape(const char*);
char* byte_escape(const void*, size_t);
size_t byte_findb(const void*, size_t, const void* what, size_t wlen);
size_t byte_finds(const void*, size_t, const char* what);
size_t byte_equal(const void* s, size_t n, const void* t);
void byte_copy(void* out, size_t len, const void* in);
void byte_copyr(void* out, size_t len, const void* in);
size_t byte_rchrs(const char* in, size_t len, const char needles[], size_t nn);
#define DBUF_INIT_0() \
(DynBuf) { 0, 0, 0, 0, 0, 0 }
#define DBUF_INIT_CTX(ctx) \
(DynBuf) { 0, 0, 0, 0, (DynBufReallocFunc*)js_realloc_rt, JS_GetRuntime(ctx) }
extern const uint8_t escape_url_tab[256], escape_noquote_tab[256], escape_singlequote_tab[256], escape_doublequote_tab[256], escape_backquote_tab[256];
char* dbuf_at_n(const DynBuf*, size_t, size_t* n, char sep);
const char* dbuf_last_line(DynBuf*, size_t*);
int dbuf_prepend(DynBuf*, const uint8_t*, size_t len);
void dbuf_put_colorstr(DynBuf*, const char*, const char* color, int with_color);
void dbuf_put_escaped_pred(DynBuf*, const char*, size_t len, int (*pred)(int));
void dbuf_put_escaped_table(DynBuf*, const char*, size_t len, const uint8_t table[256]);
void dbuf_put_unescaped_table(DynBuf* db, const char* str, size_t len, const uint8_t table[256]);
void dbuf_put_unescaped_pred(DynBuf*, const char*, size_t len, int (*pred)());
void dbuf_put_escaped(DynBuf*, const char*, size_t len);
void dbuf_put_value(DynBuf*, JSContext*, JSValue value);
void dbuf_put_uint32(DynBuf* db, uint32_t num);
void dbuf_put_atom(DynBuf* db, JSContext* ctx, JSAtom atom);
int dbuf_reserve_start(DynBuf*, size_t);
uint8_t* dbuf_reserve(DynBuf*, size_t);
size_t dbuf_token_pop(DynBuf*, char);
size_t dbuf_token_push(DynBuf*, const char*, size_t len, char delim);
JSValue dbuf_tostring_free(DynBuf*, JSContext*);
ssize_t dbuf_load(DynBuf*, const char*);
int dbuf_vprintf(DynBuf*, const char*, va_list);
int screen_size(int size[2]);
static inline int
dbuf_putm(DynBuf* db, ...) {
int r = 0;
va_list a;
const char* s;
va_start(a, db);
while((s = va_arg(a, char*)))
if(dbuf_putstr(db, s))
return -1;
va_end(a);
return r;
}
#define dbuf_append(d, x, n) dbuf_put((d), (const uint8_t*)(x), (n))
static inline size_t
dbuf_count(DynBuf* db, int ch) {
return byte_count(db->buf, db->size, ch);
}
static inline void
dbuf_0(DynBuf* db) {
dbuf_putc(db, '\0');
db->size--;
}
static inline void
dbuf_zero(DynBuf* db) {
dbuf_realloc(db, 0);
db->size = 0;
}
size_t dbuf_bitflags(DynBuf* db, uint32_t bits, const char* const names[]);
#define js_dbuf_init(ctx, buf) dbuf_init2((buf), (ctx), (realloc_func*)&utils_js_realloc)
#define js_dbuf_init_rt(rt, buf) dbuf_init2((buf), (rt), (realloc_func*)&utils_js_realloc_rt)
void js_dbuf_allocator(JSContext* ctx, DynBuf* s);
typedef struct {
uint8_t* base;
size_t size;
} MemoryBlock;
static inline void
block_init(MemoryBlock* mb) {
mb->base = 0;
mb->size = 0;
}
/* clang-format off */
static inline void* block_data(const MemoryBlock* mb) { return mb->base; }
static inline size_t block_length(const MemoryBlock* mb) { return mb->size; }
static inline void* block_begin(const MemoryBlock* mb) { return mb->base; }
static inline void* block_end(const MemoryBlock* mb) { return mb->base + mb->size; }
/* clang-format on */
static inline BOOL
block_arraybuffer(MemoryBlock* mb, JSValueConst ab, JSContext* ctx) {
mb->base = JS_GetArrayBuffer(ctx, &mb->size, ab);
return mb->base != 0;
}
typedef struct {
uint8_t *start, *end;
} PointerRange;
static inline void
range_init(PointerRange* pr) {
pr->end = pr->start = 0;
}
static inline PointerRange
range_from(const MemoryBlock* mb) {
return (PointerRange){mb->base, mb->base + mb->size};
}
typedef struct {
int64_t start, end;
} IndexRange;
typedef struct {
int64_t offset, length;
} OffsetLength;
#define OFFSET_INIT() \
(OffsetLength) { 0, INT64_MAX }
static inline void
offset_init(OffsetLength* ol) {
ol->offset = 0;
ol->length = INT64_MAX;
}
static inline BOOL
offset_is_default(const OffsetLength* ol) {
return ol->offset == 0 && ol->length == INT64_MAX;
}
static inline void*
offset_data(const OffsetLength* ol, const void* x) {
return (uint8_t*)x + ol->offset;
}
static inline size_t
offset_size(const OffsetLength* ol, size_t n) {
if(ol->length == -1)
return (signed long)n - ol->offset;
return MIN_NUM(ol->length, (signed long)n - ol->offset);
}
static inline MemoryBlock
offset_block(const OffsetLength* ol, const void* x, size_t n) {
return (MemoryBlock){offset_data(ol, x), offset_size(ol, n)};
}
static inline PointerRange
offset_range(const OffsetLength* ol, const void* x, size_t n) {
MemoryBlock mb = offset_block(ol, x, n);
return range_from(&mb);
}
static inline OffsetLength
offset_slice(const OffsetLength ol, int64_t start, int64_t end) {
if(start < 0)
start = ol.length + (start % ol.length);
else if(start > ol.length)
start = ol.length;
if(end < 0)
end = ol.length + (end % ol.length);
else if(end > ol.length)
end = ol.length;
return (OffsetLength){start, end - start};
}
static inline OffsetLength
offset_offset(const OffsetLength* ol, const OffsetLength* by) {
OffsetLength ret;
ret.offset = ol->offset + by->offset;
ret.length = MIN_NUM(by->length, ol->length - by->offset);
return ret;
}
static inline OffsetLength
offset_from_indexrange(const IndexRange* ir) {
OffsetLength ret;
ret.offset = ir->start;
ret.length = ir->end - ir->start;
return ret;
}
static inline JSValue
offset_typedarray(OffsetLength* ol, JSValueConst array, JSContext* ctx) {
JSValue ret;
size_t offset, length;
ret = JS_GetTypedArrayBuffer(ctx, array, &offset, &length, NULL);
if(!JS_IsException(ret)) {
ol->offset = offset;
ol->length = length;
}
return ret;
}
static inline IndexRange
indexrange_from_offset(const OffsetLength* ol) {
IndexRange ret;
ret.start = ol->offset;
ret.end = ol->offset + ol->length;
return ret;
}
static inline MemoryBlock
block_range(const MemoryBlock* mb, const OffsetLength* range) {
MemoryBlock ret;
ret.base = mb->base + range->offset;
ret.size = MIN_NUM((size_t)range->length, mb->size - range->offset);
return ret;
}
static inline int
block_realloc(MemoryBlock* mb, size_t new_size, JSContext* ctx) {
if((mb->base = js_realloc(ctx, mb->base, new_size))) {
mb->size = new_size;
return 0;
}
return -1;
}
typedef struct InputBuffer {
union {
MemoryBlock block;
struct {
uint8_t* data;
size_t size;
};
};
size_t pos;
void (*free)(JSContext*, const char*, JSValue);
JSValue value;
OffsetLength range;
} InputBuffer;
static inline void
input_buffer_free_default(JSContext* ctx, const char* str, JSValue val) {
if(JS_IsString(val))
JS_FreeCString(ctx, str);
if(!JS_IsUndefined(val))
JS_FreeValue(ctx, val);
}
InputBuffer js_input_buffer(JSContext* ctx, JSValueConst value);
InputBuffer js_input_chars(JSContext* ctx, JSValueConst value);
InputBuffer js_input_args(JSContext* ctx, int argc, JSValueConst argv[]);
InputBuffer js_output_args(JSContext* ctx, int argc, JSValueConst argv[]);
InputBuffer input_buffer_clone(const InputBuffer* in, JSContext* ctx);
BOOL input_buffer_valid(const InputBuffer* in);
void input_buffer_dump(const InputBuffer* in, DynBuf* db);
void input_buffer_free(InputBuffer* in, JSContext* ctx);
static inline uint8_t*
input_buffer_data(const InputBuffer* in) {
return offset_data(&in->range, in->data);
}
static inline size_t
input_buffer_length(const InputBuffer* in) {
return offset_size(&in->range, in->size);
}
static inline MemoryBlock
input_buffer_block(InputBuffer* in) {
return (MemoryBlock){input_buffer_data(in), input_buffer_length(in)};
}
static inline MemoryBlock*
input_buffer_blockptr(InputBuffer* in) {
return &in->block;
}
const uint8_t* input_buffer_get(InputBuffer* in, size_t* lenp);
const uint8_t* input_buffer_peek(InputBuffer* in, size_t* lenp);
const char* input_buffer_currentline(InputBuffer*, size_t* len);
size_t input_buffer_column(InputBuffer*, size_t* len);
int input_buffer_peekc(InputBuffer* in, size_t* lenp);
int input_buffer_putc(InputBuffer*, unsigned int, JSContext*);
static inline int
input_buffer_getc(InputBuffer* in) {
size_t n;
int ret;
ret = input_buffer_peekc(in, &n);
in->pos += n;
return ret;
}
static inline void*
input_buffer_begin(const InputBuffer* in) {
return input_buffer_data(in);
}
static inline void*
input_buffer_end(const InputBuffer* in) {
return input_buffer_data(in) + input_buffer_length(in);
}
static inline BOOL
input_buffer_eof(const InputBuffer* in) {
return in->pos == input_buffer_length(in);
}
static inline size_t
input_buffer_remain(const InputBuffer* in) {
return input_buffer_length(in) - in->pos;
}
int js_offset_length(JSContext*, int64_t size, int argc, JSValueConst argv[], OffsetLength* off_len_p);
int js_index_range(JSContext*, int64_t size, int argc, JSValueConst argv[], IndexRange* idx_rng_p);
/**
* @}
*/
#endif /* defined(BUFFER_UTILS) */

578
src/quickjs/char-utils.c Normal file
View File

@@ -0,0 +1,578 @@
#include "char-utils.h"
#include "libutf.h"
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__)
#include <winnls.h>
#include <windows.h>
#include <wchar.h>
#endif
/**
* \addtogroup char-utils
* @{
*/
size_t
token_length(const char* str, size_t len, char delim) {
const char *s, *e;
size_t pos;
for(s = str, e = s + len; s < e; s += pos + 1) {
pos = byte_chr(s, e - s, delim);
if(s + pos == e)
break;
if(pos == 0 || s[pos - 1] != '\\') {
s += pos;
break;
}
}
return s - str;
}
size_t
fmt_ulong(char* dest, uint32_t i) {
uint32_t len, tmp, len2;
for(len = 1, tmp = i; tmp > 9; ++len)
tmp /= 10;
if(dest)
for(tmp = i, dest += len, len2 = len + 1; --len2; tmp /= 10)
*--dest = (char)((tmp % 10) + '0');
return len;
}
size_t
fmt_longlong(char* dest, int64_t i) {
if(i < 0) {
if(dest)
*dest++ = '-';
return fmt_ulonglong(dest, (uint64_t)-i) + 1;
}
return fmt_ulonglong(dest, (uint64_t)i);
}
size_t
fmt_ulonglong(char* dest, uint64_t i) {
size_t len;
uint64_t tmp, len2;
for(len = 1, tmp = i; tmp > 9ll; ++len)
tmp /= 10ll;
if(dest)
for(tmp = i, dest += len, len2 = len + 1; --len2; tmp /= 10ll)
*--dest = (tmp % 10ll) + '0';
return len;
}
#define tohex(c) (char)((c) >= 10 ? (c)-10 + 'a' : (c) + '0')
size_t
fmt_xlonglong(char* dest, uint64_t i) {
uint64_t len, tmp;
for(len = 1, tmp = i; tmp > 15ll; ++len)
tmp >>= 4ll;
if(dest)
for(tmp = i, dest += len;;) {
*--dest = tohex(tmp & 15ll);
if(!(tmp >>= 4ll))
break;
}
return len;
}
size_t
fmt_xlonglong0(char* dest, uint64_t num, size_t n) {
size_t i = 0, len;
if((len = fmt_xlonglong(NULL, num)) < n) {
len = n - len;
while(i < len)
dest[i++] = '0';
}
i += fmt_xlonglong(&dest[i], num);
return i;
}
size_t
fmt_8long(char* dest, uint32_t i) {
uint32_t len, tmp;
/* first count the number of bytes needed */
for(len = 1, tmp = i; tmp > 7; ++len)
tmp >>= 3;
if(dest)
for(tmp = i, dest += len;;) {
*--dest = (char)((tmp & 7) + '0');
if(!(tmp >>= 3))
break;
}
return len;
}
#define tohex(c) (char)((c) >= 10 ? (c)-10 + 'a' : (c) + '0')
size_t
fmt_xlong(char* dest, uint32_t i) {
uint32_t len, tmp;
/* first count the number of bytes needed */
for(len = 1, tmp = i; tmp > 15; ++len)
tmp >>= 4;
if(dest)
for(tmp = i, dest += len;;) {
*--dest = tohex(tmp & 15);
if(!(tmp >>= 4))
break;
}
return len;
}
size_t
fmt_xlong0(char* dest, uint32_t num, size_t n) {
size_t i = 0, len;
if((len = fmt_xlong(NULL, num)) < n) {
len = n - len;
while(i < len)
dest[i++] = '0';
}
i += fmt_xlong(&dest[i], num);
return i;
}
size_t
scan_ushort(const char* src, uint16_t* dest) {
const char* cur;
uint16_t l;
for(cur = src, l = 0; *cur >= '0' && *cur <= '9'; ++cur) {
uint32_t tmp = l * 10ul + *cur - '0';
if((uint16_t)tmp != tmp)
break;
l = tmp;
}
if(cur > src)
*dest = l;
return (size_t)(cur - src);
}
size_t
scan_uint(const char* src, uint32_t* dest) {
uint64_t u64;
size_t r = scan_ulonglong(src, &u64);
*dest = u64;
return r;
}
size_t
scan_int(const char* src, int32_t* dest) {
int64_t i64;
size_t r = scan_longlong(src, &i64);
*dest = i64;
return r;
}
#ifndef MAXLONG
#define MAXLONG (((uint32_t)-1) >> 1)
#endif
size_t
scan_longlong(const char* src, int64_t* dest) {
size_t i, o;
uint64_t l;
char c = src[0];
unsigned int neg = c == '-';
o = c == '-' || c == '+';
if((i = scan_ulonglong(src + o, &l))) {
if(i > 0ll && l > MAXLONG + neg) {
l /= 10ll;
--i;
}
if(i + o)
*dest = (int64_t)(c == '-' ? -l : l);
return i + o;
}
return 0;
}
size_t
scan_ulonglong(const char* src, uint64_t* dest) {
const char* tmp = src;
uint64_t l = 0;
unsigned char c;
while((c = (unsigned char)(*tmp - '0')) < 10) {
uint64_t n;
n = l << 3ll;
if((n >> 3ll) != l)
break;
if(n + (l << 1ll) < n)
break;
n += l << 1ll;
if(n + c < n)
break;
l = n + c;
++tmp;
}
if(tmp - src)
*dest = l;
return (size_t)(tmp - src);
}
size_t
scan_xlonglong(const char* src, uint64_t* dest) {
const char* tmp = src;
int64_t l = 0;
unsigned char c;
while((c = scan_fromhex(*tmp)) < 16) {
l = (l << 4) + c;
++tmp;
}
*dest = l;
return tmp - src;
}
size_t
scan_8longn(const char* src, size_t n, uint32_t* dest) {
const char* tmp = src;
uint32_t l = 0;
unsigned char c;
while(n-- > 0 && (c = (unsigned char)(*tmp - '0')) < 8) {
if(l >> (sizeof(l) * 8 - 3))
break;
l = l * 8 + c;
++tmp;
}
*dest = l;
return (size_t)(tmp - src);
}
size_t
scan_whitenskip(const char* s, size_t limit) {
const char *t, *u;
for(t = s, u = t + limit; t < u; ++t)
if(!is_whitespace_char(*t))
break;
return (size_t)(t - s);
}
size_t
scan_nonwhitenskip(const char* s, size_t limit) {
const char *t, *u;
for(t = s, u = t + limit; t < u; ++t)
if(is_whitespace_char(*t))
break;
return (size_t)(t - s);
}
size_t
scan_line(const char* s, size_t limit) {
const char *t, *u;
for(t = s, u = s + limit; t < u; ++t)
if(*t == '\n' || *t == '\r')
break;
return (size_t)(t - s);
}
size_t
scan_lineskip(const char* s, size_t limit) {
const char *t, *u;
for(t = s, u = s + limit; t < u; ++t)
if(*t == '\n') {
++t;
break;
}
return (size_t)(t - s);
}
size_t
scan_lineskip_escaped(const char* s, size_t limit) {
const char *t, *u;
for(t = s, u = s + limit; t < u; ++t) {
if(*t == '\\') {
++t;
continue;
}
if(*t == '\n') {
++t;
break;
}
}
return (size_t)(t - s);
}
size_t
scan_eolskip(const char* s, size_t limit) {
size_t n = 0;
if(n + 1 < limit && s[0] == '\r' && s[1] == '\n')
n += 2;
else if(n < limit && s[0] == '\n')
n += 1;
return n;
}
size_t
utf8_strlen(const void* in, size_t len) {
const uint8_t *pos, *end, *next;
size_t i = 0;
for(pos = (const uint8_t*)in, end = pos + len; pos < end; pos = next, ++i)
unicode_from_utf8(pos, end - pos, &next);
return i;
}
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__)
wchar_t*
utf8_towcs(const char* s) {
int len = (int)strlen(s);
int n = MultiByteToWideChar(CP_UTF8, 0, s, len, NULL, 0);
wchar_t* ret;
if((ret = (wchar_t*)malloc((n + 1) * sizeof(wchar_t)))) {
MultiByteToWideChar(CP_UTF8, 0, s, len, ret, n);
ret[n] = L'\0';
}
return ret;
}
char*
utf8_fromwcs(const wchar_t* wstr) {
int len = (int)wcslen(wstr);
int n = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
char* ret;
if((ret = malloc((n + 1)))) {
WideCharToMultiByte(CP_UTF8, 0, wstr, len, ret, n, NULL, NULL);
ret[n] = '\0';
}
return ret;
}
#endif
BOOL
utf16_multiword(const void* in) {
const uint16_t* p16 = in;
LibutfC16Type type = libutf_c16_type(p16[0]);
return !((LIBUTF_UTF16_NOT_SURROGATE == type) || (LIBUTF_UTF16_SURROGATE_HIGH != type || LIBUTF_UTF16_SURROGATE_LOW != libutf_c16_type(p16[1])));
}
int
case_lowerc(int c) {
if(c >= 'A' && c <= 'Z')
c += 'a' - 'A';
return c;
}
int
case_starts(const char* a, const char* b) {
const char *s, *t;
for(s = a, t = b;; ++s, ++t) {
unsigned char x, y;
if(!*t)
return 1;
x = case_lowerc(*s);
y = case_lowerc(*t);
if(x != y)
break;
if(!x)
break;
}
return 0;
}
int
case_diffb(const void* S, size_t len, const void* T) {
unsigned char x, y;
const char *s, *t;
for(s = (const char*)S, t = (const char*)T; len > 0;) {
--len;
x = case_lowerc(*s);
y = case_lowerc(*t);
++s;
++t;
if(x != y)
return ((int)(unsigned int)x) - ((int)(unsigned int)y);
}
return 0;
}
size_t
case_findb(const void* haystack, size_t hlen, const void* what, size_t wlen) {
size_t i, last;
const char* s = haystack;
if(hlen < wlen)
return hlen;
last = hlen - wlen;
for(i = 0; i <= last; i++, s++)
if(!case_diffb(s, wlen, what))
return i;
return hlen;
}
size_t
case_finds(const void* haystack, const char* what) {
return case_findb(haystack, strlen(haystack), what, strlen(what));
}
ssize_t
write_file(const char* file, const void* buf, size_t len) {
FILE* f;
ssize_t ret = -1;
if((f = fopen(file, "w+")))
switch(fwrite(buf, len, 1, f)) {
case 1: {
ret = len;
break;
}
}
fflush(f);
ret = ftell(f);
fclose(f);
return ret;
}
ssize_t
puts_file(const char* file, const char* s) {
return write_file(file, s, strlen(s));
}
size_t
u64toa(char* x, uint64_t num, int base) {
size_t len = 0;
uint64_t n = num;
do {
n /= base;
len++;
x++;
} while(n != 0);
*x-- = '\0';
do {
char c = num % base;
num /= base;
if(c >= 10)
c += 'a' - '0' - 10;
*x-- = c + '0';
} while(num != 0);
return len;
}
size_t
i64toa(char* x, int64_t num, int base) {
size_t pos = 0, len;
if(num < 0) {
x[pos++] = '-';
num = -num;
}
len = u64toa(&x[pos], num, base);
return pos + len;
}
size_t
str_findb(const char* s1, const char* x, size_t n) {
const char* b;
size_t i, j, len = strlen(s1);
if(len >= n) {
size_t end = len - n + 1;
for(i = 0; i < end; i++) {
b = &s1[i];
for(j = 0; x[j] == b[j];)
if(++j == n)
return i;
}
}
return len;
}
size_t
str_find(const void* s, const void* what) {
return str_findb(s, what, strlen(what));
}
/**
* @}
*/

441
src/quickjs/char-utils.h Normal file
View File

@@ -0,0 +1,441 @@
#ifndef CHAR_UTILS_H
#define CHAR_UTILS_H
#include <cutils.h>
#include <string.h>
#include "debug.h"
/**
* \defgroup char-utils char-utils: Character Utilities
* @{
*/
#define is_control_char(c) ((c) == '\a' || (c) == '\b' || (c) == '\t' || (c) == '\n' || (c) == '\v' || (c) == '\f' || (c) == '\r')
#define is_alphanumeric_char(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
#define is_digit_char(c) ((c) >= '0' && (c) <= '9')
#define is_print_char(c) ((c) >= ' ' && (c) <= '\x7f')
#define is_newline_char(c) ((c) == '\n')
#define is_identifier_char(c) (is_alphanumeric_char(c) || is_digit_char(c) || (c) == '$' || (c) == '_')
#define is_whitespace_char(c) ((c) == ' ' || (c) == '\t' || (c) == '\v' || (c) == '\n' || (c) == '\r')
#define str_equal(s, t) (!strcmp((s), (t)))
static inline int
escape_char_pred(int c) {
static const unsigned char table[256] = {
'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 0x62, 0x74, 0x6e, 0x76, 0x66, 0x72, 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x',
'x', 'x', 'x', 0, 0, 0, 0, 0, 0, 0, 0x27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
return table[(unsigned char)c];
}
static inline int
unescape_char_pred(int c) {
switch(c) {
case 'b': return 8;
case 'f': return 12;
case 'n': return 10;
case 'r': return 13;
case 't': return 9;
case 'v': return 11;
case '\'': return 39;
case '\\': return 92;
}
return 0;
}
static inline int
is_escape_char(int c) {
return is_control_char(c) || c == '\\' || c == '\'' || c == 0x1b || c == 0;
}
static inline int
is_backslash_char(int c) {
return c == '\\';
}
//#define is_dot_char(c) ((c) == '.')0
//#define is_backslash_char(c) ((c) == '\\')
static inline int
is_dot_char(int c) {
return c == '.';
}
static inline int
is_identifier(const char* str) {
if(!((*str >= 'A' && *str <= 'Z') || (*str >= 'a' && *str <= 'z') || *str == '$' || *str == '_'))
return 0;
while(*++str)
if(!is_identifier_char(*str))
return 0;
return 1;
}
static inline int
is_integer(const char* str) {
if(*str == '-')
++str;
if(!(*str >= '1' && *str <= '9') && !(*str == '0' && str[1] == '\0'))
return 0;
while(*++str)
if(!is_digit_char(*str))
return 0;
return 1;
}
static inline size_t
byte_count(const void* s, size_t n, char c) {
const uint8_t* t;
uint8_t ch = (uint8_t)c;
size_t count;
for(t = (uint8_t*)s, count = 0; n; ++t, --n)
if(*t == ch)
++count;
return count;
}
static inline size_t
byte_chr(const void* str, size_t len, char c) {
const char* s = memchr(str, c, len);
if(s)
return s - (const char*)str;
return len;
}
static inline size_t
byte_rchr(const void* haystack, size_t len, char needle) {
const char *s, *t;
for(s = (const char*)haystack, t = s + len;;) {
--t;
if(s > t)
break;
if(*t == needle)
return (size_t)(t - s);
}
return len;
}
/*size_t
byte_rchr(const void* str, size_t len, char c) {
const char* s = memrchr(str, c, len);
if(s)
return s - (const char*)str;
return len;
}*/
static inline size_t
byte_chrs(const void* str, size_t len, const char needle[], size_t nl) {
const char *s, *t;
for(s = str, t = s + len; s != t; s++)
if(byte_chr(needle, nl, *s) < nl)
break;
return s - (const char*)str;
}
static inline int
byte_diff(const void* a, size_t len, const void* b) {
size_t i;
for(i = 0; i < len; ++i) {
int r = ((unsigned char*)a)[i] - ((unsigned char*)b)[i];
if(r)
return r;
}
return 0;
}
static inline int
byte_diff2(const char* a, size_t alen, const char* b, size_t blen) {
if(alen < blen)
return -b[alen];
if(blen < alen)
return a[blen];
return byte_diff(a, alen, b);
}
static inline size_t
str_chr(const char* in, char needle) {
const char *t, c = needle;
for(t = in; *t; ++t)
if(*t == c)
break;
return (size_t)(t - in);
}
static inline size_t
str_chrs(const char* in, const char needles[], size_t nn) {
const char* t;
size_t i;
for(t = in; *t; ++t)
for(i = 0; i < nn; i++)
if(*t == needles[i])
return (size_t)(t - in);
return (size_t)(t - in);
}
static inline size_t
str_rchr(const char* s, char needle) {
const char *in, *found = 0;
for(in = s; *in; ++in)
if(*in == needle)
found = in;
return (size_t)((found ? found : in) - s);
}
static inline size_t
str_rchrs(const char* in, const char needles[], size_t nn) {
const char *s, *found = 0;
size_t i;
for(s = in; *s; ++s)
for(i = 0; i < nn; ++i)
if(*s == needles[i])
found = s;
return (size_t)((found ? found : s) - in);
}
static inline int
str_endb(const char* a, const char* x, size_t n) {
size_t alen = strlen(a);
a += alen - n;
return alen >= n && !memcmp(a, x, n);
}
/* str_ends returns 1 if the b is a suffix of a, 0 otherwise */
static inline int
str_ends(const char* a, const char* b) {
return str_endb(a, b, strlen(b));
}
static inline int
str_startb(const char* a, const char* x, size_t len) {
size_t i;
for(i = 0;; i++) {
if(i == len)
return 1;
if(a[i] != x[i])
break;
}
return 0;
}
static inline int
str_start(const char* a, const char* b) {
return str_startb(a, b, strlen(b));
}
#define str_contains(s, needle) (!!strchr((s), (needle)))
char* str_escape(const char*);
static inline size_t
str_count(const char* s, char c) {
size_t i, count = 0;
for(i = 0; s[i]; i++)
if(s[i] == c)
++count;
return count;
}
static inline size_t
str_copy(char* out, const char* in) {
char* s;
for(s = out; (*s = *in); ++s)
++in;
return (size_t)(s - out);
}
static inline size_t
str_copyn(char* out, const char* in, size_t n) {
char* s;
for(s = out; n-- && (*s = *in); ++s)
++in;
*s = '\0';
return (size_t)(s - out);
}
static inline char*
str_ndup(const char* s, size_t n) {
char* r = malloc(n + 1);
if(r == NULL)
return NULL;
memcpy(r, s, n);
r[n] = '\0';
return r;
}
size_t str_findb(const char*, const char*, size_t);
size_t str_find(const void*, const void*);
static inline size_t
predicate_find(const char* str, size_t len, int (*pred)(int32_t)) {
size_t pos;
for(pos = 0; pos < len; pos++)
if(pred(str[pos]))
break;
return pos;
}
static inline size_t
lookup_find(const char* str, size_t len, const char table[256]) {
size_t pos;
for(pos = 0; pos < len; pos++)
if(table[(unsigned char)str[pos]])
break;
return pos;
}
static inline char
escape_char_letter(char c) {
switch(c) {
case '\0': return '0';
case '\a': return 'a';
case '\b': return 'b';
case '\t': return 't';
case '\n': return 'n';
case '\v': return 'v';
case '\f': return 'f';
case '\r': return 'r';
case '\\': return '\\';
case '\'': return '\'';
}
return 0;
}
#define FMT_LONG 41 /* enough space to hold -2^127 in decimal, plus \0 */
#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */
#define FMT_8LONG 44 /* enough space to hold 2^128 - 1 in octal, plus \0 */
#define FMT_XLONG 33 /* enough space to hold 2^128 - 1 in hexadecimal, plus \0 */
size_t token_length(const char*, size_t, char delim);
size_t fmt_ulong(char*, uint32_t);
size_t scan_ushort(const char*, uint16_t*);
size_t fmt_longlong(char*, int64_t);
size_t fmt_ulonglong(char*, uint64_t);
size_t fmt_xlonglong(char*, uint64_t);
size_t fmt_xlonglong0(char*, uint64_t, size_t);
size_t fmt_8long(char* dest, uint32_t i);
size_t fmt_xlong(char* dest, uint32_t num);
size_t fmt_xlong0(char* dest, uint32_t num, size_t n);
size_t scan_longlong(const char*, int64_t*);
size_t scan_int(const char*, int32_t*);
size_t scan_uint(const char*, uint32_t*);
size_t scan_ulonglong(const char*, uint64_t*);
size_t scan_xlonglong(const char*, uint64_t*);
size_t scan_8longn(const char*, size_t, uint32_t* dest);
size_t scan_whitenskip(const char*, size_t);
size_t scan_nonwhitenskip(const char*, size_t);
size_t scan_line(const char*, size_t);
size_t scan_lineskip(const char*, size_t);
size_t scan_lineskip_escaped(const char*, size_t);
size_t scan_eolskip(const char*, size_t);
size_t utf8_strlen(const void*, size_t);
wchar_t* utf8_towcs(const char*);
char* utf8_fromwcs(const wchar_t*);
BOOL utf16_multiword(const void*);
int case_lowerc(int);
int case_starts(const char*, const char*);
int case_diffb(const void*, size_t, const void* T);
size_t case_findb(const void*, size_t, const void* what, size_t wlen);
size_t case_finds(const void*, const char*);
static inline int
scan_fromhex(unsigned char c) {
c -= '0';
if(c <= 9)
return c;
c &= ~0x20;
c -= 'A' - '0';
if(c < 6)
return c + 10;
return -1;
}
static inline size_t
scan_8long(const char* src, uint32_t* dest) {
return scan_8longn(src, (size_t)-1, dest);
}
static inline size_t
utf8_charlen(const char* in, size_t len) {
const uint8_t* next = (const void*)in;
int r = unicode_from_utf8((const uint8_t*)in, len, &next);
return r == -1 ? 0 : next - (const uint8_t*)in;
}
static inline int
utf8_charcode(const char* in, size_t len) {
const uint8_t* next = (const void*)in;
int r = unicode_from_utf8((const uint8_t*)in, len, &next);
return next > in ? r : -1;
}
BOOL utf16_multiword(const void*);
ssize_t write_file(const char* file, const void* buf, size_t len);
ssize_t puts_file(const char* file, const char* s);
size_t u64toa(char*, uint64_t num, int base);
size_t i64toa(char*, int64_t num, int base);
/**
* @}
*/
#endif /* defined(CHAR_UTILS_H) */

631
src/quickjs/cutils.c Normal file
View File

@@ -0,0 +1,631 @@
/*
* C utilities
*
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "cutils.h"
void pstrcpy(char *buf, int buf_size, const char *str)
{
int c;
char *q = buf;
if (buf_size <= 0)
return;
for(;;) {
c = *str++;
if (c == 0 || q >= buf + buf_size - 1)
break;
*q++ = c;
}
*q = '\0';
}
/* strcat and truncate. */
char *pstrcat(char *buf, int buf_size, const char *s)
{
int len;
len = strlen(buf);
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
int strstart(const char *str, const char *val, const char **ptr)
{
const char *p, *q;
p = str;
q = val;
while (*q != '\0') {
if (*p != *q)
return 0;
p++;
q++;
}
if (ptr)
*ptr = p;
return 1;
}
int has_suffix(const char *str, const char *suffix)
{
size_t len = strlen(str);
size_t slen = strlen(suffix);
return (len >= slen && !memcmp(str + len - slen, suffix, slen));
}
/* Dynamic buffer package */
static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size)
{
return realloc(ptr, size);
}
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func)
{
memset(s, 0, sizeof(*s));
if (!realloc_func)
realloc_func = dbuf_default_realloc;
s->opaque = opaque;
s->realloc_func = realloc_func;
}
void dbuf_init(DynBuf *s)
{
dbuf_init2(s, NULL, NULL);
}
/* return < 0 if error */
int dbuf_realloc(DynBuf *s, size_t new_size)
{
size_t size;
uint8_t *new_buf;
if (new_size > s->allocated_size) {
if (s->error)
return -1;
size = s->allocated_size * 3 / 2;
if (size > new_size)
new_size = size;
new_buf = s->realloc_func(s->opaque, s->buf, new_size);
if (!new_buf) {
s->error = TRUE;
return -1;
}
s->buf = new_buf;
s->allocated_size = new_size;
}
return 0;
}
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
{
size_t end;
end = offset + len;
if (dbuf_realloc(s, end))
return -1;
memcpy(s->buf + offset, data, len);
if (end > s->size)
s->size = end;
return 0;
}
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
{
if (unlikely((s->size + len) > s->allocated_size)) {
if (dbuf_realloc(s, s->size + len))
return -1;
}
memcpy_no_ub(s->buf + s->size, data, len);
s->size += len;
return 0;
}
int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
{
if (unlikely((s->size + len) > s->allocated_size)) {
if (dbuf_realloc(s, s->size + len))
return -1;
}
memcpy(s->buf + s->size, s->buf + offset, len);
s->size += len;
return 0;
}
int dbuf_putc(DynBuf *s, uint8_t c)
{
return dbuf_put(s, &c, 1);
}
int dbuf_putstr(DynBuf *s, const char *str)
{
return dbuf_put(s, (const uint8_t *)str, strlen(str));
}
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...)
{
va_list ap;
char buf[128];
int len;
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
if (len < sizeof(buf)) {
/* fast case */
return dbuf_put(s, (uint8_t *)buf, len);
} else {
if (dbuf_realloc(s, s->size + len + 1))
return -1;
va_start(ap, fmt);
vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,
fmt, ap);
va_end(ap);
s->size += len;
}
return 0;
}
void dbuf_free(DynBuf *s)
{
/* we test s->buf as a fail safe to avoid crashing if dbuf_free()
is called twice */
if (s->buf) {
s->realloc_func(s->opaque, s->buf, 0);
}
memset(s, 0, sizeof(*s));
}
/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes
are output. */
int unicode_to_utf8(uint8_t *buf, unsigned int c)
{
uint8_t *q = buf;
if (c < 0x80) {
*q++ = c;
} else {
if (c < 0x800) {
*q++ = (c >> 6) | 0xc0;
} else {
if (c < 0x10000) {
*q++ = (c >> 12) | 0xe0;
} else {
if (c < 0x00200000) {
*q++ = (c >> 18) | 0xf0;
} else {
if (c < 0x04000000) {
*q++ = (c >> 24) | 0xf8;
} else if (c < 0x80000000) {
*q++ = (c >> 30) | 0xfc;
*q++ = ((c >> 24) & 0x3f) | 0x80;
} else {
return 0;
}
*q++ = ((c >> 18) & 0x3f) | 0x80;
}
*q++ = ((c >> 12) & 0x3f) | 0x80;
}
*q++ = ((c >> 6) & 0x3f) | 0x80;
}
*q++ = (c & 0x3f) | 0x80;
}
return q - buf;
}
static const unsigned int utf8_min_code[5] = {
0x80, 0x800, 0x10000, 0x00200000, 0x04000000,
};
static const unsigned char utf8_first_code_mask[5] = {
0x1f, 0xf, 0x7, 0x3, 0x1,
};
/* return -1 if error. *pp is not updated in this case. max_len must
be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
{
int l, c, b, i;
c = *p++;
if (c < 0x80) {
*pp = p;
return c;
}
switch(c) {
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb:
case 0xcc: case 0xcd: case 0xce: case 0xcf:
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
case 0xd4: case 0xd5: case 0xd6: case 0xd7:
case 0xd8: case 0xd9: case 0xda: case 0xdb:
case 0xdc: case 0xdd: case 0xde: case 0xdf:
l = 1;
break;
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
case 0xec: case 0xed: case 0xee: case 0xef:
l = 2;
break;
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
l = 3;
break;
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
l = 4;
break;
case 0xfc: case 0xfd:
l = 5;
break;
default:
return -1;
}
/* check that we have enough characters */
if (l > (max_len - 1))
return -1;
c &= utf8_first_code_mask[l - 1];
for(i = 0; i < l; i++) {
b = *p++;
if (b < 0x80 || b >= 0xc0)
return -1;
c = (c << 6) | (b & 0x3f);
}
if (c < utf8_min_code[l - 1])
return -1;
*pp = p;
return c;
}
#if 0
#if defined(EMSCRIPTEN) || defined(__ANDROID__)
static void *rqsort_arg;
static int (*rqsort_cmp)(const void *, const void *, void *);
static int rqsort_cmp2(const void *p1, const void *p2)
{
return rqsort_cmp(p1, p2, rqsort_arg);
}
/* not reentrant, but not needed with emscripten */
void rqsort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *, void *),
void *arg)
{
rqsort_arg = arg;
rqsort_cmp = cmp;
qsort(base, nmemb, size, rqsort_cmp2);
}
#endif
#else
typedef void (*exchange_f)(void *a, void *b, size_t size);
typedef int (*cmp_f)(const void *, const void *, void *opaque);
static void exchange_bytes(void *a, void *b, size_t size) {
uint8_t *ap = (uint8_t *)a;
uint8_t *bp = (uint8_t *)b;
while (size-- != 0) {
uint8_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_byte(void *a, void *b, size_t size) {
uint8_t *ap = (uint8_t *)a;
uint8_t *bp = (uint8_t *)b;
uint8_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int16s(void *a, void *b, size_t size) {
uint16_t *ap = (uint16_t *)a;
uint16_t *bp = (uint16_t *)b;
for (size /= sizeof(uint16_t); size-- != 0;) {
uint16_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int16(void *a, void *b, size_t size) {
uint16_t *ap = (uint16_t *)a;
uint16_t *bp = (uint16_t *)b;
uint16_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int32s(void *a, void *b, size_t size) {
uint32_t *ap = (uint32_t *)a;
uint32_t *bp = (uint32_t *)b;
for (size /= sizeof(uint32_t); size-- != 0;) {
uint32_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int32(void *a, void *b, size_t size) {
uint32_t *ap = (uint32_t *)a;
uint32_t *bp = (uint32_t *)b;
uint32_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int64s(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
for (size /= sizeof(uint64_t); size-- != 0;) {
uint64_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int64(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
uint64_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int128s(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) {
uint64_t t = ap[0];
uint64_t u = ap[1];
ap[0] = bp[0];
ap[1] = bp[1];
bp[0] = t;
bp[1] = u;
}
}
static void exchange_one_int128(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
uint64_t t = ap[0];
uint64_t u = ap[1];
ap[0] = bp[0];
ap[1] = bp[1];
bp[0] = t;
bp[1] = u;
}
static inline exchange_f exchange_func(const void *base, size_t size) {
switch (((uintptr_t)base | (uintptr_t)size) & 15) {
case 0:
if (size == sizeof(uint64_t) * 2)
return exchange_one_int128;
else
return exchange_int128s;
case 8:
if (size == sizeof(uint64_t))
return exchange_one_int64;
else
return exchange_int64s;
case 4:
case 12:
if (size == sizeof(uint32_t))
return exchange_one_int32;
else
return exchange_int32s;
case 2:
case 6:
case 10:
case 14:
if (size == sizeof(uint16_t))
return exchange_one_int16;
else
return exchange_int16s;
default:
if (size == 1)
return exchange_one_byte;
else
return exchange_bytes;
}
}
static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
{
uint8_t *basep = (uint8_t *)base;
size_t i, n, c, r;
exchange_f swap = exchange_func(base, size);
if (nmemb > 1) {
i = (nmemb / 2) * size;
n = nmemb * size;
while (i > 0) {
i -= size;
for (r = i; (c = r * 2 + size) < n; r = c) {
if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0)
c += size;
if (cmp(basep + r, basep + c, opaque) > 0)
break;
swap(basep + r, basep + c, size);
}
}
for (i = n - size; i > 0; i -= size) {
swap(basep, basep + i, size);
for (r = 0; (c = r * 2 + size) < i; r = c) {
if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0)
c += size;
if (cmp(basep + r, basep + c, opaque) > 0)
break;
swap(basep + r, basep + c, size);
}
}
}
}
static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque)
{
return cmp(a, b, opaque) < 0 ?
(cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) :
(cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c ));
}
/* pointer based version with local stack and insertion sort threshhold */
void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
{
struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack;
uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m;
size_t m4, i, lt, gt, span, span2;
int c, depth;
exchange_f swap = exchange_func(base, size);
exchange_f swap_block = exchange_func(base, size | 128);
if (nmemb < 2 || size <= 0)
return;
sp->base = (uint8_t *)base;
sp->count = nmemb;
sp->depth = 0;
sp++;
while (sp > stack) {
sp--;
ptr = sp->base;
nmemb = sp->count;
depth = sp->depth;
while (nmemb > 6) {
if (++depth > 50) {
/* depth check to ensure worst case logarithmic time */
heapsortx(ptr, nmemb, size, cmp, opaque);
nmemb = 0;
break;
}
/* select median of 3 from 1/4, 1/2, 3/4 positions */
/* should use median of 5 or 9? */
m4 = (nmemb >> 2) * size;
m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque);
swap(ptr, m, size); /* move the pivot to the start or the array */
i = lt = 1;
pi = plt = ptr + size;
gt = nmemb;
pj = pgt = top = ptr + nmemb * size;
for (;;) {
while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) {
if (c == 0) {
swap(plt, pi, size);
lt++;
plt += size;
}
i++;
pi += size;
}
while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) {
if (c == 0) {
gt--;
pgt -= size;
swap(pgt, pj, size);
}
}
if (pi >= pj)
break;
swap(pi, pj, size);
i++;
pi += size;
}
/* array has 4 parts:
* from 0 to lt excluded: elements identical to pivot
* from lt to pi excluded: elements smaller than pivot
* from pi to gt excluded: elements greater than pivot
* from gt to n excluded: elements identical to pivot
*/
/* move elements identical to pivot in the middle of the array: */
/* swap values in ranges [0..lt[ and [i-lt..i[
swapping the smallest span between lt and i-lt is sufficient
*/
span = plt - ptr;
span2 = pi - plt;
lt = i - lt;
if (span > span2)
span = span2;
swap_block(ptr, pi - span, span);
/* swap values in ranges [gt..top[ and [i..top-(top-gt)[
swapping the smallest span between top-gt and gt-i is sufficient
*/
span = top - pgt;
span2 = pgt - pi;
pgt = top - span2;
gt = nmemb - (gt - i);
if (span > span2)
span = span2;
swap_block(pi, top - span, span);
/* now array has 3 parts:
* from 0 to lt excluded: elements smaller than pivot
* from lt to gt excluded: elements identical to pivot
* from gt to n excluded: elements greater than pivot
*/
/* stack the larger segment and keep processing the smaller one
to minimize stack use for pathological distributions */
if (lt > nmemb - gt) {
sp->base = ptr;
sp->count = lt;
sp->depth = depth;
sp++;
ptr = pgt;
nmemb -= gt;
} else {
sp->base = pgt;
sp->count = nmemb - gt;
sp->depth = depth;
sp++;
nmemb = lt;
}
}
/* Use insertion sort for small fragments */
for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) {
for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size)
swap(pj, pj - size, size);
}
}
}
#endif

341
src/quickjs/cutils.h Normal file
View File

@@ -0,0 +1,341 @@
/*
* C utilities
*
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
* 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 CUTILS_H
#define CUTILS_H
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline inline __attribute__((always_inline))
#define no_inline __attribute__((noinline))
#define __maybe_unused __attribute__((unused))
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0]))
#endif
#ifndef container_of
/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
#endif
typedef int BOOL;
#ifndef FALSE
enum {
FALSE = 0,
TRUE = 1,
};
#endif
void pstrcpy(char *buf, int buf_size, const char *str);
char *pstrcat(char *buf, int buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
int has_suffix(const char *str, const char *suffix);
/* Prevent UB when n == 0 and (src == NULL or dest == NULL) */
static inline void memcpy_no_ub(void *dest, const void *src, size_t n) {
if (n)
memcpy(dest, src, n);
}
static inline int max_int(int a, int b)
{
if (a > b)
return a;
else
return b;
}
static inline int min_int(int a, int b)
{
if (a < b)
return a;
else
return b;
}
static inline uint32_t max_uint32(uint32_t a, uint32_t b)
{
if (a > b)
return a;
else
return b;
}
static inline uint32_t min_uint32(uint32_t a, uint32_t b)
{
if (a < b)
return a;
else
return b;
}
static inline int64_t max_int64(int64_t a, int64_t b)
{
if (a > b)
return a;
else
return b;
}
static inline int64_t min_int64(int64_t a, int64_t b)
{
if (a < b)
return a;
else
return b;
}
/* WARNING: undefined if a = 0 */
static inline int clz32(unsigned int a)
{
return __builtin_clz(a);
}
/* WARNING: undefined if a = 0 */
static inline int clz64(uint64_t a)
{
return __builtin_clzll(a);
}
/* WARNING: undefined if a = 0 */
static inline int ctz32(unsigned int a)
{
return __builtin_ctz(a);
}
/* WARNING: undefined if a = 0 */
static inline int ctz64(uint64_t a)
{
return __builtin_ctzll(a);
}
struct __attribute__((packed)) packed_u64 {
uint64_t v;
};
struct __attribute__((packed)) packed_u32 {
uint32_t v;
};
struct __attribute__((packed)) packed_u16 {
uint16_t v;
};
static inline uint64_t get_u64(const uint8_t *tab)
{
return ((const struct packed_u64 *)tab)->v;
}
static inline int64_t get_i64(const uint8_t *tab)
{
return (int64_t)((const struct packed_u64 *)tab)->v;
}
static inline void put_u64(uint8_t *tab, uint64_t val)
{
((struct packed_u64 *)tab)->v = val;
}
static inline uint32_t get_u32(const uint8_t *tab)
{
return ((const struct packed_u32 *)tab)->v;
}
static inline int32_t get_i32(const uint8_t *tab)
{
return (int32_t)((const struct packed_u32 *)tab)->v;
}
static inline void put_u32(uint8_t *tab, uint32_t val)
{
((struct packed_u32 *)tab)->v = val;
}
static inline uint32_t get_u16(const uint8_t *tab)
{
return ((const struct packed_u16 *)tab)->v;
}
static inline int32_t get_i16(const uint8_t *tab)
{
return (int16_t)((const struct packed_u16 *)tab)->v;
}
static inline void put_u16(uint8_t *tab, uint16_t val)
{
((struct packed_u16 *)tab)->v = val;
}
static inline uint32_t get_u8(const uint8_t *tab)
{
return *tab;
}
static inline int32_t get_i8(const uint8_t *tab)
{
return (int8_t)*tab;
}
static inline void put_u8(uint8_t *tab, uint8_t val)
{
*tab = val;
}
#ifndef bswap16
static inline uint16_t bswap16(uint16_t x)
{
return (x >> 8) | (x << 8);
}
#endif
#ifndef bswap32
static inline uint32_t bswap32(uint32_t v)
{
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
}
#endif
#ifndef bswap64
static inline uint64_t bswap64(uint64_t v)
{
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
}
#endif
/* XXX: should take an extra argument to pass slack information to the caller */
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
typedef struct DynBuf {
uint8_t *buf;
size_t size;
size_t allocated_size;
BOOL error; /* true if a memory allocation error occurred */
DynBufReallocFunc *realloc_func;
void *opaque; /* for realloc_func */
} DynBuf;
void dbuf_init(DynBuf *s);
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
int dbuf_realloc(DynBuf *s, size_t new_size);
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
int dbuf_putc(DynBuf *s, uint8_t c);
int dbuf_putstr(DynBuf *s, const char *str);
static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
{
return dbuf_put(s, (uint8_t *)&val, 2);
}
static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
{
return dbuf_put(s, (uint8_t *)&val, 4);
}
static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
{
return dbuf_put(s, (uint8_t *)&val, 8);
}
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...);
void dbuf_free(DynBuf *s);
static inline BOOL dbuf_error(DynBuf *s) {
return s->error;
}
static inline void dbuf_set_error(DynBuf *s)
{
s->error = TRUE;
}
#define UTF8_CHAR_LEN_MAX 6
int unicode_to_utf8(uint8_t *buf, unsigned int c);
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
static inline BOOL is_surrogate(uint32_t c)
{
return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
}
static inline BOOL is_hi_surrogate(uint32_t c)
{
return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
}
static inline BOOL is_lo_surrogate(uint32_t c)
{
return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
}
static inline uint32_t get_hi_surrogate(uint32_t c)
{
return (c >> 10) - (0x10000 >> 10) + 0xD800;
}
static inline uint32_t get_lo_surrogate(uint32_t c)
{
return (c & 0x3FF) | 0xDC00;
}
static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
{
return 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00);
}
static inline int from_hex(int c)
{
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
else
return -1;
}
void rqsort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *, void *),
void *arg);
#endif /* CUTILS_H */

483
src/quickjs/debug.c Normal file
View File

@@ -0,0 +1,483 @@
#define _IN_DEBUG_C 1
#include "debug.h"
#include <quickjs.h>
#include <list.h>
#include <cutils.h>
#include <assert.h>
#include "defines.h"
#include <string.h>
#include <stdlib.h>
/**
* \addtogroup debug
* @{
*/
struct alloc_block {
struct list_head link;
const char* file;
int line;
size_t size;
};
#define ALLOC_BLOCK_SIZE sizeof(struct alloc_block)
#define ALLOC_BLOCK(p) (((struct alloc_block*)(p)) - 1)
#define ALLOC_PTR struct alloc_block*
#undef malloc
#undef calloc
#undef realloc
#undef strdup
#undef free
#undef js_malloc
#undef js_mallocz
#undef js_realloc
#undef js_strdup
#undef js_strndup
#undef js_free
#undef js_malloc_usable_size
#undef js_malloc_rt
#undef js_mallocz_rt
#undef js_realloc_rt
#undef js_free_rt
#undef js_malloc_usable_size_rt
thread_local struct list_head alloc_block_list = {0, 0};
static inline void
add_to_list(struct list_head* el, struct list_head* head) {
if(alloc_block_list.prev == 0 && alloc_block_list.next == 0)
init_list_head(&alloc_block_list);
list_add_tail(el, head);
}
int64_t
check_pointer(void* p) {
ALLOC_PTR ptr = ALLOC_BLOCK(p);
struct list_head* link;
int64_t ret = 0;
list_for_each(link, &alloc_block_list) {
if(link == &ptr->link)
return ret;
ret++;
}
// assert(0);
return -1;
}
void*
debug_malloc(size_t n, const char* file, int line) {
ALLOC_PTR ptr;
if((ptr = malloc(n + ALLOC_BLOCK_SIZE))) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
void*
debug_calloc(size_t m, size_t n, const char* file, int line) {
ALLOC_PTR ptr;
m *= n;
n = 1;
if((ptr = calloc(m + ALLOC_BLOCK_SIZE, 1))) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
void*
debug_realloc(void* p, size_t n, const char* file, int line) {
ALLOC_PTR ptr;
if(p) {
check_pointer(p);
ptr = ALLOC_BLOCK(p);
list_del(&ptr->link);
if(n == 0) {
free(ptr);
return 0;
}
ptr = realloc(ptr, n + ALLOC_BLOCK_SIZE);
} else {
ptr = malloc(n + ALLOC_BLOCK_SIZE);
}
if(ptr) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
void*
debug_strdup(const char* s, const char* file, int line) {
ALLOC_PTR ptr;
size_t len = strlen(s);
if((ptr = malloc(len + 1 + ALLOC_BLOCK_SIZE))) {
ptr->file = file;
ptr->line = line;
ptr->size = len + 1;
add_to_list(&ptr->link, &alloc_block_list);
memcpy(&ptr[1], s, len + 1);
return &ptr[1];
}
return 0;
}
void
debug_free(void* p, const char* file, int line) {
ALLOC_PTR ptr = ALLOC_BLOCK(p);
list_del(&ptr->link);
memset(ptr, 0xff, ALLOC_BLOCK_SIZE);
free(ptr);
}
void*
debug_js_malloc(JSContext* ctx, size_t n, const char* file, int line) {
ALLOC_PTR ptr;
if((ptr = js_malloc(ctx, n + ALLOC_BLOCK_SIZE))) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
void*
debug_js_mallocz(JSContext* ctx, size_t n, const char* file, int line) {
ALLOC_PTR ptr;
if((ptr = js_mallocz(ctx, n + ALLOC_BLOCK_SIZE))) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
void*
debug_js_realloc(JSContext* ctx, void* p, size_t n, const char* file, int line) {
ALLOC_PTR ptr;
if(p) {
check_pointer(p);
ptr = ALLOC_BLOCK(p);
list_del(&ptr->link);
if(n == 0) {
js_free(ctx, ptr);
return 0;
}
ptr = js_realloc(ctx, ptr, n + ALLOC_BLOCK_SIZE);
} else {
ptr = js_malloc(ctx, n + ALLOC_BLOCK_SIZE);
}
if(ptr) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
void*
debug_js_realloc2(JSContext* ctx, void* p, size_t size, size_t* pslack, const char* file, int line) {
void* ptr;
if((ptr = debug_js_realloc(ctx, p, size, file, line))) {
if(pslack) {
size_t new_size = debug_js_malloc_usable_size(ctx, ptr, file, line);
*pslack = (new_size > size) ? new_size - size : 0;
}
}
return ptr;
}
void*
debug_js_strdup(JSContext* ctx, const char* s, const char* file, int line) {
ALLOC_PTR ptr;
size_t len = strlen(s);
if((ptr = js_malloc(ctx, len + 1 + ALLOC_BLOCK_SIZE))) {
char* p = (char*)&ptr[1];
ptr->file = file;
ptr->line = line;
ptr->size = len + 1;
add_to_list(&ptr->link, &alloc_block_list);
memcpy(p, s, len + 1);
return p;
}
return 0;
}
void*
debug_js_strndup(JSContext* ctx, const char* s, size_t len, const char* file, int line) {
ALLOC_PTR ptr;
if((ptr = js_malloc(ctx, len + 1 + ALLOC_BLOCK_SIZE))) {
char* p = (char*)&ptr[1];
ptr->file = file;
ptr->line = line;
ptr->size = len + 1;
add_to_list(&ptr->link, &alloc_block_list);
memcpy(p, s, len);
p[len] = '\0';
return p;
}
return 0;
}
size_t
debug_js_malloc_usable_size(JSContext* ctx, const void* p, const char* file, int line) {
ALLOC_PTR ptr = ALLOC_BLOCK(p);
return js_malloc_usable_size(ctx, ptr) - ALLOC_BLOCK_SIZE;
}
void
debug_js_free(JSContext* ctx, void* p, const char* file, int line) {
ALLOC_PTR ptr;
check_pointer(p);
ptr = ALLOC_BLOCK(p);
list_del(&ptr->link);
memset(ptr, 0xff, ALLOC_BLOCK_SIZE);
js_free(ctx, ptr);
}
void*
debug_js_malloc_rt(JSRuntime* rt, size_t n, const char* file, int line) {
ALLOC_PTR ptr;
if((ptr = js_malloc_rt(rt, n + ALLOC_BLOCK_SIZE))) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
void*
debug_js_mallocz_rt(JSRuntime* rt, size_t n, const char* file, int line) {
ALLOC_PTR ptr;
if((ptr = js_mallocz_rt(rt, n + ALLOC_BLOCK_SIZE))) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
void*
debug_js_realloc_rt(JSRuntime* rt, void* p, size_t n, const char* file, int line) {
ALLOC_PTR ptr;
if(p) {
check_pointer(p);
ptr = ALLOC_BLOCK(p);
list_del(&ptr->link);
if(n == 0) {
js_free_rt(rt, ptr);
return 0;
}
ptr = js_realloc_rt(rt, ptr, n + ALLOC_BLOCK_SIZE);
} else {
ptr = js_malloc_rt(rt, n + ALLOC_BLOCK_SIZE);
}
if(ptr) {
ptr->file = file;
ptr->line = line;
ptr->size = n;
add_to_list(&ptr->link, &alloc_block_list);
return &ptr[1];
}
return 0;
}
size_t
debug_js_malloc_usable_size_rt(JSRuntime* rt, const void* p, const char* file, int line) {
ALLOC_PTR ptr = ALLOC_BLOCK(p);
return js_malloc_usable_size_rt(rt, ptr) - ALLOC_BLOCK_SIZE;
}
void
debug_js_free_rt(JSRuntime* rt, void* p, const char* file, int line) {
ALLOC_PTR ptr;
check_pointer(p);
ptr = ALLOC_BLOCK(p);
// printf("debug_js_free_rt %p\n", p);
list_del(&ptr->link);
memset(ptr, 0xff, ALLOC_BLOCK_SIZE);
js_free_rt(rt, ptr);
}
#undef malloc
#undef calloc
#undef realloc
#undef strdup
#undef free
#undef js_malloc
#undef js_mallocz
#undef js_realloc
#undef js_strdup
#undef js_strndup
#undef js_malloc_usable_size
#undef js_free
#undef js_malloc_rt
#undef js_mallocz_rt
#undef js_realloc_rt
#undef js_malloc_usable_size_rt
#undef js_free_rt
void*
orig_malloc(size_t size) {
return malloc(size);
}
void*
orig_calloc(size_t nelem, size_t elemsz) {
return calloc(nelem, elemsz);
}
void*
orig_realloc(void* ptr, size_t size) {
return realloc(ptr, size);
}
void*
orig_strdup(const char* str) {
return strdup(str);
}
void
orig_free(void* ptr) {
free(ptr);
}
void*
orig_js_malloc(JSContext* ctx, size_t size) {
return js_malloc(ctx, size);
}
void*
orig_js_mallocz(JSContext* ctx, size_t size) {
return js_mallocz(ctx, size);
}
void*
orig_js_realloc(JSContext* ctx, void* p, size_t size) {
return js_realloc(ctx, p, size);
}
void*
orig_js_strdup(JSContext* ctx, const char* str) {
return js_strdup(ctx, str);
}
void*
orig_js_strndup(JSContext* ctx, const char* str, size_t size) {
return js_strndup(ctx, str, size);
}
size_t
orig_js_malloc_usable_size(JSContext* ctx, const void* p) {
return js_malloc_usable_size(ctx, p);
}
void
orig_js_free(JSContext* ctx, void* p) {
return js_free(ctx, p);
}
void*
orig_js_malloc_rt(JSRuntime* rt, size_t size) {
return js_malloc_rt(rt, size);
}
void*
orig_js_mallocz_rt(JSRuntime* rt, size_t size) {
return js_mallocz_rt(rt, size);
}
void*
orig_js_realloc_rt(JSRuntime* rt, void* p, size_t size) {
return js_realloc_rt(rt, p, size);
}
size_t
orig_js_malloc_usable_size_rt(JSRuntime* rt, const void* p) {
return js_malloc_usable_size_rt(rt, p);
}
void
orig_js_free_rt(JSRuntime* rt, void* p) {
return js_free_rt(rt, p);
}
/**
* @}
*/

165
src/quickjs/debug.h Normal file
View File

@@ -0,0 +1,165 @@
#ifndef DEBUG_H
#define DEBUG_H
#include <quickjs.h>
#include <cutils.h>
#include "defines.h"
#ifndef QUICKJS_H
#error "quickjs.h not included"
#endif
/**
* \defgroup debug debug: Debugging helpers
* @{
*/
extern thread_local struct list_head alloc_block_list;
int64_t check_pointer(void*);
void* debug_malloc(size_t, const char*, int);
void* debug_calloc(size_t, size_t, const char*, int line);
void* debug_realloc(void*, size_t, const char*, int line);
void* debug_strdup(const char*, const char*, int);
void debug_free(void*, const char*, int);
void* debug_js_malloc(JSContext*, size_t, const char*, int line);
void* debug_js_mallocz(JSContext*, size_t, const char*, int line);
void* debug_js_realloc(JSContext*, void*, size_t, const char* file, int line);
void* debug_js_realloc2(JSContext*, void*, size_t, size_t* pslack, const char* file, int line);
void* debug_js_strdup(JSContext*, const char*, const char*, int line);
void* debug_js_strndup(JSContext*, const char*, size_t, const char* file, int line);
size_t debug_js_malloc_usable_size(JSContext*, const void*, const char*, int line);
void debug_js_free(JSContext*, void*, const char*, int line);
void* debug_js_malloc_rt(JSRuntime*, size_t, const char*, int line);
void* debug_js_mallocz_rt(JSRuntime*, size_t, const char*, int line);
void* debug_js_realloc_rt(JSRuntime*, void*, size_t, const char* file, int line);
size_t debug_js_malloc_usable_size_rt(JSRuntime*, const void*, const char*, int line);
void debug_js_free_rt(JSRuntime*, void*, const char*, int line);
#if !defined(_IN_DEBUG_C)
#if defined(DEBUG_ALLOC)
#define malloc(size) debug_malloc(size, __FILE__, __LINE__)
#define calloc(nelem, size) debug_calloc(nelem, size, __FILE__, __LINE__)
#define realloc(ptr, size) debug_realloc(ptr, size, __FILE__, __LINE__)
#define strdup(str) debug_strdup(str, __FILE__, __LINE__)
#define free(ptr) debug_free(ptr, __FILE__, __LINE__)
#define js_malloc(ctx, size) debug_js_malloc(ctx, size, __FILE__, __LINE__)
#define js_mallocz(ctx, size) debug_js_mallocz(ctx, size, __FILE__, __LINE__)
#define js_realloc(ctx, ptr, size) debug_js_realloc(ctx, ptr, size, __FILE__, __LINE__)
#define js_strdup(ctx, str) debug_js_strdup(ctx, str, __FILE__, __LINE__)
#define js_strndup(ctx, str, len) debug_js_strndup(ctx, str, len, __FILE__, __LINE__)
#define js_free(ctx, ptr) debug_js_free(ctx, ptr, __FILE__, __LINE__)
#define js_malloc_usable_size(ctx, ptr) debug_js_malloc_usable_size(ctx, ptr, __FILE__, __LINE__)
#define js_malloc_rt(rt, size) debug_js_malloc_rt(rt, size, __FILE__, __LINE__)
#define js_mallocz_rt(rt, size) debug_js_mallocz_rt(rt, size, __FILE__, __LINE__)
#define js_realloc_rt(rt, ptr, size) debug_js_realloc_rt(rt, ptr, size, __FILE__, __LINE__)
#define js_malloc_usable_size_rt(rt, ptr) debug_js_malloc_usable_size_rt(rt, ptr, __FILE__, __LINE__)
#define js_free_rt(rt, ptr) debug_js_free_rt(rt, ptr, __FILE__, __LINE__)
#endif
#ifdef DEBUG_ALLOC
#define realloc_helper(name) \
void* name(void* ptr, size_t size) { \
if(ptr == 0) \
return debug_malloc(size, __FILE__, __LINE__); \
if(size == 0) \
return debug_free(ptr, __FILE__, __LINE__); \
return debug_realloc(ptr, size, __FILE__, __LINE__); \
}
#define realloc2_helper(name) \
void* name(void* opaque, void* ptr, size_t size) { \
if(ptr == 0) \
return debug_malloc(size, __FILE__, __LINE__); \
if(size == 0) { \
debug_free(ptr, __FILE__, __LINE__); \
return 0; \
} \
return debug_realloc(ptr, size, __FILE__, __LINE__); \
}
#define js_realloc_helper(name) \
void* name(JSContext* ctx, void* ptr, size_t size) { \
if(ptr == 0) \
return debug_js_malloc(ctx, size, __FILE__, __LINE__); \
if(size == 0) { \
debug_js_free(ctx, ptr, __FILE__, __LINE__); \
return 0; \
} \
return debug_js_realloc(ctx, ptr, size, __FILE__, __LINE__); \
}
#define js_realloc_rt_helper(name) \
void* name(JSRuntime* rt, void* ptr, size_t size) { \
if(ptr == 0) \
return debug_js_malloc_rt(rt, size, __FILE__, __LINE__); \
if(size == 0) { \
debug_js_free_rt(rt, ptr, __FILE__, __LINE__); \
return 0; \
} \
return debug_js_realloc_rt(rt, ptr, size, __FILE__, __LINE__); \
}
#else
#define realloc_helper(name) \
void* name(void* ptr, size_t size) { \
if(ptr == 0) \
return malloc(size); \
if(size == 0) { \
free(ptr); \
return 0; \
} \
return realloc(ptr, size); \
}
#define realloc2_helper(name) \
void* name(void* opaque, void* ptr, size_t size) { \
if(ptr == 0) \
return malloc(size); \
if(size == 0) { \
free(ptr); \
return 0; \
} \
return realloc(ptr, size); \
}
#define js_realloc_helper(name) \
void* name(JSContext* ctx, void* ptr, size_t size) { \
if(ptr == 0) \
return orig_js_malloc(ctx, size); \
if(size == 0) { \
orig_js_free(ctx, ptr); \
return 0; \
} \
return orig_js_realloc(ctx, ptr, size); \
}
#define js_realloc_rt_helper(name) \
void* name(JSRuntime* rt, void* ptr, size_t size) { \
if(ptr == 0) \
return orig_js_malloc_rt(rt, size); \
if(size == 0) { \
orig_js_free_rt(rt, ptr); \
return 0; \
} \
return orig_js_realloc_rt(rt, ptr, size); \
}
#endif
#endif
void* orig_malloc(size_t);
void* orig_calloc(size_t, size_t);
void* orig_realloc(void*, size_t);
void* orig_strdup(const char*);
void orig_free(void*);
void* orig_js_malloc(JSContext*, size_t);
void* orig_js_mallocz(JSContext*, size_t);
void* orig_js_realloc(JSContext*, void*, size_t);
void* orig_js_strdup(JSContext*, const char*);
void* orig_js_strndup(JSContext*, const char*, size_t);
size_t orig_js_malloc_usable_size(JSContext*, const void*);
void orig_js_free(JSContext*, void*);
void* orig_js_malloc_rt(JSRuntime*, size_t);
void* orig_js_mallocz_rt(JSRuntime*, size_t);
void* orig_js_realloc_rt(JSRuntime*, void*, size_t);
size_t orig_js_malloc_usable_size_rt(JSRuntime*, const void*);
void orig_js_free_rt(JSRuntime*, void*);
/**
* @}
*/
#endif /* defined(DEBUG_H) */

181
src/quickjs/defines.h Normal file
View File

@@ -0,0 +1,181 @@
#ifndef DEFINES_H
#define DEFINES_H
/**
* \defgroup defines defines: Preprocessor definitions
* @{
*/
#ifdef _WIN32
#include <io.h>
#define FD_TO_SOCKET(fd) ((SOCKET)_get_osfhandle((fd)))
#define SOCKET_TO_FD(fh) (_open_osfhandle((intptr_t)(fh), O_RDWR | O_BINARY))
#else
#define FD_TO_SOCKET(fd) (fd)
#define SOCKET_TO_FD(fh) (fh)
#endif
#ifndef offsetof
#define offsetof(type, field) ((size_t) & ((type*)0)->field)
#endif
#ifndef inrange
#define inrange(value, min, max) ((value) >= (min) && (value) <= (max))
#endif
#define trim_dotslash(str) (!strncmp((str), "./", 2) ? (str) + 2 : (str))
#ifndef thread_local
#ifdef _Thread_local
#define thread_local _Thread_local
#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define thread_local __thread
#elif defined(_WIN32)
#define thread_local __declspec(thread)
#else
#error No TLS implementation found.
#endif
#endif
#if defined(__GNUC__) || defined(__clang__)
#define PACK __attribute__((packed))
#define ENDPACK
#else
#define PACK #pragma pack(push, 1)
#define ENDPACK #pragma pack(pop)
#endif
#define JS_CGETSET_ENUMERABLE_DEF(prop_name, fgetter, fsetter, magic_num) \
{ \
.name = prop_name, .prop_flags = JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE, .def_type = JS_DEF_CGETSET_MAGIC, .magic = magic_num, .u = { \
.getset = {.get = {.getter_magic = fgetter}, .set = {.setter_magic = fsetter}} \
} \
}
#define JS_CGETSET_MAGIC_FLAGS_DEF(prop_name, fgetter, fsetter, magic_num, flags) \
{ \
.name = prop_name, .prop_flags = flags, .def_type = JS_DEF_CGETSET_MAGIC, .magic = magic_num, .u = { \
.getset = {.get = {.getter_magic = fgetter}, .set = {.setter_magic = fsetter}} \
} \
}
#define JS_CFUNC_DEF_FLAGS(prop_name, length, func1, flags) \
{ \
.name = prop_name, .prop_flags = flags, .def_type = JS_DEF_CFUNC, .magic = 0, .u = {.func = {length, JS_CFUNC_generic, {.generic = func1}} } \
}
#define JS_CONSTANT_FLAGS(name, flags) JS_PROP_INT32_DEF(#name, name, (flags))
#define JS_CONSTANT(name) JS_PROP_INT32_DEF(#name, name, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)
#define JS_CONSTANT_NONENUMERABLE(name) JS_PROP_INT32_DEF(#name, name, JS_PROP_CONFIGURABLE)
#ifdef JS_SHARED_LIBRARY
#if defined(_WIN32) || defined(__MINGW32__)
#define VISIBLE __declspec(dllexport)
#define HIDDEN
#else
#define VISIBLE __attribute__((visibility("default")))
#define HIDDEN __attribute__((visibility("hidden")))
#endif
#else
#define VISIBLE
#define HIDDEN
#endif
#ifndef MAX_NUM
#define MAX_NUM(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN_NUM
#define MIN_NUM(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef ABS_NUM
#define ABS_NUM(n) ((n) < 0 ? -(n) : (n))
#endif
#ifndef MOD_NUM
#define MOD_NUM(n, divisor) ((((n) % (divisor)) + (divisor)) % (divisor))
#endif
#ifndef SIGN_NUM
#define SIGN_NUM(n) ((n) < 0)
#endif
#define COLOR_BLACK "\x1b[0;30m"
#define COLOR_RED "\x1b[0;31m"
#define COLOR_GREEN "\x1b[0;32m"
#define COLOR_BROWN "\x1b[0;33m"
#define COLOR_BLUE "\x1b[0;34m"
#define COLOR_PURPLE "\x1b[0;35m"
#define COLOR_MARINE "\x1b[0;36m"
#define COLOR_LIGHTGRAY "\x1b[0;37m"
#define COLOR_GRAY "\x1b[1;30m"
#define COLOR_NONE "\x1b[0m"
#define COLOR_LIGHTRED "\x1b[1;31m"
#define COLOR_LIGHTGREEN "\x1b[1;32m"
#define COLOR_YELLOW "\x1b[1;33m"
#define COLOR_LIGHTBLUE "\x1b[1;34m"
#define COLOR_MAGENTA "\x1b[1;35m"
#define COLOR_CYAN "\x1b[1;36m"
#define COLOR_WHITE "\x1b[1;37m"
#define BGCOLOR_RED "\x1b[48;5;124m"
#define BGCOLOR_BLUE "\x1b[48;5;20m"
#define BGCOLOR_YELLOW "\x1b[48;5;214m"
#define BGCOLOR_GREEN "\x1b[48;5;28m"
#define BGCOLOR_PINK "\x1b[48;5;165m"
#define JS_VALUE_FREE(ctx, value) \
do { \
JS_FreeValue((ctx), (value)); \
(value) = JS_UNDEFINED; \
} while(0);
#define JS_VALUE_FREE_RT(ctx, value) \
do { \
JS_FreeValueRT((ctx), (value)); \
(value) = JS_UNDEFINED; \
} while(0);
#if 0
#define js_object_tmpmark_set(value) \
do { \
((uint8_t*)JS_VALUE_GET_OBJ((value)))[5] |= 0x40; \
} while(0);
#define js_object_tmpmark_clear(value) \
do { \
((uint8_t*)JS_VALUE_GET_OBJ((value)))[5] &= ~0x40; \
} while(0);
#define js_object_tmpmark_isset(value) (((uint8_t*)JS_VALUE_GET_OBJ((value)))[5] & 0x40)
#else
#define js_object_tmpmark_set(value) \
do { \
JS_VALUE_GET_OBJ((value))->tmp_mark |= 0x40; \
} while(0);
#define js_object_tmpmark_clear(value) \
do { \
JS_VALUE_GET_OBJ((value))->tmp_mark &= ~0x40; \
} while(0);
#define js_object_tmpmark_isset(value) (JS_VALUE_GET_OBJ((value))->tmp_mark & 0x40)
#endif
#define js_runtime_exception_set(rt, value) \
do { \
*(JSValue*)((uint8_t*)(rt) + 216) = value; \
} while(0);
#define js_runtime_exception_get(rt) (*(JSValue*)((uint8_t*)(rt) + 216))
#define js_runtime_exception_clear(rt) \
do { \
if(!JS_IsNull(js_runtime_exception_get(rt))) \
JS_FreeValueRT((rt), js_runtime_exception_get(rt)); \
js_runtime_exception_set(rt, JS_NULL); \
} while(0)
#define JS_ATOM_TAG_INT (1U << 31)
#define JS_ATOM_MAX_INT (JS_ATOM_TAG_INT - 1)
#define JS_ATOM_ISINT(i) ((JSAtom)((i)&JS_ATOM_TAG_INT))
#define JS_ATOM_FROMINT(i) ((JSAtom)((i)&JS_ATOM_MAX_INT) | JS_ATOM_TAG_INT)
#define JS_ATOM_TOINT(i) (unsigned int)(((JSAtom)(i) & (~(JS_ATOM_TAG_INT))))
/**
* @}
*/
#endif /* defined(DEFINES_H) */

45
src/quickjs/hello.c Normal file
View File

@@ -0,0 +1,45 @@
/* File generated automatically by the QuickJS compiler. */
#include "quickjs-libc.h"
const uint32_t qjsc_hello_size = 87;
const uint8_t qjsc_hello[87] = {
0x43, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,
0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x16, 0x48,
0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72,
0x6c, 0x64, 0x22, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c,
0x6f, 0x2e, 0x6a, 0x73, 0x0c, 0x00, 0x06, 0x00,
0xa2, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00,
0x14, 0x01, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x38,
0xe3, 0x00, 0x00, 0x00, 0x42, 0xe4, 0x00, 0x00,
0x00, 0x04, 0xe5, 0x00, 0x00, 0x00, 0x24, 0x01,
0x00, 0xcf, 0x28, 0xcc, 0x03, 0x01, 0x00,
};
static JSContext *JS_NewCustomContext(JSRuntime *rt)
{
JSContext *ctx = JS_NewContextRaw(rt);
if (!ctx)
return NULL;
JS_AddIntrinsicBaseObjects(ctx);
return ctx;
}
int main(int argc, char **argv)
{
JSRuntime *rt;
JSContext *ctx;
rt = JS_NewRuntime();
js_std_set_worker_new_context_func(JS_NewCustomContext);
js_std_init_handlers(rt);
ctx = JS_NewCustomContext(rt);
js_std_add_helpers(ctx, argc, argv);
js_std_eval_binary(ctx, qjsc_hello, qjsc_hello_size, 0);
js_std_loop(ctx);
js_std_free_handlers(rt);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}

27
src/quickjs/iso_8859_1.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_1_H
#define TUTF8E_ISO_8859_1_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_1_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_1, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_1_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_1, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_1_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_1, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_1_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_1, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_10.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_10_H
#define TUTF8E_ISO_8859_10_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_10_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_10, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_10_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_10, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_10_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_10, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_10_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_10, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_11.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_11_H
#define TUTF8E_ISO_8859_11_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_11_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_11, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_11_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_11, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_11_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_11, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_11_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_11, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_13.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_13_H
#define TUTF8E_ISO_8859_13_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_13_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_13, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_13_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_13, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_13_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_13, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_13_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_13, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_14.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_14_H
#define TUTF8E_ISO_8859_14_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_14_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_14, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_14_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_14, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_14_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_14, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_14_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_14, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_15.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_15_H
#define TUTF8E_ISO_8859_15_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_15_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_15, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_15_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_15, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_15_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_15, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_15_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_15, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_16.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_16_H
#define TUTF8E_ISO_8859_16_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_16_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_16, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_16_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_16, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_16_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_16, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_16_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_16, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_2.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_2_H
#define TUTF8E_ISO_8859_2_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_2_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_2, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_2_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_2, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_2_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_2, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_2_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_2, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_3.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_3_H
#define TUTF8E_ISO_8859_3_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_3_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_3, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_3_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_3, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_3_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_3, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_3_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_3, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_4.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_4_H
#define TUTF8E_ISO_8859_4_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_4_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_4, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_4_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_4, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_4_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_4, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_4_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_4, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_5.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_5_H
#define TUTF8E_ISO_8859_5_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_5_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_5, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_5_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_5, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_5_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_5, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_5_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_5, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_6.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_6_H
#define TUTF8E_ISO_8859_6_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_6_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_6, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_6_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_6, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_6_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_6, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_6_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_6, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_7.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_7_H
#define TUTF8E_ISO_8859_7_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_7_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_7, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_7_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_7, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_7_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_7, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_7_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_7, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_8.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_8_H
#define TUTF8E_ISO_8859_8_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_8_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_8, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_8_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_8, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_8_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_8, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_8_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_8, input, input_length, invalid, output, output_length);
}
#endif

27
src/quickjs/iso_8859_9.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TUTF8E_ISO_8859_9_H
#define TUTF8E_ISO_8859_9_H
#include <tutf8e.h>
static inline int tutf8e_iso_8859_9_string_length(const char *input, size_t *input_length, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_length(tutf8e_encoder_iso_8859_9, input, input_length, invalid, output_length);
}
static inline int tutf8e_iso_8859_9_string_encode(const char *input, char *output, const char *invalid, size_t *output_length)
{
return tutf8e_encoder_string_encode(tutf8e_encoder_iso_8859_9, input, invalid, output, output_length);
}
static inline int tutf8e_iso_8859_9_buffer_length(const char *i, size_t input_length, const char *invalid, size_t *length)
{
return tutf8e_encoder_buffer_length(tutf8e_encoder_iso_8859_9, input, input_length, invalid, length);
}
static inline int tutf8e_iso_8859_9_buffer_encode(const char *i, size_t input_length, const char *invalid, char *output, size_t *output_length)
{
return tutf8e_encoder_buffer_encode(tutf8e_encoder_iso_8859_9, input, input_length, invalid, output, output_length);
}
#endif

8473
src/quickjs/libbf.c Normal file

File diff suppressed because it is too large Load Diff

535
src/quickjs/libbf.h Normal file
View File

@@ -0,0 +1,535 @@
/*
* Tiny arbitrary precision floating point library
*
* Copyright (c) 2017-2021 Fabrice Bellard
*
* 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 LIBBF_H
#define LIBBF_H
#include <stddef.h>
#include <stdint.h>
#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
#define LIMB_LOG2_BITS 6
#else
#define LIMB_LOG2_BITS 5
#endif
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
#if LIMB_BITS == 64
typedef __int128 int128_t;
typedef unsigned __int128 uint128_t;
typedef int64_t slimb_t;
typedef uint64_t limb_t;
typedef uint128_t dlimb_t;
#define BF_RAW_EXP_MIN INT64_MIN
#define BF_RAW_EXP_MAX INT64_MAX
#define LIMB_DIGITS 19
#define BF_DEC_BASE UINT64_C(10000000000000000000)
#else
typedef int32_t slimb_t;
typedef uint32_t limb_t;
typedef uint64_t dlimb_t;
#define BF_RAW_EXP_MIN INT32_MIN
#define BF_RAW_EXP_MAX INT32_MAX
#define LIMB_DIGITS 9
#define BF_DEC_BASE 1000000000U
#endif
/* in bits */
/* minimum number of bits for the exponent */
#define BF_EXP_BITS_MIN 3
/* maximum number of bits for the exponent */
#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
/* extended range for exponent, used internally */
#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
/* minimum possible precision */
#define BF_PREC_MIN 2
/* minimum possible precision */
#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
/* some operations support infinite precision */
#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
#if LIMB_BITS == 64
#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
#else
#define BF_CHKSUM_MOD 975620677U
#endif
#define BF_EXP_ZERO BF_RAW_EXP_MIN
#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
#define BF_EXP_NAN BF_RAW_EXP_MAX
/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
+/-infinity is represented with expn = BF_EXP_INF and len = 0,
NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
*/
typedef struct {
struct bf_context_t *ctx;
int sign;
slimb_t expn;
limb_t len;
limb_t *tab;
} bf_t;
typedef struct {
/* must be kept identical to bf_t */
struct bf_context_t *ctx;
int sign;
slimb_t expn;
limb_t len;
limb_t *tab;
} bfdec_t;
typedef enum {
BF_RNDN, /* round to nearest, ties to even */
BF_RNDZ, /* round to zero */
BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */
BF_RNDU, /* round to +inf */
BF_RNDNA, /* round to nearest, ties away from zero */
BF_RNDA, /* round away from zero */
BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
inexact flag is always set) */
} bf_rnd_t;
/* allow subnormal numbers. Only available if the number of exponent
bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */
#define BF_FLAG_SUBNORMAL (1 << 3)
/* 'prec' is the precision after the radix point instead of the whole
mantissa. Can only be used with bf_round() and
bfdec_[add|sub|mul|div|sqrt|round](). */
#define BF_FLAG_RADPNT_PREC (1 << 4)
#define BF_RND_MASK 0x7
#define BF_EXP_BITS_SHIFT 5
#define BF_EXP_BITS_MASK 0x3f
/* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */
#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
/* contains the rounding mode and number of exponents bits */
typedef uint32_t bf_flags_t;
typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
typedef struct {
bf_t val;
limb_t prec;
} BFConstCache;
typedef struct bf_context_t {
void *realloc_opaque;
bf_realloc_func_t *realloc_func;
BFConstCache log2_cache;
BFConstCache pi_cache;
struct BFNTTState *ntt_state;
} bf_context_t;
static inline int bf_get_exp_bits(bf_flags_t flags)
{
int e;
e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
if (e == BF_EXP_BITS_MASK)
return BF_EXP_BITS_MAX + 1;
else
return BF_EXP_BITS_MAX - e;
}
static inline bf_flags_t bf_set_exp_bits(int n)
{
return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
}
/* returned status */
#define BF_ST_INVALID_OP (1 << 0)
#define BF_ST_DIVIDE_ZERO (1 << 1)
#define BF_ST_OVERFLOW (1 << 2)
#define BF_ST_UNDERFLOW (1 << 3)
#define BF_ST_INEXACT (1 << 4)
/* indicate that a memory allocation error occured. NaN is returned */
#define BF_ST_MEM_ERROR (1 << 5)
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
static inline slimb_t bf_max(slimb_t a, slimb_t b)
{
if (a > b)
return a;
else
return b;
}
static inline slimb_t bf_min(slimb_t a, slimb_t b)
{
if (a < b)
return a;
else
return b;
}
void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
void *realloc_opaque);
void bf_context_end(bf_context_t *s);
/* free memory allocated for the bf cache data */
void bf_clear_cache(bf_context_t *s);
static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
{
return s->realloc_func(s->realloc_opaque, ptr, size);
}
/* 'size' must be != 0 */
static inline void *bf_malloc(bf_context_t *s, size_t size)
{
return bf_realloc(s, NULL, size);
}
static inline void bf_free(bf_context_t *s, void *ptr)
{
/* must test ptr otherwise equivalent to malloc(0) */
if (ptr)
bf_realloc(s, ptr, 0);
}
void bf_init(bf_context_t *s, bf_t *r);
static inline void bf_delete(bf_t *r)
{
bf_context_t *s = r->ctx;
/* we accept to delete a zeroed bf_t structure */
if (s && r->tab) {
bf_realloc(s, r->tab, 0);
}
}
static inline void bf_neg(bf_t *r)
{
r->sign ^= 1;
}
static inline int bf_is_finite(const bf_t *a)
{
return (a->expn < BF_EXP_INF);
}
static inline int bf_is_nan(const bf_t *a)
{
return (a->expn == BF_EXP_NAN);
}
static inline int bf_is_zero(const bf_t *a)
{
return (a->expn == BF_EXP_ZERO);
}
static inline void bf_memcpy(bf_t *r, const bf_t *a)
{
*r = *a;
}
int bf_set_ui(bf_t *r, uint64_t a);
int bf_set_si(bf_t *r, int64_t a);
void bf_set_nan(bf_t *r);
void bf_set_zero(bf_t *r, int is_neg);
void bf_set_inf(bf_t *r, int is_neg);
int bf_set(bf_t *r, const bf_t *a);
void bf_move(bf_t *r, bf_t *a);
int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
int bf_set_float64(bf_t *a, double d);
int bf_cmpu(const bf_t *a, const bf_t *b);
int bf_cmp_full(const bf_t *a, const bf_t *b);
int bf_cmp(const bf_t *a, const bf_t *b);
static inline int bf_cmp_eq(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) == 0;
}
static inline int bf_cmp_le(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) <= 0;
}
static inline int bf_cmp_lt(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) < 0;
}
int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
#define BF_DIVREM_EUCLIDIAN BF_RNDF
int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
limb_t prec, bf_flags_t flags, int rnd_mode);
int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
/* round to integer with infinite precision */
int bf_rint(bf_t *r, int rnd_mode);
int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
slimb_t bf_get_exp_min(const bf_t *a);
int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
/* additional flags for bf_atof */
/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
#define BF_ATOF_NO_HEX (1 << 16)
/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
#define BF_ATOF_BIN_OCT (1 << 17)
/* Do not parse NaN or Inf */
#define BF_ATOF_NO_NAN_INF (1 << 18)
/* return the exponent separately */
#define BF_ATOF_EXPONENT (1 << 19)
int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
limb_t prec, bf_flags_t flags);
/* this version accepts prec = BF_PREC_INF and returns the radix
exponent */
int bf_atof2(bf_t *r, slimb_t *pexponent,
const char *str, const char **pnext, int radix,
limb_t prec, bf_flags_t flags);
int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
slimb_t expn, limb_t prec, bf_flags_t flags);
/* Conversion of floating point number to string. Return a null
terminated string or NULL if memory error. *plen contains its
length if plen != NULL. The exponent letter is "e" for base 10,
"p" for bases 2, 8, 16 with a binary exponent and "@" for the other
bases. */
#define BF_FTOA_FORMAT_MASK (3 << 16)
/* fixed format: prec significant digits rounded with (flags &
BF_RND_MASK). Exponential notation is used if too many zeros are
needed.*/
#define BF_FTOA_FORMAT_FIXED (0 << 16)
/* fractional format: prec digits after the decimal point rounded with
(flags & BF_RND_MASK) */
#define BF_FTOA_FORMAT_FRAC (1 << 16)
/* free format:
For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
number of digits to represent 'a'. The precision and the rounding
mode are ignored.
For the non binary radices with bf_ftoa(): use as many digits as
necessary so that bf_atof() return the same number when using
precision 'prec', rounding to nearest and the subnormal
configuration of 'flags'. The result is meaningful only if 'a' is
already rounded to 'prec' bits. If the subnormal flag is set, the
exponent in 'flags' must also be set to the desired exponent range.
*/
#define BF_FTOA_FORMAT_FREE (2 << 16)
/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
(takes more computation time). Identical to BF_FTOA_FORMAT_FREE for
binary radices with bf_ftoa() and for bfdec_ftoa(). */
#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
/* force exponential notation for fixed or free format */
#define BF_FTOA_FORCE_EXP (1 << 20)
/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
base 2 if non zero value */
#define BF_FTOA_ADD_PREFIX (1 << 21)
/* return "Infinity" instead of "Inf" and add a "+" for positive
exponents */
#define BF_FTOA_JS_QUIRKS (1 << 22)
char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
bf_flags_t flags);
/* modulo 2^n instead of saturation. NaN and infinity return 0 */
#define BF_GET_INT_MOD (1 << 0)
int bf_get_int32(int *pres, const bf_t *a, int flags);
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
int bf_get_uint64(uint64_t *pres, const bf_t *a);
/* the following functions are exported for testing only. */
void mp_print_str(const char *str, const limb_t *tab, limb_t n);
void bf_print_str(const char *str, const bf_t *a);
int bf_resize(bf_t *r, limb_t len);
int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
int is_ceil1);
int mp_mul(bf_context_t *s, limb_t *result,
const limb_t *op1, limb_t op1_size,
const limb_t *op2, limb_t op2_size);
limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
limb_t n, limb_t carry);
limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n);
limb_t bf_isqrt(limb_t a);
/* transcendental functions */
int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
limb_t prec, bf_flags_t flags);
int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
/* decimal floating point */
static inline void bfdec_init(bf_context_t *s, bfdec_t *r)
{
bf_init(s, (bf_t *)r);
}
static inline void bfdec_delete(bfdec_t *r)
{
bf_delete((bf_t *)r);
}
static inline void bfdec_neg(bfdec_t *r)
{
r->sign ^= 1;
}
static inline int bfdec_is_finite(const bfdec_t *a)
{
return (a->expn < BF_EXP_INF);
}
static inline int bfdec_is_nan(const bfdec_t *a)
{
return (a->expn == BF_EXP_NAN);
}
static inline int bfdec_is_zero(const bfdec_t *a)
{
return (a->expn == BF_EXP_ZERO);
}
static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a)
{
bf_memcpy((bf_t *)r, (const bf_t *)a);
}
int bfdec_set_ui(bfdec_t *r, uint64_t a);
int bfdec_set_si(bfdec_t *r, int64_t a);
static inline void bfdec_set_nan(bfdec_t *r)
{
bf_set_nan((bf_t *)r);
}
static inline void bfdec_set_zero(bfdec_t *r, int is_neg)
{
bf_set_zero((bf_t *)r, is_neg);
}
static inline void bfdec_set_inf(bfdec_t *r, int is_neg)
{
bf_set_inf((bf_t *)r, is_neg);
}
static inline int bfdec_set(bfdec_t *r, const bfdec_t *a)
{
return bf_set((bf_t *)r, (bf_t *)a);
}
static inline void bfdec_move(bfdec_t *r, bfdec_t *a)
{
bf_move((bf_t *)r, (bf_t *)a);
}
static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmpu((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmp_full((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmp((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) == 0;
}
static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) <= 0;
}
static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) < 0;
}
int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
limb_t prec, bf_flags_t flags, int rnd_mode);
int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
int bfdec_rint(bfdec_t *r, int rnd_mode);
int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags);
int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
int bfdec_get_int32(int *pres, const bfdec_t *a);
int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b);
char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags);
int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
limb_t prec, bf_flags_t flags);
/* the following functions are exported for testing only. */
extern const limb_t mp_pow_dec[LIMB_DIGITS + 1];
void bfdec_print_str(const char *str, const bfdec_t *a);
static inline int bfdec_resize(bfdec_t *r, limb_t len)
{
return bf_resize((bf_t *)r, len);
}
int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
#endif /* LIBBF_H */

View File

@@ -0,0 +1,57 @@
/*
* Regular Expression Engine
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* 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.
*/
#ifdef DEF
DEF(invalid, 1) /* never used */
DEF(char, 3)
DEF(char32, 5)
DEF(dot, 1)
DEF(any, 1) /* same as dot but match any character including line terminator */
DEF(line_start, 1)
DEF(line_end, 1)
DEF(goto, 5)
DEF(split_goto_first, 5)
DEF(split_next_first, 5)
DEF(match, 1)
DEF(save_start, 2) /* save start position */
DEF(save_end, 2) /* save end position, must come after saved_start */
DEF(save_reset, 3) /* reset save positions */
DEF(loop, 5) /* decrement the top the stack and goto if != 0 */
DEF(push_i32, 5) /* push integer on the stack */
DEF(drop, 1)
DEF(word_boundary, 1)
DEF(not_word_boundary, 1)
DEF(back_reference, 2)
DEF(backward_back_reference, 2) /* must come after back_reference */
DEF(range, 3) /* variable length */
DEF(range32, 3) /* variable length */
DEF(lookahead, 5)
DEF(negative_lookahead, 5)
DEF(push_char_pos, 1) /* push the character position on the stack */
DEF(check_advance, 1) /* pop one stack element and check that it is different from the character position */
DEF(prev, 1) /* go to the previous char */
DEF(simple_greedy_quant, 17)
#endif /* DEF */

2528
src/quickjs/libregexp.c Normal file

File diff suppressed because it is too large Load Diff

92
src/quickjs/libregexp.h Normal file
View File

@@ -0,0 +1,92 @@
/*
* Regular Expression Engine
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* 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 LIBREGEXP_H
#define LIBREGEXP_H
#include <stddef.h>
#include "libunicode.h"
#define LRE_BOOL int /* for documentation purposes */
#define LRE_FLAG_GLOBAL (1 << 0)
#define LRE_FLAG_IGNORECASE (1 << 1)
#define LRE_FLAG_MULTILINE (1 << 2)
#define LRE_FLAG_DOTALL (1 << 3)
#define LRE_FLAG_UNICODE (1 << 4)
#define LRE_FLAG_STICKY (1 << 5)
#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
const char *buf, size_t buf_len, int re_flags,
void *opaque);
int lre_get_capture_count(const uint8_t *bc_buf);
int lre_get_flags(const uint8_t *bc_buf);
const char *lre_get_groupnames(const uint8_t *bc_buf);
int lre_exec(uint8_t **capture,
const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
int cbuf_type, void *opaque);
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
LRE_BOOL lre_is_space(int c);
/* must be provided by the user */
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
/* JS identifier test */
extern uint32_t const lre_id_start_table_ascii[4];
extern uint32_t const lre_id_continue_table_ascii[4];
static inline int lre_js_is_ident_first(int c)
{
if ((uint32_t)c < 128) {
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_start(c);
#else
return !lre_is_space(c);
#endif
}
}
static inline int lre_js_is_ident_next(int c)
{
if ((uint32_t)c < 128) {
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
/* ZWNJ and ZWJ are accepted in identifiers */
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
#else
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
#endif
}
}
#undef LRE_BOOL
#endif /* LIBREGEXP_H */

File diff suppressed because it is too large Load Diff

1788
src/quickjs/libunicode.c Normal file

File diff suppressed because it is too large Load Diff

127
src/quickjs/libunicode.h Normal file
View File

@@ -0,0 +1,127 @@
/*
* Unicode utilities
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* 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 LIBUNICODE_H
#define LIBUNICODE_H
#include <inttypes.h>
#define LRE_BOOL int /* for documentation purposes */
/* define it to include all the unicode tables (40KB larger) */
#define CONFIG_ALL_UNICODE
#define LRE_CC_RES_LEN_MAX 3
typedef enum {
UNICODE_NFC,
UNICODE_NFD,
UNICODE_NFKC,
UNICODE_NFKD,
} UnicodeNormalizationEnum;
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
int lre_canonicalize(uint32_t c, LRE_BOOL is_unicode);
LRE_BOOL lre_is_cased(uint32_t c);
LRE_BOOL lre_is_case_ignorable(uint32_t c);
/* char ranges */
typedef struct {
int len; /* in points, always even */
int size;
uint32_t *points; /* points sorted by increasing value */
void *mem_opaque;
void *(*realloc_func)(void *opaque, void *ptr, size_t size);
} CharRange;
typedef enum {
CR_OP_UNION,
CR_OP_INTER,
CR_OP_XOR,
} CharRangeOpEnum;
void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
void cr_free(CharRange *cr);
int cr_realloc(CharRange *cr, int size);
int cr_copy(CharRange *cr, const CharRange *cr1);
static inline int cr_add_point(CharRange *cr, uint32_t v)
{
if (cr->len >= cr->size) {
if (cr_realloc(cr, cr->len + 1))
return -1;
}
cr->points[cr->len++] = v;
return 0;
}
static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2)
{
if ((cr->len + 2) > cr->size) {
if (cr_realloc(cr, cr->len + 2))
return -1;
}
cr->points[cr->len++] = c1;
cr->points[cr->len++] = c2;
return 0;
}
int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len);
static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2)
{
uint32_t b_pt[2];
b_pt[0] = c1;
b_pt[1] = c2 + 1;
return cr_union1(cr, b_pt, 2);
}
int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
const uint32_t *b_pt, int b_len, int op);
int cr_invert(CharRange *cr);
int cr_regexp_canonicalize(CharRange *cr, LRE_BOOL is_unicode);
#ifdef CONFIG_ALL_UNICODE
LRE_BOOL lre_is_id_start(uint32_t c);
LRE_BOOL lre_is_id_continue(uint32_t c);
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
UnicodeNormalizationEnum n_type,
void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
/* Unicode character range functions */
int unicode_script(CharRange *cr,
const char *script_name, LRE_BOOL is_ext);
int unicode_general_category(CharRange *cr, const char *gc_name);
int unicode_prop(CharRange *cr, const char *prop_name);
#endif /* CONFIG_ALL_UNICODE */
#undef LRE_BOOL
#endif /* LIBUNICODE_H */

153
src/quickjs/libutf.c Normal file
View File

@@ -0,0 +1,153 @@
#include <libutf.h>
#include <assert.h>
#include <stdlib.h>
LibutfC16Type libutf_c16_type(uint_least16_t c16) {
if (0xD800 != (0xF800 & c16)) {
return LIBUTF_UTF16_NOT_SURROGATE;
}
return (c16 & 0x0400) ? LIBUTF_UTF16_SURROGATE_LOW : LIBUTF_UTF16_SURROGATE_HIGH;
}
LibutfC8Type libutf_c8_type(char c) {
static const LibutfC8Type lookup_table[256] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4,-2,-2,-2,-2,-2,-2,-2,-2,
};
return lookup_table[(unsigned char) c];
}
bool libutf_c32_to_c8(uint_least32_t c32, int *length, char c8[4]) {
if (!libutf_c32_is_valid(c32)) {
*length = 3;
c8[0] = (char) 0xEF;
c8[1] = (char) 0xBF;
c8[2] = (char) 0xBD;
return false;
}
if (c32 <= 0x007F) {
c8[0] = c32;
*length = 1;
return true;
} else if (c32 <= 0x07FF) {
c8[0] = (char) (0xC0 | (c32 >> 6));
c8[1] = (char) (0x80 | (c32 & 0x3F));
*length = 2;
return true;
} else if (c32 <= 0xFFFF) {
c8[0] = (char) (0xE0 | (c32 >> 12));
c8[1] = (char) (0x80 | ((c32 >> 6) & 0x3F));
c8[2] = (char) (0x80 | (c32 & 0x3F));
*length = 3;
return true;
}
assert(c32 <= 0x10FFFF);
c8[0] = (char) (0xF0 | (c32 >> 18));
c8[1] = (char) (0x80 | ((c32 >> 12) & 0x3F));
c8[2] = (char) (0x80 | ((c32 >> 6) & 0x3F));
c8[3] = (char) (0x80 | (c32 & 0x3F));
*length = 4;
return true;
}
bool libutf_c8_to_c32(const char *c8, uint_least32_t *c32) {
if (!c8 || !c32) {
return false;
}
unsigned char c = *c8;
*c32 = 0xFFFD;
LibutfC8Type type = libutf_c8_type(c);
if (type < 0) {
return false;
}
int len = type;
uint_least32_t result;
switch (len) {
case 1:
*c32 = c;
return true;
case 2:
result = c & 0x1F;
break;
case 3:
result = c & 0x0F;
break;
case 4:
result = c & 0x07;
break;
default:
abort();
}
for (int i = 1; i < len; ++i) {
c = *++c8;
if ((0xC0 & c) != 0x80) {
return false;
}
result = (result << 6) + (c & 0x3F);
}
if (!libutf_c32_is_valid(result)) {
return false;
}
char c8seq[4];
int n;
bool ok = libutf_c32_to_c8(result, &n, c8seq);
assert(ok);
if (n < (int) len) {
return false;
}
*c32 = result;
return true;
}
bool libutf_c32_to_c16(uint_least32_t c32, int *length, uint_least16_t c16[2]) {
if (!libutf_c32_is_valid(c32)) {
c16[0] = 0xFFFD;
c16[1] = 0;
*length = 1;
return false;
}
if (c32 < 0x10000) {
c16[0] = c32;
c16[1] = 0;
*length = 1;
} else {
c32 -= 0x10000;
c16[0] = 0xD800 | (c32 >> 10);
c16[1] = 0xDC00 | (c32 & 0x3FF);
*length = 2;
}
return true;
}
bool libutf_c16_to_c32(uint_least16_t c16[2], uint_least32_t *c32) {
LibutfC16Type type = libutf_c16_type(c16[0]);
if (LIBUTF_UTF16_NOT_SURROGATE == type) {
*c32 = c16[0];
return true;
}
if (LIBUTF_UTF16_SURROGATE_HIGH != type || LIBUTF_UTF16_SURROGATE_LOW != libutf_c16_type(c16[1])) {
*c32 = 0xFFFD;
return false;
}
*c32 = 0x10000 + ((c16[0] & 0x3FF) << 10) + (c16[1] & 0x3ff);
return true;
}
bool libutf_c32_is_valid(uint_least32_t c32) {
return c32 < 0xD800 || (0xDFFF < c32 && c32 < 0x110000);
}

109
src/quickjs/libutf.h Normal file
View File

@@ -0,0 +1,109 @@
/* LIBrary of UTF-(8,16,32) helper utility functions.
*
* Terminology:
* code point = number of a Unicode character
* code unit
* = 1 byte for UTF-8
* = 2 bytes for UTF-16
* = 4 bytes for UTF-32
* sequence = sequence of code units encoding SINGLE Unicode character
*
* Unicode has code points 0x000000..0x10FFFF except for the codes 0xD800..0xDFFF which are
* reserved for UTF-16 surrogate pairs.
*
* UTF-32 is the simplest Unicode encoding. It encodes Unicode code points as is. Thus we may use
* UTF-32 as a synonym for Unicode code point.
* + O(1) indexing
* - the text is 2-4 times bigger than in other encodings
*
* UTF-16 is variable width encoding. Each Unicode code point is represented as either single
* code unit (two-byte number) or two code units which are called surrogate pairs.
* - ASCII-only texts will be twice as big as in ASCII
* - O(n) indexing
*
* UTF-8 is a variable width encoding. Each Unicode code point is represented as a sequence
* of up to 4 bytes. The first byte determines the length of the sequence.
* + is a superset of ASCII
* + ASCII-only texts will have the same size
* - O(n) indexing
* - single Unicode code point can have different representations in
* UTF-8, only the shortest one is considered valid
*/
#ifndef LIBUTF_H
#define LIBUTF_H
#include <stdbool.h>
#include <stdint.h>
// UTF-8 code unit type
typedef enum {
LIBUTF_UTF8_OVERLONG = -2,
LIBUTF_UTF8_TRAILING = -1,
LIBUTF_UTF8_ONE_BYTE = 1,
LIBUTF_UTF8_TWO_BYTE = 2,
LIBUTF_UTF8_THREE_BYTE = 3,
LIBUTF_UTF8_FOUR_BYTE = 4,
} LibutfC8Type;
// UTF-16 code unit type
typedef enum {
LIBUTF_UTF16_SURROGATE_LOW = -1,
LIBUTF_UTF16_NOT_SURROGATE = 1,
LIBUTF_UTF16_SURROGATE_HIGH = 2,
} LibutfC16Type;
/* Determine type of UTF-16 code unit. type = length of UTF-16 sequence starting with the specified code unit
* or negative value if sequence cannot start with this code unit. */
LibutfC16Type libutf_c16_type(uint_least16_t c16);
/* Determine type of UTF-8 sequence based on the first byte. type = length of UTF-8 sequence starting
* with this byte or negative value if the byte cannot be first. UTF-8 may be up to 4 bytes long.
* Common idiom for using this function:
* >>> LibutfC8Type type = libutf_c8_type(c);
* >>> if (type < 0) {
* >>> return ERROR_CODE;
* >>> }
* >>> int length = type;
* */
LibutfC8Type libutf_c8_type(char c);
/* Convert Unicode code point into UTF-8 sequence. If c32 is not a valid
* Unicode code point c8 will be filled with UTF-8 representation of special
* replacement character U+FFFD, *length will be set to its length and false will be returned.
* c32 -- UTF-32 Unicode code point
* length -- where to put length of the UTF-8 sequence.
* c8 -- where to put UTF-8 sequence. Make sure string has enough space.
* result -- true if c32 is a valid Unicode code point or false otherwise. */
bool libutf_c32_to_c8(uint_least32_t c32, int *length, char c8[4]);
/* Convert UTF-8 sequence into a UTF-32 Unicode code point. If c8 does not
* point to a valid UTF-8 sequence c32 will be filled with special replacement
* character U+FFFD and false will be returned.
* c8 -- pointer to UTF-8 sequence.
* c32 -- where to save UTF-32 Unicode code point.
* result -- true if c8 points to a valid UTF-8 sequence or false otherwise. */
bool libutf_c8_to_c32(const char *c8, uint_least32_t *c32);
/* Convert UTF-32 Unicode code point into UTF-16 sequence. If c32 is not a valid
* Unicode code point c16 will be filled with UTF-16 representation of special
* replacement character U+FFFD and false will be returned.
* c32 -- UTF-32 Unicode code point.
* length -- were to put length of UTF-16 sequence.
* c16 -- where to put UTF-16 sequence (c16[0] -- high surrogate, c16[1] -- low surrogate)
* result -- true if c32 is a valid Unicode code point or false otherwise. */
bool libutf_c32_to_c16(uint_least32_t c32, int *length, uint_least16_t c16[2]);
/* Construct UTF-32 Unicode code point from UTF-16 surrogate pair. high
* must be high surrogate and low must be low surrogate otherwise *c32 will
* be filled with special replacement character U+FFFD and false will be returned.
* c16 -- where to put UTF-16 sequence (c32[0] -- high surrogate, c32[1] -- low surrogate)
* result -- true if c16 points to a valid UTF-16 sequence (single not surrogate
* or valid surrogate pair) or false otherwise. */
bool libutf_c16_to_c32(uint_least16_t c16[2], uint_least32_t *c32);
/* Check whether given value is a valid Unicode code point i.e. below 0x110000 and is not
* a UTF-16 surrogate. */
bool libutf_c32_is_valid(uint_least32_t c32);
#endif

99
src/quickjs/list.h Normal file
View File

@@ -0,0 +1,99 @@
/*
* Linux klist like system
*
* Copyright (c) 2016-2017 Fabrice Bellard
*
* 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 LIST_H
#define LIST_H
#ifndef NULL
#include <stddef.h>
#endif
struct list_head {
struct list_head *prev;
struct list_head *next;
};
#define LIST_HEAD_INIT(el) { &(el), &(el) }
/* return the pointer of type 'type *' containing 'el' as field 'member' */
#define list_entry(el, type, member) container_of(el, type, member)
static inline void init_list_head(struct list_head *head)
{
head->prev = head;
head->next = head;
}
/* insert 'el' between 'prev' and 'next' */
static inline void __list_add(struct list_head *el,
struct list_head *prev, struct list_head *next)
{
prev->next = el;
el->prev = prev;
el->next = next;
next->prev = el;
}
/* add 'el' at the head of the list 'head' (= after element head) */
static inline void list_add(struct list_head *el, struct list_head *head)
{
__list_add(el, head, head->next);
}
/* add 'el' at the end of the list 'head' (= before element head) */
static inline void list_add_tail(struct list_head *el, struct list_head *head)
{
__list_add(el, head->prev, head);
}
static inline void list_del(struct list_head *el)
{
struct list_head *prev, *next;
prev = el->prev;
next = el->next;
prev->next = next;
next->prev = prev;
el->prev = NULL; /* fail safe */
el->next = NULL; /* fail safe */
}
static inline int list_empty(struct list_head *el)
{
return el->next == el;
}
#define list_for_each(el, head) \
for(el = (head)->next; el != (head); el = el->next)
#define list_for_each_safe(el, el1, head) \
for(el = (head)->next, el1 = el->next; el != (head); \
el = el1, el1 = el->next)
#define list_for_each_prev(el, head) \
for(el = (head)->prev; el != (head); el = el->prev)
#define list_for_each_prev_safe(el, el1, head) \
for(el = (head)->prev, el1 = el->prev; el != (head); \
el = el1, el1 = el->prev)
#endif /* LIST_H */

552
src/quickjs/qjs.c Normal file
View File

@@ -0,0 +1,552 @@
/*
* QuickJS stand alone interpreter
*
* Copyright (c) 2017-2021 Fabrice Bellard
* Copyright (c) 2017-2021 Charlie Gordon
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#if defined(__APPLE__)
#include <malloc/malloc.h>
#elif defined(__linux__)
#include <malloc.h>
#elif defined(__FreeBSD__)
#include <malloc_np.h>
#endif
#include "cutils.h"
#include "quickjs-libc.h"
#ifdef CONFIG_BIGNUM
static int bignum_ext;
#endif
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
const char *filename, int eval_flags)
{
JSValue val;
int ret;
if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) {
/* for the modules, we compile then run to be able to set
import.meta */
val = JS_Eval(ctx, buf, buf_len, filename,
eval_flags | JS_EVAL_FLAG_COMPILE_ONLY);
if (!JS_IsException(val)) {
js_module_set_import_meta(ctx, val, TRUE, TRUE);
val = JS_EvalFunction(ctx, val);
}
val = js_std_await(ctx, val);
} else {
val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
}
if (JS_IsException(val)) {
js_std_dump_error(ctx);
ret = -1;
} else {
ret = 0;
}
JS_FreeValue(ctx, val);
return ret;
}
static int eval_file(JSContext *ctx, const char *filename, int module)
{
uint8_t *buf;
int ret, eval_flags;
size_t buf_len;
buf = js_load_file(ctx, &buf_len, filename);
if (!buf) {
perror(filename);
exit(1);
}
if (module < 0) {
module = (has_suffix(filename, ".mjs") ||
JS_DetectModule((const char *)buf, buf_len));
}
if (module)
eval_flags = JS_EVAL_TYPE_MODULE;
else
eval_flags = JS_EVAL_TYPE_GLOBAL;
ret = eval_buf(ctx, buf, buf_len, filename, eval_flags);
js_free(ctx, buf);
return ret;
}
/* also used to initialize the worker context */
static JSContext *JS_NewCustomContext(JSRuntime *rt)
{
JSContext *ctx;
ctx = JS_NewContext(rt);
if (!ctx)
return NULL;
#ifdef CONFIG_BIGNUM
if (bignum_ext) {
JS_AddIntrinsicBigFloat(ctx);
JS_AddIntrinsicBigDecimal(ctx);
JS_AddIntrinsicOperators(ctx);
JS_EnableBignumExt(ctx, TRUE);
}
#endif
/* system modules */
js_init_module_std(ctx, "std");
js_init_module_os(ctx, "os");
return ctx;
}
#if defined(__APPLE__)
#define MALLOC_OVERHEAD 0
#else
#define MALLOC_OVERHEAD 8
#endif
struct trace_malloc_data {
uint8_t *base;
};
static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr,
struct trace_malloc_data *dp)
{
return ptr - dp->base;
}
/* default memory allocation functions with memory limitation */
static size_t js_trace_malloc_usable_size(const void *ptr)
{
#if defined(__APPLE__)
return malloc_size(ptr);
#elif defined(_WIN32)
return _msize((void *)ptr);
#elif defined(EMSCRIPTEN)
return 0;
#elif defined(__linux__)
return malloc_usable_size((void *)ptr);
#else
/* change this to `return 0;` if compilation fails */
return malloc_usable_size((void *)ptr);
#endif
}
static void
#ifdef _WIN32
/* mingw printf is used */
__attribute__((format(gnu_printf, 2, 3)))
#else
__attribute__((format(printf, 2, 3)))
#endif
js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...)
{
va_list ap;
int c;
va_start(ap, fmt);
while ((c = *fmt++) != '\0') {
if (c == '%') {
/* only handle %p and %zd */
if (*fmt == 'p') {
uint8_t *ptr = va_arg(ap, void *);
if (ptr == NULL) {
printf("NULL");
} else {
printf("H%+06lld.%zd",
js_trace_malloc_ptr_offset(ptr, s->opaque),
js_trace_malloc_usable_size(ptr));
}
fmt++;
continue;
}
if (fmt[0] == 'z' && fmt[1] == 'd') {
size_t sz = va_arg(ap, size_t);
printf("%zd", sz);
fmt += 2;
continue;
}
}
putc(c, stdout);
}
va_end(ap);
}
static void js_trace_malloc_init(struct trace_malloc_data *s)
{
free(s->base = malloc(8));
}
static void *js_trace_malloc(JSMallocState *s, size_t size)
{
void *ptr;
/* Do not allocate zero bytes: behavior is platform dependent */
assert(size != 0);
if (unlikely(s->malloc_size + size > s->malloc_limit))
return NULL;
ptr = malloc(size);
js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr);
if (ptr) {
s->malloc_count++;
s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
}
return ptr;
}
static void js_trace_free(JSMallocState *s, void *ptr)
{
if (!ptr)
return;
js_trace_malloc_printf(s, "F %p\n", ptr);
s->malloc_count--;
s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD;
free(ptr);
}
static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size)
{
size_t old_size;
if (!ptr) {
if (size == 0)
return NULL;
return js_trace_malloc(s, size);
}
old_size = js_trace_malloc_usable_size(ptr);
if (size == 0) {
js_trace_malloc_printf(s, "R %zd %p\n", size, ptr);
s->malloc_count--;
s->malloc_size -= old_size + MALLOC_OVERHEAD;
free(ptr);
return NULL;
}
if (s->malloc_size + size - old_size > s->malloc_limit)
return NULL;
js_trace_malloc_printf(s, "R %zd %p", size, ptr);
ptr = realloc(ptr, size);
js_trace_malloc_printf(s, " -> %p\n", ptr);
if (ptr) {
s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size;
}
return ptr;
}
static const JSMallocFunctions trace_mf = {
js_trace_malloc,
js_trace_free,
js_trace_realloc,
js_trace_malloc_usable_size,
};
#define PROG_NAME "qjs"
void help(void)
{
printf("QuickJS lite\n"
"usage: " PROG_NAME " [options] [file [args]]\n"
"-h --help list options\n"
"-e --eval EXPR evaluate EXPR\n"
"-i --interactive go to interactive mode\n"
"-m --module load as ES6 module (default=autodetect)\n"
" --script load as ES6 script (default=autodetect)\n"
"-I --include file include an additional file\n"
" --std make 'std' and 'os' available to the loaded script\n"
#ifdef CONFIG_BIGNUM
" --bignum enable the bignum extensions (BigFloat, BigDecimal)\n"
" --qjscalc load the QJSCalc runtime (default if invoked as qjscalc)\n"
#endif
"-T --trace trace memory allocation\n"
"-d --dump dump the memory usage stats\n"
" --memory-limit n limit the memory usage to 'n' bytes\n"
" --stack-size n limit the stack size to 'n' bytes\n"
" --unhandled-rejection dump unhandled promise rejections\n"
"-q --quit just instantiate the interpreter and quit\n");
exit(1);
}
int main(int argc, char **argv)
{
JSRuntime *rt;
JSContext *ctx;
struct trace_malloc_data trace_data = { NULL };
int optind;
char *expr = NULL;
int interactive = 0;
int dump_memory = 0;
int trace_memory = 0;
int empty_run = 0;
int module = -1;
int load_std = 0;
int dump_unhandled_promise_rejection = 0;
size_t memory_limit = 0;
char *include_list[32];
int i, include_count = 0;
#ifdef CONFIG_BIGNUM
int load_jscalc;
#endif
size_t stack_size = 0;
#ifdef CONFIG_BIGNUM
/* load jscalc runtime if invoked as 'qjscalc' */
{
const char *p, *exename;
exename = argv[0];
p = strrchr(exename, '/');
if (p)
exename = p + 1;
load_jscalc = !strcmp(exename, "qjscalc");
}
#endif
/* cannot use getopt because we want to pass the command line to
the script */
optind = 1;
while (optind < argc && *argv[optind] == '-') {
char *arg = argv[optind] + 1;
const char *longopt = "";
/* a single - is not an option, it also stops argument scanning */
if (!*arg)
break;
optind++;
if (*arg == '-') {
longopt = arg + 1;
arg += strlen(arg);
/* -- stops argument scanning */
if (!*longopt)
break;
}
for (; *arg || *longopt; longopt = "") {
char opt = *arg;
if (opt)
arg++;
if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) {
help();
continue;
}
if (opt == 'e' || !strcmp(longopt, "eval")) {
if (*arg) {
expr = arg;
break;
}
if (optind < argc) {
expr = argv[optind++];
break;
}
fprintf(stderr, "qjs: missing expression for -e\n");
exit(2);
}
if (opt == 'I' || !strcmp(longopt, "include")) {
if (optind >= argc) {
fprintf(stderr, "expecting filename");
exit(1);
}
if (include_count >= countof(include_list)) {
fprintf(stderr, "too many included files");
exit(1);
}
include_list[include_count++] = argv[optind++];
continue;
}
if (opt == 'i' || !strcmp(longopt, "interactive")) {
interactive++;
continue;
}
if (opt == 'm' || !strcmp(longopt, "module")) {
module = 1;
continue;
}
if (!strcmp(longopt, "script")) {
module = 0;
continue;
}
if (opt == 'd' || !strcmp(longopt, "dump")) {
dump_memory++;
continue;
}
if (opt == 'T' || !strcmp(longopt, "trace")) {
trace_memory++;
continue;
}
if (!strcmp(longopt, "std")) {
load_std = 1;
continue;
}
if (!strcmp(longopt, "unhandled-rejection")) {
dump_unhandled_promise_rejection = 1;
continue;
}
#ifdef CONFIG_BIGNUM
if (!strcmp(longopt, "bignum")) {
bignum_ext = 1;
continue;
}
if (!strcmp(longopt, "qjscalc")) {
load_jscalc = 1;
continue;
}
#endif
if (opt == 'q' || !strcmp(longopt, "quit")) {
empty_run++;
continue;
}
if (!strcmp(longopt, "memory-limit")) {
if (optind >= argc) {
fprintf(stderr, "expecting memory limit");
exit(1);
}
memory_limit = (size_t)strtod(argv[optind++], NULL);
continue;
}
if (!strcmp(longopt, "stack-size")) {
if (optind >= argc) {
fprintf(stderr, "expecting stack size");
exit(1);
}
stack_size = (size_t)strtod(argv[optind++], NULL);
continue;
}
if (opt) {
fprintf(stderr, "qjs: unknown option '-%c'\n", opt);
} else {
fprintf(stderr, "qjs: unknown option '--%s'\n", longopt);
}
help();
}
}
#ifdef CONFIG_BIGNUM
if (load_jscalc)
bignum_ext = 1;
#endif
if (trace_memory) {
js_trace_malloc_init(&trace_data);
rt = JS_NewRuntime2(&trace_mf, &trace_data);
} else {
rt = JS_NewRuntime();
}
if (!rt) {
fprintf(stderr, "qjs: cannot allocate JS runtime\n");
exit(2);
}
if (memory_limit != 0)
JS_SetMemoryLimit(rt, memory_limit);
if (stack_size != 0)
JS_SetMaxStackSize(rt, stack_size);
js_std_set_worker_new_context_func(JS_NewCustomContext);
js_std_init_handlers(rt);
ctx = JS_NewCustomContext(rt);
if (!ctx) {
fprintf(stderr, "qjs: cannot allocate JS context\n");
exit(2);
}
/* loader for ES6 modules */
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
if (dump_unhandled_promise_rejection) {
JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker,
NULL);
}
if (!empty_run) {
js_std_add_helpers(ctx, argc - optind, argv + optind);
/* make 'std' and 'os' visible to non module code */
if (load_std) {
const char *str = "import * as std from 'std';\n"
"import * as os from 'os';\n"
"globalThis.std = std;\n"
"globalThis.os = os;\n";
eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
}
for(i = 0; i < include_count; i++) {
if (eval_file(ctx, include_list[i], module))
goto fail;
}
if (expr) {
if (eval_buf(ctx, expr, strlen(expr), "<cmdline>", 0))
goto fail;
} else
if (optind >= argc) {
/* interactive mode */
interactive = 1;
} else {
const char *filename;
filename = argv[optind];
if (eval_file(ctx, filename, module))
goto fail;
}
js_std_loop(ctx);
}
if (dump_memory) {
JSMemoryUsage stats;
JS_ComputeMemoryUsage(rt, &stats);
JS_DumpMemoryUsage(stdout, &stats, rt);
}
js_std_free_handlers(rt);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
if (empty_run && dump_memory) {
clock_t t[5];
double best[5];
int i, j;
for (i = 0; i < 100; i++) {
t[0] = clock();
rt = JS_NewRuntime();
t[1] = clock();
ctx = JS_NewContext(rt);
t[2] = clock();
JS_FreeContext(ctx);
t[3] = clock();
JS_FreeRuntime(rt);
t[4] = clock();
for (j = 4; j > 0; j--) {
double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC;
if (i == 0 || best[j] > ms)
best[j] = ms;
}
}
printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n",
best[1] + best[2] + best[3] + best[4],
best[1], best[2], best[3], best[4]);
}
return 0;
fail:
js_std_free_handlers(rt);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 1;
}

761
src/quickjs/qjsc.c Normal file
View File

@@ -0,0 +1,761 @@
/*
* QuickJS command line compiler
*
* Copyright (c) 2018-2021 Fabrice Bellard
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#if !defined(_WIN32)
#include <sys/wait.h>
#endif
#include "cutils.h"
#include "quickjs-libc.h"
typedef struct {
char *name;
char *short_name;
int flags;
} namelist_entry_t;
typedef struct namelist_t {
namelist_entry_t *array;
int count;
int size;
} namelist_t;
typedef struct {
const char *option_name;
const char *init_name;
} FeatureEntry;
static namelist_t cname_list;
static namelist_t cmodule_list;
static namelist_t init_module_list;
static uint64_t feature_bitmap;
static FILE *outfile;
static BOOL byte_swap;
static BOOL dynamic_export;
static const char *c_ident_prefix = "qjsc_";
#define FE_ALL (-1)
static const FeatureEntry feature_list[] = {
{ "date", "Date" },
{ "eval", "Eval" },
{ "string-normalize", "StringNormalize" },
{ "regexp", "RegExp" },
{ "json", "JSON" },
{ "proxy", "Proxy" },
{ "map", "MapSet" },
{ "typedarray", "TypedArrays" },
{ "promise", "Promise" },
#define FE_MODULE_LOADER 9
{ "module-loader", NULL },
{ "bigint", "BigInt" },
};
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
int flags)
{
namelist_entry_t *e;
if (lp->count == lp->size) {
size_t newsize = lp->size + (lp->size >> 1) + 4;
namelist_entry_t *a =
realloc(lp->array, sizeof(lp->array[0]) * newsize);
/* XXX: check for realloc failure */
lp->array = a;
lp->size = newsize;
}
e = &lp->array[lp->count++];
e->name = strdup(name);
if (short_name)
e->short_name = strdup(short_name);
else
e->short_name = NULL;
e->flags = flags;
}
void namelist_free(namelist_t *lp)
{
while (lp->count > 0) {
namelist_entry_t *e = &lp->array[--lp->count];
free(e->name);
free(e->short_name);
}
free(lp->array);
lp->array = NULL;
lp->size = 0;
}
namelist_entry_t *namelist_find(namelist_t *lp, const char *name)
{
int i;
for(i = 0; i < lp->count; i++) {
namelist_entry_t *e = &lp->array[i];
if (!strcmp(e->name, name))
return e;
}
return NULL;
}
static void get_c_name(char *buf, size_t buf_size, const char *file)
{
const char *p, *r;
size_t len, i;
int c;
char *q;
p = strrchr(file, '/');
if (!p)
p = file;
else
p++;
r = strrchr(p, '.');
if (!r)
len = strlen(p);
else
len = r - p;
pstrcpy(buf, buf_size, c_ident_prefix);
q = buf + strlen(buf);
for(i = 0; i < len; i++) {
c = p[i];
if (!((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z'))) {
c = '_';
}
if ((q - buf) < buf_size - 1)
*q++ = c;
}
*q = '\0';
}
static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
{
size_t i, col;
col = 0;
for(i = 0; i < len; i++) {
fprintf(f, " 0x%02x,", buf[i]);
if (++col == 8) {
fprintf(f, "\n");
col = 0;
}
}
if (col != 0)
fprintf(f, "\n");
}
static void output_object_code(JSContext *ctx,
FILE *fo, JSValueConst obj, const char *c_name,
BOOL load_only)
{
uint8_t *out_buf;
size_t out_buf_len;
int flags;
flags = JS_WRITE_OBJ_BYTECODE;
if (byte_swap)
flags |= JS_WRITE_OBJ_BSWAP;
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
if (!out_buf) {
js_std_dump_error(ctx);
exit(1);
}
namelist_add(&cname_list, c_name, NULL, load_only);
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
c_name, (unsigned int)out_buf_len);
fprintf(fo, "const uint8_t %s[%u] = {\n",
c_name, (unsigned int)out_buf_len);
dump_hex(fo, out_buf, out_buf_len);
fprintf(fo, "};\n\n");
js_free(ctx, out_buf);
}
static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m)
{
/* should never be called when compiling JS code */
abort();
}
static void find_unique_cname(char *cname, size_t cname_size)
{
char cname1[1024];
int suffix_num;
size_t len, max_len;
assert(cname_size >= 32);
/* find a C name not matching an existing module C name by
adding a numeric suffix */
len = strlen(cname);
max_len = cname_size - 16;
if (len > max_len)
cname[max_len] = '\0';
suffix_num = 1;
for(;;) {
snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num);
if (!namelist_find(&cname_list, cname1))
break;
suffix_num++;
}
pstrcpy(cname, cname_size, cname1);
}
JSModuleDef *jsc_module_loader(JSContext *ctx,
const char *module_name, void *opaque)
{
JSModuleDef *m;
namelist_entry_t *e;
/* check if it is a declared C or system module */
e = namelist_find(&cmodule_list, module_name);
if (e) {
/* add in the static init module list */
namelist_add(&init_module_list, e->name, e->short_name, 0);
/* create a dummy module */
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
} else if (has_suffix(module_name, ".so")) {
fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name);
/* create a dummy module */
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
/* the resulting executable will export its symbols for the
dynamic library */
dynamic_export = TRUE;
} else {
size_t buf_len;
uint8_t *buf;
JSValue func_val;
char cname[1024];
buf = js_load_file(ctx, &buf_len, module_name);
if (!buf) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
module_name);
return NULL;
}
/* compile the module */
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
js_free(ctx, buf);
if (JS_IsException(func_val))
return NULL;
get_c_name(cname, sizeof(cname), module_name);
if (namelist_find(&cname_list, cname)) {
find_unique_cname(cname, sizeof(cname));
}
output_object_code(ctx, outfile, func_val, cname, TRUE);
/* the module is already referenced, so we must free it */
m = JS_VALUE_GET_PTR(func_val);
JS_FreeValue(ctx, func_val);
}
return m;
}
static void compile_file(JSContext *ctx, FILE *fo,
const char *filename,
const char *c_name1,
int module)
{
uint8_t *buf;
char c_name[1024];
int eval_flags;
JSValue obj;
size_t buf_len;
buf = js_load_file(ctx, &buf_len, filename);
if (!buf) {
fprintf(stderr, "Could not load '%s'\n", filename);
exit(1);
}
eval_flags = JS_EVAL_FLAG_COMPILE_ONLY;
if (module < 0) {
module = (has_suffix(filename, ".mjs") ||
JS_DetectModule((const char *)buf, buf_len));
}
if (module)
eval_flags |= JS_EVAL_TYPE_MODULE;
else
eval_flags |= JS_EVAL_TYPE_GLOBAL;
obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags);
if (JS_IsException(obj)) {
js_std_dump_error(ctx);
exit(1);
}
js_free(ctx, buf);
if (c_name1) {
pstrcpy(c_name, sizeof(c_name), c_name1);
} else {
get_c_name(c_name, sizeof(c_name), filename);
}
output_object_code(ctx, fo, obj, c_name, FALSE);
JS_FreeValue(ctx, obj);
}
static const char main_c_template1[] =
"int main(int argc, char **argv)\n"
"{\n"
" JSRuntime *rt;\n"
" JSContext *ctx;\n"
" rt = JS_NewRuntime();\n"
" js_std_set_worker_new_context_func(JS_NewCustomContext);\n"
" js_std_init_handlers(rt);\n"
;
static const char main_c_template2[] =
" js_std_loop(ctx);\n"
" js_std_free_handlers(rt);\n"
" JS_FreeContext(ctx);\n"
" JS_FreeRuntime(rt);\n"
" return 0;\n"
"}\n";
#define PROG_NAME "qjsc"
void help(void)
{
printf("QuickJS Compiler version " CONFIG_VERSION "\n"
"usage: " PROG_NAME " [options] [files]\n"
"\n"
"options are:\n"
"-c only output bytecode to a C file\n"
"-e output main() and bytecode to a C file (default = executable output)\n"
"-o output set the output filename\n"
"-N cname set the C name of the generated data\n"
"-m compile as Javascript module (default=autodetect)\n"
"-D module_name compile a dynamically loaded module or worker\n"
"-M module_name[,cname] add initialization code for an external C module\n"
"-x byte swapped output\n"
"-p prefix set the prefix of the generated C names\n"
"-S n set the maximum stack size to 'n' bytes (default=%d)\n",
JS_DEFAULT_STACK_SIZE);
#ifdef CONFIG_LTO
{
int i;
printf("-flto use link time optimization\n");
printf("-fbignum enable bignum extensions\n");
printf("-fno-[");
for(i = 0; i < countof(feature_list); i++) {
if (i != 0)
printf("|");
printf("%s", feature_list[i].option_name);
}
printf("]\n"
" disable selected language features (smaller code size)\n");
}
#endif
exit(1);
}
#if defined(CONFIG_CC) && !defined(_WIN32)
int exec_cmd(char **argv)
{
int pid, status, ret;
pid = fork();
if (pid == 0) {
execvp(argv[0], argv);
exit(1);
}
for(;;) {
ret = waitpid(pid, &status, 0);
if (ret == pid && WIFEXITED(status))
break;
}
return WEXITSTATUS(status);
}
static int output_executable(const char *out_filename, const char *cfilename,
BOOL use_lto, BOOL verbose, const char *exename)
{
const char *argv[64];
const char **arg, *bn_suffix, *lto_suffix;
char libjsname[1024];
char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p;
int ret;
/* get the directory of the executable */
pstrcpy(exe_dir, sizeof(exe_dir), exename);
p = strrchr(exe_dir, '/');
if (p) {
*p = '\0';
} else {
pstrcpy(exe_dir, sizeof(exe_dir), ".");
}
/* if 'quickjs.h' is present at the same path as the executable, we
use it as include and lib directory */
snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir);
if (access(buf, R_OK) == 0) {
pstrcpy(inc_dir, sizeof(inc_dir), exe_dir);
pstrcpy(lib_dir, sizeof(lib_dir), exe_dir);
} else {
snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX);
snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX);
}
lto_suffix = "";
bn_suffix = "";
arg = argv;
*arg++ = CONFIG_CC;
*arg++ = "-O2";
#ifdef CONFIG_LTO
if (use_lto) {
*arg++ = "-flto";
lto_suffix = ".lto";
}
#endif
/* XXX: use the executable path to find the includes files and
libraries */
*arg++ = "-D";
*arg++ = "_GNU_SOURCE";
*arg++ = "-I";
*arg++ = inc_dir;
*arg++ = "-o";
*arg++ = out_filename;
if (dynamic_export)
*arg++ = "-rdynamic";
*arg++ = cfilename;
snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a",
lib_dir, bn_suffix, lto_suffix);
*arg++ = libjsname;
*arg++ = "-lm";
*arg++ = "-ldl";
*arg++ = "-lpthread";
*arg = NULL;
if (verbose) {
for(arg = argv; *arg != NULL; arg++)
printf("%s ", *arg);
printf("\n");
}
ret = exec_cmd((char **)argv);
unlink(cfilename);
return ret;
}
#else
static int output_executable(const char *out_filename, const char *cfilename,
BOOL use_lto, BOOL verbose, const char *exename)
{
fprintf(stderr, "Executable output is not supported for this target\n");
exit(1);
return 0;
}
#endif
typedef enum {
OUTPUT_C,
OUTPUT_C_MAIN,
OUTPUT_EXECUTABLE,
} OutputTypeEnum;
int main(int argc, char **argv)
{
int c, i, verbose;
const char *out_filename, *cname;
char cfilename[1024];
FILE *fo;
JSRuntime *rt;
JSContext *ctx;
BOOL use_lto;
int module;
OutputTypeEnum output_type;
size_t stack_size;
#ifdef CONFIG_BIGNUM
BOOL bignum_ext = FALSE;
#endif
namelist_t dynamic_module_list;
out_filename = NULL;
output_type = OUTPUT_EXECUTABLE;
cname = NULL;
feature_bitmap = FE_ALL;
module = -1;
byte_swap = FALSE;
verbose = 0;
use_lto = FALSE;
stack_size = 0;
memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
/* add system modules */
namelist_add(&cmodule_list, "std", "std", 0);
namelist_add(&cmodule_list, "os", "os", 0);
for(;;) {
c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:");
if (c == -1)
break;
switch(c) {
case 'h':
help();
case 'o':
out_filename = optarg;
break;
case 'c':
output_type = OUTPUT_C;
break;
case 'e':
output_type = OUTPUT_C_MAIN;
break;
case 'N':
cname = optarg;
break;
case 'f':
{
const char *p;
p = optarg;
if (!strcmp(optarg, "lto")) {
use_lto = TRUE;
} else if (strstart(p, "no-", &p)) {
use_lto = TRUE;
for(i = 0; i < countof(feature_list); i++) {
if (!strcmp(p, feature_list[i].option_name)) {
feature_bitmap &= ~((uint64_t)1 << i);
break;
}
}
if (i == countof(feature_list))
goto bad_feature;
} else
#ifdef CONFIG_BIGNUM
if (!strcmp(optarg, "bignum")) {
bignum_ext = TRUE;
} else
#endif
{
bad_feature:
fprintf(stderr, "unsupported feature: %s\n", optarg);
exit(1);
}
}
break;
case 'm':
module = 1;
break;
case 'M':
{
char *p;
char path[1024];
char cname[1024];
pstrcpy(path, sizeof(path), optarg);
p = strchr(path, ',');
if (p) {
*p = '\0';
pstrcpy(cname, sizeof(cname), p + 1);
} else {
get_c_name(cname, sizeof(cname), path);
}
namelist_add(&cmodule_list, path, cname, 0);
}
break;
case 'D':
namelist_add(&dynamic_module_list, optarg, NULL, 0);
break;
case 'x':
byte_swap = TRUE;
break;
case 'v':
verbose++;
break;
case 'p':
c_ident_prefix = optarg;
break;
case 'S':
stack_size = (size_t)strtod(optarg, NULL);
break;
default:
break;
}
}
if (optind >= argc)
help();
if (!out_filename) {
if (output_type == OUTPUT_EXECUTABLE) {
out_filename = "a.out";
} else {
out_filename = "out.c";
}
}
if (output_type == OUTPUT_EXECUTABLE) {
#if defined(_WIN32) || defined(__ANDROID__)
/* XXX: find a /tmp directory ? */
snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid());
#else
snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid());
#endif
} else {
pstrcpy(cfilename, sizeof(cfilename), out_filename);
}
fo = fopen(cfilename, "w");
if (!fo) {
perror(cfilename);
exit(1);
}
outfile = fo;
rt = JS_NewRuntime();
ctx = JS_NewContext(rt);
#ifdef CONFIG_BIGNUM
if (bignum_ext) {
JS_AddIntrinsicBigFloat(ctx);
JS_AddIntrinsicBigDecimal(ctx);
JS_AddIntrinsicOperators(ctx);
JS_EnableBignumExt(ctx, TRUE);
}
#endif
/* loader for ES6 modules */
JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n"
"\n"
);
if (output_type != OUTPUT_C) {
fprintf(fo, "#include \"quickjs-libc.h\"\n"
"\n"
);
} else {
fprintf(fo, "#include <inttypes.h>\n"
"\n"
);
}
for(i = optind; i < argc; i++) {
const char *filename = argv[i];
compile_file(ctx, fo, filename, cname, module);
cname = NULL;
}
for(i = 0; i < dynamic_module_list.count; i++) {
if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) {
fprintf(stderr, "Could not load dynamic module '%s'\n",
dynamic_module_list.array[i].name);
exit(1);
}
}
if (output_type != OUTPUT_C) {
fprintf(fo,
"static JSContext *JS_NewCustomContext(JSRuntime *rt)\n"
"{\n"
" JSContext *ctx = JS_NewContextRaw(rt);\n"
" if (!ctx)\n"
" return NULL;\n");
/* add the basic objects */
fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n");
for(i = 0; i < countof(feature_list); i++) {
if ((feature_bitmap & ((uint64_t)1 << i)) &&
feature_list[i].init_name) {
fprintf(fo, " JS_AddIntrinsic%s(ctx);\n",
feature_list[i].init_name);
}
}
#ifdef CONFIG_BIGNUM
if (bignum_ext) {
fprintf(fo,
" JS_AddIntrinsicBigFloat(ctx);\n"
" JS_AddIntrinsicBigDecimal(ctx);\n"
" JS_AddIntrinsicOperators(ctx);\n"
" JS_EnableBignumExt(ctx, 1);\n");
}
#endif
/* add the precompiled modules (XXX: could modify the module
loader instead) */
for(i = 0; i < init_module_list.count; i++) {
namelist_entry_t *e = &init_module_list.array[i];
/* initialize the static C modules */
fprintf(fo,
" {\n"
" extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
" js_init_module_%s(ctx, \"%s\");\n"
" }\n",
e->short_name, e->short_name, e->name);
}
for(i = 0; i < cname_list.count; i++) {
namelist_entry_t *e = &cname_list.array[i];
if (e->flags) {
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n",
e->name, e->name);
}
}
fprintf(fo,
" return ctx;\n"
"}\n\n");
fputs(main_c_template1, fo);
if (stack_size != 0) {
fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
(unsigned int)stack_size);
}
/* add the module loader if necessary */
if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
}
fprintf(fo,
" ctx = JS_NewCustomContext(rt);\n"
" js_std_add_helpers(ctx, argc, argv);\n");
for(i = 0; i < cname_list.count; i++) {
namelist_entry_t *e = &cname_list.array[i];
if (!e->flags) {
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n",
e->name, e->name);
}
}
fputs(main_c_template2, fo);
}
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
fclose(fo);
if (output_type == OUTPUT_EXECUTABLE) {
return output_executable(out_filename, cfilename, use_lto, verbose,
argv[0]);
}
namelist_free(&cname_list);
namelist_free(&cmodule_list);
namelist_free(&init_module_list);
return 0;
}

87
src/quickjs/qsort_r.c Normal file
View File

@@ -0,0 +1,87 @@
#include <sys/types.h>
#include <stdlib.h>
static void
exch(char* base, size_t size, size_t a, size_t b) {
char* x = base + a * size;
char* y = base + b * size;
while(size) {
char z = *x;
*x = *y;
*y = z;
--size;
++x;
++y;
}
}
#define RAND
/* Quicksort with 3-way partitioning, ala Sedgewick */
/* Blame him for the scary variable names */
/* http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf */
static void
quicksort(char* base, size_t size, ssize_t l, ssize_t r, int (*compar)(const void*, const void*, void*), void* ptr) {
ssize_t i = l - 1, j = r, p = l - 1, q = r, k;
char* v = base + r * size;
if(r <= l)
return;
#ifdef RAND
/*
We chose the rightmost element in the array to be sorted as pivot,
which is OK if the data is random, but which is horrible if the
data is already sorted. Try to improve by exchanging it with a
random other pivot.
*/
exch(base, size, l + (rand() % (r - l)), r);
#elif defined MID
/*
We chose the rightmost element in the array to be sorted as pivot,
which is OK if the data is random, but which is horrible if the
data is already sorted. Try to improve by chosing the middle
element instead.
*/
exch(base, size, l + (r - l) / 2, r);
#endif
for(;;) {
while(++i != r && compar(base + i * size, v, ptr) < 0)
;
while(compar(v, base + (--j) * size, ptr) < 0)
if(j == l)
break;
if(i >= j)
break;
exch(base, size, i, j);
if(compar(base + i * size, v, ptr) == 0)
exch(base, size, ++p, i);
if(compar(v, base + j * size, ptr) == 0)
exch(base, size, j, --q);
}
exch(base, size, i, r);
j = i - 1;
++i;
for(k = l; k < p; k++, j--)
exch(base, size, k, j);
for(k = r - 1; k > q; k--, i++)
exch(base, size, i, k);
quicksort(base, size, l, j, compar, ptr);
quicksort(base, size, i, r, compar, ptr);
}
void
quicksort_r(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* ptr) {
/* check for integer overflows */
if(nmemb >= (((size_t)-1) >> 1) || size >= (((size_t)-1) >> 1))
return;
#if 0
if (sizeof(size_t) < sizeof(unsigned long long)) {
if ((unsigned long long)size * nmemb > (size_t)-1) return;
} else {
if (size*nmemb/nmemb != size) return;
}
#endif
if(nmemb > 1)
quicksort(base, size, 0, nmemb - 1, compar, ptr);
}

273
src/quickjs/quickjs-atom.h Normal file
View File

@@ -0,0 +1,273 @@
/*
* QuickJS atom definitions
*
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
* 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.
*/
#ifdef DEF
/* Note: first atoms are considered as keywords in the parser */
DEF(null, "null") /* must be first */
DEF(false, "false")
DEF(true, "true")
DEF(if, "if")
DEF(else, "else")
DEF(return, "return")
DEF(var, "var")
DEF(this, "this")
DEF(delete, "delete")
DEF(void, "void")
DEF(typeof, "typeof")
DEF(new, "new")
DEF(in, "in")
DEF(instanceof, "instanceof")
DEF(do, "do")
DEF(while, "while")
DEF(for, "for")
DEF(break, "break")
DEF(continue, "continue")
DEF(switch, "switch")
DEF(case, "case")
DEF(default, "default")
DEF(throw, "throw")
DEF(try, "try")
DEF(catch, "catch")
DEF(finally, "finally")
DEF(function, "function")
DEF(debugger, "debugger")
DEF(with, "with")
/* FutureReservedWord */
DEF(class, "class")
DEF(const, "const")
DEF(enum, "enum")
DEF(export, "export")
DEF(extends, "extends")
DEF(import, "import")
DEF(super, "super")
/* FutureReservedWords when parsing strict mode code */
DEF(implements, "implements")
DEF(interface, "interface")
DEF(let, "let")
DEF(package, "package")
DEF(private, "private")
DEF(protected, "protected")
DEF(public, "public")
DEF(static, "static")
DEF(yield, "yield")
DEF(await, "await")
/* empty string */
DEF(empty_string, "")
/* identifiers */
DEF(length, "length")
DEF(fileName, "fileName")
DEF(lineNumber, "lineNumber")
DEF(message, "message")
DEF(cause, "cause")
DEF(errors, "errors")
DEF(stack, "stack")
DEF(name, "name")
DEF(toString, "toString")
DEF(toLocaleString, "toLocaleString")
DEF(valueOf, "valueOf")
DEF(eval, "eval")
DEF(prototype, "prototype")
DEF(constructor, "constructor")
DEF(configurable, "configurable")
DEF(writable, "writable")
DEF(enumerable, "enumerable")
DEF(value, "value")
DEF(get, "get")
DEF(set, "set")
DEF(of, "of")
DEF(__proto__, "__proto__")
DEF(undefined, "undefined")
DEF(number, "number")
DEF(boolean, "boolean")
DEF(string, "string")
DEF(object, "object")
DEF(symbol, "symbol")
DEF(integer, "integer")
DEF(unknown, "unknown")
DEF(arguments, "arguments")
DEF(callee, "callee")
DEF(caller, "caller")
DEF(_eval_, "<eval>")
DEF(_ret_, "<ret>")
DEF(_var_, "<var>")
DEF(_arg_var_, "<arg_var>")
DEF(_with_, "<with>")
DEF(lastIndex, "lastIndex")
DEF(target, "target")
DEF(index, "index")
DEF(input, "input")
DEF(defineProperties, "defineProperties")
DEF(apply, "apply")
DEF(join, "join")
DEF(concat, "concat")
DEF(split, "split")
DEF(construct, "construct")
DEF(getPrototypeOf, "getPrototypeOf")
DEF(setPrototypeOf, "setPrototypeOf")
DEF(isExtensible, "isExtensible")
DEF(preventExtensions, "preventExtensions")
DEF(has, "has")
DEF(deleteProperty, "deleteProperty")
DEF(defineProperty, "defineProperty")
DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor")
DEF(ownKeys, "ownKeys")
DEF(add, "add")
DEF(done, "done")
DEF(next, "next")
DEF(values, "values")
DEF(source, "source")
DEF(flags, "flags")
DEF(global, "global")
DEF(unicode, "unicode")
DEF(raw, "raw")
DEF(new_target, "new.target")
DEF(this_active_func, "this.active_func")
DEF(home_object, "<home_object>")
DEF(computed_field, "<computed_field>")
DEF(static_computed_field, "<static_computed_field>") /* must come after computed_fields */
DEF(class_fields_init, "<class_fields_init>")
DEF(brand, "<brand>")
DEF(hash_constructor, "#constructor")
DEF(as, "as")
DEF(from, "from")
DEF(meta, "meta")
DEF(_default_, "*default*")
DEF(_star_, "*")
DEF(Module, "Module")
DEF(then, "then")
DEF(resolve, "resolve")
DEF(reject, "reject")
DEF(promise, "promise")
DEF(proxy, "proxy")
DEF(revoke, "revoke")
DEF(async, "async")
DEF(exec, "exec")
DEF(groups, "groups")
DEF(indices, "indices")
DEF(status, "status")
DEF(reason, "reason")
DEF(globalThis, "globalThis")
DEF(bigint, "bigint")
#ifdef CONFIG_BIGNUM
DEF(bigfloat, "bigfloat")
DEF(bigdecimal, "bigdecimal")
DEF(roundingMode, "roundingMode")
DEF(maximumSignificantDigits, "maximumSignificantDigits")
DEF(maximumFractionDigits, "maximumFractionDigits")
#endif
/* the following 3 atoms are only used with CONFIG_ATOMICS */
DEF(not_equal, "not-equal")
DEF(timed_out, "timed-out")
DEF(ok, "ok")
/* */
DEF(toJSON, "toJSON")
/* class names */
DEF(Object, "Object")
DEF(Array, "Array")
DEF(Error, "Error")
DEF(Number, "Number")
DEF(String, "String")
DEF(Boolean, "Boolean")
DEF(Symbol, "Symbol")
DEF(Arguments, "Arguments")
DEF(Math, "Math")
DEF(JSON, "JSON")
DEF(Date, "Date")
DEF(Function, "Function")
DEF(GeneratorFunction, "GeneratorFunction")
DEF(ForInIterator, "ForInIterator")
DEF(RegExp, "RegExp")
DEF(ArrayBuffer, "ArrayBuffer")
DEF(SharedArrayBuffer, "SharedArrayBuffer")
/* must keep same order as class IDs for typed arrays */
DEF(Uint8ClampedArray, "Uint8ClampedArray")
DEF(Int8Array, "Int8Array")
DEF(Uint8Array, "Uint8Array")
DEF(Int16Array, "Int16Array")
DEF(Uint16Array, "Uint16Array")
DEF(Int32Array, "Int32Array")
DEF(Uint32Array, "Uint32Array")
DEF(BigInt64Array, "BigInt64Array")
DEF(BigUint64Array, "BigUint64Array")
DEF(Float32Array, "Float32Array")
DEF(Float64Array, "Float64Array")
DEF(DataView, "DataView")
DEF(BigInt, "BigInt")
#ifdef CONFIG_BIGNUM
DEF(BigFloat, "BigFloat")
DEF(BigFloatEnv, "BigFloatEnv")
DEF(BigDecimal, "BigDecimal")
DEF(OperatorSet, "OperatorSet")
DEF(Operators, "Operators")
#endif
DEF(Map, "Map")
DEF(Set, "Set") /* Map + 1 */
DEF(WeakMap, "WeakMap") /* Map + 2 */
DEF(WeakSet, "WeakSet") /* Map + 3 */
DEF(Map_Iterator, "Map Iterator")
DEF(Set_Iterator, "Set Iterator")
DEF(Array_Iterator, "Array Iterator")
DEF(String_Iterator, "String Iterator")
DEF(RegExp_String_Iterator, "RegExp String Iterator")
DEF(Generator, "Generator")
DEF(Proxy, "Proxy")
DEF(Promise, "Promise")
DEF(PromiseResolveFunction, "PromiseResolveFunction")
DEF(PromiseRejectFunction, "PromiseRejectFunction")
DEF(AsyncFunction, "AsyncFunction")
DEF(AsyncFunctionResolve, "AsyncFunctionResolve")
DEF(AsyncFunctionReject, "AsyncFunctionReject")
DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction")
DEF(AsyncGenerator, "AsyncGenerator")
DEF(EvalError, "EvalError")
DEF(RangeError, "RangeError")
DEF(ReferenceError, "ReferenceError")
DEF(SyntaxError, "SyntaxError")
DEF(TypeError, "TypeError")
DEF(URIError, "URIError")
DEF(InternalError, "InternalError")
/* private symbols */
DEF(Private_brand, "<brand>")
/* symbols */
DEF(Symbol_toPrimitive, "Symbol.toPrimitive")
DEF(Symbol_iterator, "Symbol.iterator")
DEF(Symbol_match, "Symbol.match")
DEF(Symbol_matchAll, "Symbol.matchAll")
DEF(Symbol_replace, "Symbol.replace")
DEF(Symbol_search, "Symbol.search")
DEF(Symbol_split, "Symbol.split")
DEF(Symbol_toStringTag, "Symbol.toStringTag")
DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable")
DEF(Symbol_hasInstance, "Symbol.hasInstance")
DEF(Symbol_species, "Symbol.species")
DEF(Symbol_unscopables, "Symbol.unscopables")
DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
#ifdef CONFIG_BIGNUM
DEF(Symbol_operatorSet, "Symbol.operatorSet")
#endif
#endif /* DEF */

Some files were not shown because too many files have changed in this diff Show More