diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08481b1..0a5497d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,11 +7,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive - - name: Install llvm 16 - run: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 && wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 16 + - name: Install llvm 18 + run: | + sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 18 + rm llvm.sh - name: Build run: make all - name: Install tools @@ -20,15 +25,15 @@ jobs: run: make test - name: Benchmark run: make benchmark - + macos: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive - name: Install LLVM and Clang - run: brew install llvm@16 + run: brew install llvm@18 - name: Build - run: export PATH="/usr/local/opt/llvm@16/bin:$PATH" && make all + run: export PATH="/opt/homebrew/opt/llvm/bin:$PATH" && make all diff --git a/.gitmodules b/.gitmodules index b354962..ceb7ba4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,10 @@ - [submodule "deps/ckb-c-stdlib"] path = deps/ckb-c-stdlib url = https://github.com/nervosnetwork/ckb-c-stdlib.git [submodule "deps/compiler-rt-builtins-riscv"] path = deps/compiler-rt-builtins-riscv - url = https://github.com/nervosnetwork/compiler-rt-builtins-riscv.git + url = https://github.com/nervosnetwork/compiler-rt-builtins-riscv + branch = update +[submodule "deps/musl"] + path = deps/musl + url = https://github.com/xxuejie/musl diff --git a/Makefile b/Makefile index a21ce11..419db0e 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,14 @@ - -CC := clang-16 -LD := ld.lld-16 -OBJCOPY := llvm-objcopy-16 -AR := llvm-ar-16 -RANLIB := llvm-ranlib-16 +CC := clang-18 +LD := ld.lld-18 +AR := llvm-ar-18 +OBJCOPY := llvm-objcopy-18 +RANLIB := llvm-ranlib-18 UNAME := $(shell uname) ifeq ($(UNAME), Darwin) + CC := clang LD := ld.lld + AR := llvm-ar OBJCOPY := llvm-objcopy RANLIB := llvm-ranlib endif @@ -15,27 +16,31 @@ endif CFLAGS := --target=riscv64 -march=rv64imc_zba_zbb_zbc_zbs CFLAGS += -g -Os \ -Wall -Werror -Wno-nonnull -Wno-unused-function \ - -fno-builtin-printf -fno-builtin-memcmp \ - -nostdinc -nostdlib\ + -nostdinc -nostdlib \ -fdata-sections -ffunction-sections -CFLAGS += -I deps/ckb-c-stdlib/libc -I deps/ckb-c-stdlib +CFLAGS += -I deps/ckb-c-stdlib CFLAGS += -I include -I include/c-stdlib CFLAGS += -I deps/compiler-rt-builtins-riscv/compiler-rt/lib/builtins -CFLAGS += -Wextra -Wno-sign-compare -Wno-missing-field-initializers -Wundef -Wuninitialized\ --Wunused -Wno-unused-parameter -Wchar-subscripts -funsigned-char -Wno-unused-function \ --DCONFIG_VERSION=\"2021-03-27-CKB\" +CFLAGS += -Wextra -Wno-sign-compare -Wno-missing-field-initializers -Wundef -Wuninitialized \ + -Wunused -Wno-unused-parameter -Wchar-subscripts -funsigned-char -Wno-unused-function \ + -DCONFIG_VERSION=\"2021-03-27-CKB\" CFLAGS += -Wno-incompatible-library-redeclaration -Wno-implicit-const-int-float-conversion -Wno-invalid-noreturn CFLAGS += -DCKB_DECLARATION_ONLY CFLAGS += -D__BYTE_ORDER=1234 -D__LITTLE_ENDIAN=1234 -D__ISO_C_VISIBLE=1999 -D__GNU_VISIBLE -CFLAGS += -DCKB_MALLOC_DECLARATION_ONLY -DCKB_PRINTF_DECLARATION_ONLY -DCONFIG_BIGNUM -DCONFIG_STACK_CHECK +CFLAGS += -DCKB_MALLOC_DECLARATION_ONLY -DCKB_PRINTF_DECLARATION_ONLY -DCONFIG_BIGNUM -DCONFIG_STACK_CHECK +CFLAGS += -isystem deps/musl/release/include # uncomment to dump memory usage # CFLAGS += -DMEMORY_USAGE -LDFLAGS := -static --gc-sections +LDFLAGS := -static --gc-sections -nostdlib LDFLAGS += -Ldeps/compiler-rt-builtins-riscv/build -lcompiler-rt +LDFLAGS += --sysroot deps/musl/release -Ldeps/musl/release/lib -lc -lgcc +LDFLAGS += -wrap=gettimeofday +LDFLAGS += -wrap=fesetround +LDFLAGS += -wrap=localtime_r OBJDIR=build @@ -43,17 +48,16 @@ QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/lib $(OBJDIR)/cutils.o $(OBJDIR)/mocked.o $(OBJDIR)/std_module.o $(OBJDIR)/ckb_module.o $(OBJDIR)/ckb_cell_fs.o \ $(OBJDIR)/libbf.o $(OBJDIR)/cmdopt.o -STD_OBJS=$(OBJDIR)/string_impl.o $(OBJDIR)/malloc_impl.o $(OBJDIR)/math_impl.o \ - $(OBJDIR)/math_log_impl.o $(OBJDIR)/math_pow_impl.o $(OBJDIR)/printf_impl.o $(OBJDIR)/stdio_impl.o \ - $(OBJDIR)/locale_impl.o - - -all: build/ckb-js-vm +all: deps/musl/release build/ckb-js-vm deps/compiler-rt-builtins-riscv/build/libcompiler-rt.a: cd deps/compiler-rt-builtins-riscv && make -build/ckb-js-vm: $(STD_OBJS) $(QJS_OBJS) $(OBJDIR)/impl.o deps/compiler-rt-builtins-riscv/build/libcompiler-rt.a +deps/musl/release: + cd deps/musl && \ + CLANG=$(CC) ./ckb/build.sh + +build/ckb-js-vm: $(QJS_OBJS) deps/compiler-rt-builtins-riscv/build/libcompiler-rt.a $(LD) $(LDFLAGS) -o $@ $^ cp $@ $@.debug $(OBJCOPY) --strip-debug --strip-all $@ @@ -63,18 +67,10 @@ $(OBJDIR)/%.o: quickjs/%.c @echo build $< @$(CC) $(CFLAGS) -c -o $@ $< -$(OBJDIR)/%.o: include/c-stdlib/src/%.c - @echo build $< - @$(CC) $(CFLAGS) -c -o $@ $< - $(OBJDIR)/%.o: include/%.c @echo build $< @$(CC) $(CFLAGS) -c -o $@ $< -$(OBJDIR)/impl.o: deps/ckb-c-stdlib/libc/src/impl.c - @echo build $< - @$(CC) $(filter-out -DCKB_DECLARATION_ONLY, $(CFLAGS)) -c -o $@ $< - test: make -f tests/examples/Makefile make -f tests/basic/Makefile @@ -91,7 +87,7 @@ clean: make -C deps/compiler-rt-builtins-riscv clean install: - wget 'https://github.com/nervosnetwork/ckb-standalone-debugger/releases/download/v0.111.0/ckb-debugger-linux-x64.tar.gz' + wget 'https://github.com/nervosnetwork/ckb-standalone-debugger/releases/download/v0.118.0-rc2/ckb-debugger-linux-x64.tar.gz' tar zxvf ckb-debugger-linux-x64.tar.gz mv ckb-debugger ~/.cargo/bin/ckb-debugger make -f tests/ckb_js_tests/Makefile install-lua diff --git a/README.md b/README.md index 834cce6..91b2c79 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ adapting [quickjs](https://bellard.org/quickjs/). ## Build -The clang version 16 is required. +The clang version 18 is required. ```shell git submodule update --init diff --git a/deps/ckb-c-stdlib b/deps/ckb-c-stdlib index bdc87e0..be84dcf 160000 --- a/deps/ckb-c-stdlib +++ b/deps/ckb-c-stdlib @@ -1 +1 @@ -Subproject commit bdc87e064b98a40df7ccc0abc23cd3d60b7da475 +Subproject commit be84dcf385ddc2ab52b2650fb959e3769dc75093 diff --git a/deps/compiler-rt-builtins-riscv b/deps/compiler-rt-builtins-riscv index 5dc696f..906cb9d 160000 --- a/deps/compiler-rt-builtins-riscv +++ b/deps/compiler-rt-builtins-riscv @@ -1 +1 @@ -Subproject commit 5dc696f2ace0da6789dbb4b5c33a9cb46f1e7ca2 +Subproject commit 906cb9d8c777b61d61620c1d62a4e3d9623c0946 diff --git a/deps/musl b/deps/musl new file mode 160000 index 0000000..f122fb1 --- /dev/null +++ b/deps/musl @@ -0,0 +1 @@ +Subproject commit f122fb1d2743e73ad777f3dca027717738b2d3f3 diff --git a/include/Makefile b/include/Makefile index bfb43c4..da1adc4 100644 --- a/include/Makefile +++ b/include/Makefile @@ -1,10 +1,7 @@ - STYLE := "{BasedOnStyle: Google, TabWidth: 4, IndentWidth: 4, UseTab: Never, SortIncludes: false, ColumnLimit: 120}" - fmt: - clang-format -i -style=$(STYLE) *.c *.h - clang-format -i -style=$(STYLE) c-stdlib/*.h - clang-format -i -style=$(STYLE) c-stdlib/src/*.c - clang-format -i -style=$(STYLE) ../quickjs/qjs.c ../quickjs/std_module.c ../quickjs/std_module.h ../quickjs/ckb_module.c ../quickjs/ckb_module.h - \ No newline at end of file + clang-format-18 -i -style=$(STYLE) *.c *.h + clang-format-18 -i -style=$(STYLE) c-stdlib/*.h + clang-format-18 -i -style=$(STYLE) c-stdlib/src/*.c + clang-format-18 -i -style=$(STYLE) ../quickjs/qjs.c ../quickjs/std_module.c ../quickjs/std_module.h ../quickjs/ckb_module.c ../quickjs/ckb_module.h diff --git a/include/c-stdlib/README.md b/include/c-stdlib/README.md deleted file mode 100644 index 49bd744..0000000 --- a/include/c-stdlib/README.md +++ /dev/null @@ -1 +0,0 @@ -They're from C standard library but not suitable to be included in ckb-c-stdlib. diff --git a/include/c-stdlib/my_assert.h b/include/c-stdlib/my_assert.h deleted file mode 100644 index 3d24118..0000000 --- a/include/c-stdlib/my_assert.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef C_STDLIB_ASSERT_H_ -#define C_STDLIB_ASSERT_H_ - -int ckb_exit(signed char); - -#define assert(s) \ - do { \ - if (!(s)) { \ - printf("Failed at %s:%d: %s\n", __FILE__, __LINE__, (#s)); \ - ckb_exit(-1); \ - } \ - } while (0) - -#endif // C_STDLIB_ASSERT_H_ diff --git a/include/c-stdlib/my_ctype.h b/include/c-stdlib/my_ctype.h deleted file mode 100644 index a6150a2..0000000 --- a/include/c-stdlib/my_ctype.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _STDLIB_CTYPE_H_ -#define _STDLIB_CTYPE_H_ -#ifdef __cplusplus -extern "C" { -#endif - -int islower(int); -int isupper(int); - -int tolower(int); -int toupper(int); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/c-stdlib/my_errno.h b/include/c-stdlib/my_errno.h deleted file mode 100644 index 043b9e4..0000000 --- a/include/c-stdlib/my_errno.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _STDLIB_ERRNO_H_ -#define _STDLIB_ERRNO_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __GNUC__ -__attribute__((const)) -#endif -int *__errno_location(void); -#define errno (*__errno_location()) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/c-stdlib/my_features.h b/include/c-stdlib/my_features.h deleted file mode 100644 index a0d92fd..0000000 --- a/include/c-stdlib/my_features.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _FEATURES_H -#define _FEATURES_H - -#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) -#define _BSD_SOURCE 1 -#endif - -#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) && \ - !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) -#define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 700 -#endif - -#if __STDC_VERSION__ >= 199901L -#define __restrict restrict -#elif !defined(__GNUC__) -#define __restrict -#endif - -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -#define __inline inline -#elif !defined(__GNUC__) -#define __inline -#endif - -#if __STDC_VERSION__ >= 201112L -#elif defined(__GNUC__) -#define _Noreturn __attribute__((__noreturn__)) -#else -#define _Noreturn -#endif - -#define __REDIR(x, y) __typeof__(x) x __asm__(#y) - -#endif diff --git a/include/c-stdlib/my_float.h b/include/c-stdlib/my_float.h deleted file mode 100644 index e508a5c..0000000 --- a/include/c-stdlib/my_float.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef _STDLIB_FLOAT_H_ -#define _STDLIB_FLOAT_H_ - -#include - -#undef FLT_MAX -#undef DBL_MAX -#undef LDBL_MAX -#define FLT_MAX __FLT_MAX__ -#define DBL_MAX __DBL_MAX__ -#define LDBL_MAX __LDBL_MAX__ - -typedef union { - double value; - struct { - uint32_t lsw; - uint32_t msw; - } parts; - struct { - uint64_t w; - } xparts; -} ieee_double_shape_type; - -/* Get two 32 bit ints from a double. */ - -#define EXTRACT_WORDS(ix0, ix1, d) \ - do { \ - ieee_double_shape_type ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ - } while (0) - -/* Get the more significant 32 bit int from a double. */ - -#define GET_HIGH_WORD(i, d) \ - do { \ - ieee_double_shape_type gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ - } while (0) - -/* Get the less significant 32 bit int from a double. */ - -#define GET_LOW_WORD(i, d) \ - do { \ - ieee_double_shape_type gl_u; \ - gl_u.value = (d); \ - (i) = gl_u.parts.lsw; \ - } while (0) - -/* Set the more significant 32 bits of a double from an int. */ - -#define SET_HIGH_WORD(d, v) \ - do { \ - ieee_double_shape_type sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ - } while (0) - -/* Set the less significant 32 bits of a double from an int. */ - -#define SET_LOW_WORD(d, v) \ - do { \ - ieee_double_shape_type sl_u; \ - sl_u.value = (d); \ - sl_u.parts.lsw = (v); \ - (d) = sl_u.value; \ - } while (0) - -static const double ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ - ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ - two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ - twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ - huge = 1.0e+300, tiny = 1.0e-300, Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ - Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ - Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ - Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ - Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ - Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ - Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -static const double zero = 0.0; - -static const double bp[] = - { - 1.0, - 1.5, -}, - dp_h[] = - { - 0.0, - 5.84962487220764160156e-01, -}, /* 0x3FE2B803, 0x40000000 */ - dp_l[] = - { - 0.0, - 1.35003920212974897128e-08, -}, /* 0x3E4CFDEB, 0x43CFD006 */ - one = 1.0, two = 2.0, two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ - /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ - L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ - L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ - L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ - L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ - L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ - L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ - P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ - P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ - P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ - P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ - P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ - lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ - lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ - lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ - ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ - cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ - cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ - cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ - ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ - ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ - ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ - -#endif diff --git a/include/c-stdlib/my_inttypes.h b/include/c-stdlib/my_inttypes.h deleted file mode 100644 index 27df674..0000000 --- a/include/c-stdlib/my_inttypes.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef _MY_INTTYPES_H_ -#define _MY_INTTYPES_H_ - -#include -#include "my_stdint.h" - -#if UINTPTR_MAX == UINT64_MAX -#define __PRI64 "l" -#define __PRIPTR "l" -#else -#define __PRI64 "ll" -#define __PRIPTR "" -#endif - -#define PRId8 "d" -#define PRId16 "d" -#define PRId32 "d" -#define PRId64 __PRI64 "d" - -#define PRIdLEAST8 "d" -#define PRIdLEAST16 "d" -#define PRIdLEAST32 "d" -#define PRIdLEAST64 __PRI64 "d" - -#define PRIdFAST8 "d" -#define PRIdFAST16 "d" -#define PRIdFAST32 "d" -#define PRIdFAST64 __PRI64 "d" - -#define PRIi8 "i" -#define PRIi16 "i" -#define PRIi32 "i" -#define PRIi64 __PRI64 "i" - -#define PRIiLEAST8 "i" -#define PRIiLEAST16 "i" -#define PRIiLEAST32 "i" -#define PRIiLEAST64 __PRI64 "i" - -#define PRIiFAST8 "i" -#define PRIiFAST16 "i" -#define PRIiFAST32 "i" -#define PRIiFAST64 __PRI64 "i" - -#define PRIo8 "o" -#define PRIo16 "o" -#define PRIo32 "o" -#define PRIo64 __PRI64 "o" - -#define PRIoLEAST8 "o" -#define PRIoLEAST16 "o" -#define PRIoLEAST32 "o" -#define PRIoLEAST64 __PRI64 "o" - -#define PRIoFAST8 "o" -#define PRIoFAST16 "o" -#define PRIoFAST32 "o" -#define PRIoFAST64 __PRI64 "o" - -#define PRIu8 "u" -#define PRIu16 "u" -#define PRIu32 "u" -#define PRIu64 __PRI64 "u" - -#define PRIuLEAST8 "u" -#define PRIuLEAST16 "u" -#define PRIuLEAST32 "u" -#define PRIuLEAST64 __PRI64 "u" - -#define PRIuFAST8 "u" -#define PRIuFAST16 "u" -#define PRIuFAST32 "u" -#define PRIuFAST64 __PRI64 "u" - -#define PRIx8 "x" -#define PRIx16 "x" -#define PRIx32 "x" -#define PRIx64 __PRI64 "x" - -#define PRIxLEAST8 "x" -#define PRIxLEAST16 "x" -#define PRIxLEAST32 "x" -#define PRIxLEAST64 __PRI64 "x" - -#define PRIxFAST8 "x" -#define PRIxFAST16 "x" -#define PRIxFAST32 "x" -#define PRIxFAST64 __PRI64 "x" - -#define PRIX8 "X" -#define PRIX16 "X" -#define PRIX32 "X" -#define PRIX64 __PRI64 "X" - -#define PRIXLEAST8 "X" -#define PRIXLEAST16 "X" -#define PRIXLEAST32 "X" -#define PRIXLEAST64 __PRI64 "X" - -#define PRIXFAST8 "X" -#define PRIXFAST16 "X" -#define PRIXFAST32 "X" -#define PRIXFAST64 __PRI64 "X" - -#define PRIdMAX __PRI64 "d" -#define PRIiMAX __PRI64 "i" -#define PRIoMAX __PRI64 "o" -#define PRIuMAX __PRI64 "u" -#define PRIxMAX __PRI64 "x" -#define PRIXMAX __PRI64 "X" - -#endif diff --git a/include/c-stdlib/my_locale.h b/include/c-stdlib/my_locale.h deleted file mode 100644 index 6b9848f..0000000 --- a/include/c-stdlib/my_locale.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _STDLIB_LOCALE_H_ -#define _STDLIB_LOCALE_H_ -#ifdef __cplusplus -extern "C" { -#endif - -struct lconv { - char *decimal_point; - char *thousands_sep; - char *grouping; - - char *int_curr_symbol; - char *currency_symbol; - char *mon_decimal_point; - char *mon_thousands_sep; - char *mon_grouping; - char *positive_sign; - char *negative_sign; - char int_frac_digits; - char frac_digits; - char p_cs_precedes; - char p_sep_by_space; - char n_cs_precedes; - char n_sep_by_space; - char p_sign_posn; - char n_sign_posn; - char int_p_cs_precedes; - char int_p_sep_by_space; - char int_n_cs_precedes; - char int_n_sep_by_space; - char int_p_sign_posn; - char int_n_sign_posn; -}; - -struct lconv *localeconv(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/c-stdlib/my_malloc.h b/include/c-stdlib/my_malloc.h deleted file mode 100644 index 583e383..0000000 --- a/include/c-stdlib/my_malloc.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _STDLIB_MALLOC_H_ -#define _STDLIB_MALLOC_H_ - -#include - -size_t malloc_usable_size(void *ptr); -void malloc_config(uintptr_t min, uintptr_t max); -size_t malloc_usage(); - -#endif // _STDLIB_MALLOC_H_ diff --git a/include/c-stdlib/my_math.h b/include/c-stdlib/my_math.h deleted file mode 100644 index 40466fc..0000000 --- a/include/c-stdlib/my_math.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifdef __cplusplus -extern "C" { -#endif - -#define NAN (__builtin_nanf("")) -#define INFINITY (__builtin_inff()) - -/* fp_force_eval ensures that the input value is computed when that's - otherwise unused. To prevent the constant folding of the input - expression, an additional fp_barrier may be needed or a compilation - mode that does so (e.g. -frounding-math in gcc). Then it can be - used to evaluate an expression for its fenv side-effects only. */ - -#ifndef fp_force_evalf -#define fp_force_evalf fp_force_evalf -static inline void fp_force_evalf(float x) { - volatile float y; - y = x; - (void)y; -} -#endif - -#ifndef fp_force_eval -#define fp_force_eval fp_force_eval -static inline void fp_force_eval(double x) { - volatile double y; - y = x; - (void)y; -} -#endif - -#ifndef fp_force_evall -#define fp_force_evall fp_force_evall -static inline void fp_force_evall(long double x) { - volatile long double y; - y = x; - (void)y; -} -#endif - -#define FORCE_EVAL(x) \ - do { \ - if (sizeof(x) == sizeof(float)) { \ - fp_force_evalf(x); \ - } else if (sizeof(x) == sizeof(double)) { \ - fp_force_eval(x); \ - } else { \ - fp_force_evall(x); \ - } \ - } while (0) - -double acos(double); - -double asin(double); - -double atan2(double, double); - -double cos(double); - -double cosh(double); - -double exp(double); - -double fabs(double); - -double log(double); - -double log2(double); - -double log10(double); - -double pow(double, double); - -double sin(double); - -double sinh(double); - -double sqrt(double); - -double tan(double); - -double tanh(double); - -double scalbn(double, int); - -double ldexp(double, int); - -double round(double x); -int isnan(double x); -int isfinite(double x); -double trunc(double x); -long int lrint(double x); -double floor(double x); -double cbrt(double x); -double fmod(double numer, double denom); -double fmin(double x, double y); -double fmax(double x, double y); -double hypot(double x, double y); -int signbit(double num); - -double ceil(double x); - -#ifdef __cplusplus -} -#endif diff --git a/include/c-stdlib/my_setjmp.h b/include/c-stdlib/my_setjmp.h deleted file mode 100644 index 666c35d..0000000 --- a/include/c-stdlib/my_setjmp.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _STDLIB_SETJMP_H_ -#define _STDLIB_SETJMP_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// #include - -typedef unsigned long __jmp_buf[26]; - -typedef struct __jmp_buf_tag { - __jmp_buf __jb; - unsigned long __fl; - unsigned long __ss[128 / sizeof(long)]; -} jmp_buf[1]; - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) -#define __setjmp_attr __attribute__((__returns_twice__)) -#else -#define __setjmp_attr -#endif - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || \ - defined(_BSD_SOURCE) -typedef jmp_buf sigjmp_buf; -int sigsetjmp(sigjmp_buf, int) __setjmp_attr; -_Noreturn void siglongjmp(sigjmp_buf, int); -#endif - -int _setjmp(jmp_buf) __setjmp_attr; - -_Noreturn void _longjmp(jmp_buf, int); - -int setjmp(jmp_buf) __setjmp_attr; -_Noreturn void longjmp(jmp_buf, int); - -#define setjmp setjmp - -#undef __setjmp_attr - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/c-stdlib/my_stddef.h b/include/c-stdlib/my_stddef.h deleted file mode 100644 index 5cbe8c4..0000000 --- a/include/c-stdlib/my_stddef.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _C_STDLIB_STDDEF_H_ -#define _C_STDLIB_STDDEF_H_ - -typedef signed long ptrdiff_t; -typedef long long intmax_t; - -#endif /* _C_STDLIB_STDDEF_H_ */ diff --git a/include/c-stdlib/my_stdint.h b/include/c-stdlib/my_stdint.h deleted file mode 100644 index 2f039f2..0000000 --- a/include/c-stdlib/my_stdint.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _STDINT_H -#define _STDINT_H 1 - -#define INTPTR_MIN (-9223372036854775807L - 1) -#define INTPTR_MAX (9223372036854775807L) -#define UINTPTR_MAX (18446744073709551615UL) - -#define INT8_C(c) c -#define INT16_C(c) c -#define INT32_C(c) c - -#define UINT8_C(c) c -#define UINT16_C(c) c -#define UINT32_C(c) c##U - -#if UINTPTR_MAX == UINT64_MAX -#define INT64_C(c) c##L -#define UINT64_C(c) c##UL -#define INTMAX_C(c) c##L -#define UINTMAX_C(c) c##UL -#else -#define INT64_C(c) c##LL -#define UINT64_C(c) c##ULL -#define INTMAX_C(c) c##LL -#define UINTMAX_C(c) c##ULL -#endif - -#endif diff --git a/include/c-stdlib/my_stdio.h b/include/c-stdlib/my_stdio.h deleted file mode 100644 index 1d7e55e..0000000 --- a/include/c-stdlib/my_stdio.h +++ /dev/null @@ -1,117 +0,0 @@ - -#ifndef _STDIO_H -#define _STDIO_H 1 - -#include -#include -#include - -#include "../../include/ckb_cell_fs.h" - -#define BUFSIZ 512 -#define EOF (-1) -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 - -#define _IOFBF 0 -#define _IOLBF 1 -#define _IONBF 2 - -typedef struct FILE { - FSFile *file; - uint32_t offset; -} FILE; - -extern FILE *stdin; -extern FILE *stdout; -extern FILE *stderr; - -int remove(const char *__filename); - -int rename(const char *__old, const char *__new); - -FILE *tmpfile(void); - -char *tmpnam(char *__s); - -char *tempnam(const char *__dir, const char *__pfx); - -int fclose(FILE *__stream); -int fflush(FILE *__stream); - -FILE *fopen(const char *__filename, const char *__modes); -FILE *freopen(const char *__filename, const char *__modes, FILE *__stream); - -void setbuf(FILE *__stream, char *__buf); -int setvbuf(FILE *__stream, char *__buf, int __modes, size_t __n); - -int fprintf(FILE *__stream, const char *__format, ...); - -int printf(const char *format, ...); - -int sprintf(char *__s, const char *__format, ...); - -int vfprintf(FILE *__s, const char *__format, ...); - -int vsprintf(char *__s, const char *__format, ...); -int vsnprintf(char *__s, size_t __maxlen, const char *__format, ...); -int snprintf(char *__s, size_t __maxlen, const char *__format, ...); -int snprintf_(char *__s, size_t __maxlen, const char *__format, ...); - -int fscanf(FILE *__stream, const char *__format, ...); - -int scanf(const char *__format, ...); - -int sscanf(const char *__s, const char *__format, ...); - -int fgetc(FILE *__stream); - -int getc(FILE *__stream); - -int getchar(void); - -int fputc(int __c, FILE *__stream); - -int putc(int __c, FILE *__stream); - -int putchar(int __c); - -char *fgets(char *__s, int __n, FILE *__stream); -char *gets(char *__s); - -int getline(char **__lineptr, size_t *__n, FILE *__stream); - -int fputs(const char *__s, FILE *__stream); - -int puts(const char *__s); - -int ungetc(int __c, FILE *__stream); - -size_t fread(void *__ptr, size_t __size, size_t __n, FILE *__stream); - -size_t fwrite(const void *__ptr, size_t __size, size_t __n, FILE *__s); - -int fseek(FILE *__stream, long int __off, int __whence); - -long int ftell(FILE *__stream); - -void rewind(FILE *__stream); - -void clearerr(FILE *__stream); - -int feof(FILE *__stream); - -int ferror(FILE *__stream); - -void perror(const char *__s); - -int fileno(FILE *__stream); - -FILE *popen(const char *__command, const char *__modes); - -int pclose(FILE *__stream); - -void enable_local_access(int); - -#endif /* included. */ diff --git a/include/c-stdlib/my_stdlib.h b/include/c-stdlib/my_stdlib.h deleted file mode 100644 index ca5f292..0000000 --- a/include/c-stdlib/my_stdlib.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef C_STDLIB_STDLIB_H_ -#define C_STDLIB_STDLIB_H_ - -float strtof(const char *__restrict, char **__restrict); -double strtod(const char *__restrict, char **__restrict); -long double strtold(const char *__restrict, char **__restrict); -int atoi(const char *); - -int abs(int); -void exit(int); -void abort(void); -#define alloca __builtin_alloca - -#endif /* C_STDLIB_STDLIB_H_ */ diff --git a/include/c-stdlib/my_string.h b/include/c-stdlib/my_string.h deleted file mode 100644 index 9c551e8..0000000 --- a/include/c-stdlib/my_string.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef C_STDLIB_STRING_H_ -#define C_STDLIB_STRING_H_ - -#include - -char *strchr(const char *, int); -int strncmp(const char *_l, const char *_r, size_t n); -char *strpbrk(const char *, const char *); -size_t strcspn(const char *, const char *); -size_t strspn(const char *, const char *); -void *memchr(const void *, int, size_t); -char *strrchr(const char *str, int character); -char *strcat(char *destination, const char *source); - -int strcoll(const char *, const char *); - -char *strerror(int); - -#endif /* C_STDLIB_STRING_H_ */ diff --git a/include/c-stdlib/src/locale_impl.c b/include/c-stdlib/src/locale_impl.c deleted file mode 100644 index 72bf30d..0000000 --- a/include/c-stdlib/src/locale_impl.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "my_locale.h" - -static const struct lconv posix_lconv = { - .decimal_point = ".", - .thousands_sep = "", - .grouping = "", - .int_curr_symbol = "", - .currency_symbol = "", - .mon_decimal_point = "", - .mon_thousands_sep = "", - .mon_grouping = "", - .positive_sign = "", - .negative_sign = "", - .int_frac_digits = CHAR_MAX, - .frac_digits = CHAR_MAX, - .p_cs_precedes = CHAR_MAX, - .p_sep_by_space = CHAR_MAX, - .n_cs_precedes = CHAR_MAX, - .n_sep_by_space = CHAR_MAX, - .p_sign_posn = CHAR_MAX, - .n_sign_posn = CHAR_MAX, - .int_p_cs_precedes = CHAR_MAX, - .int_p_sep_by_space = CHAR_MAX, - .int_n_cs_precedes = CHAR_MAX, - .int_n_sep_by_space = CHAR_MAX, - .int_p_sign_posn = CHAR_MAX, - .int_n_sign_posn = CHAR_MAX, -}; - -struct lconv *localeconv(void) { return (void *)&posix_lconv; } diff --git a/include/c-stdlib/src/malloc_impl.c b/include/c-stdlib/src/malloc_impl.c deleted file mode 100644 index 22ed241..0000000 --- a/include/c-stdlib/src/malloc_impl.c +++ /dev/null @@ -1,398 +0,0 @@ -#define CKB_MALLOC_DECLARATION_ONLY 1 -#include -#include -#include -#include - -#ifndef CKB_BRK_MIN -extern char _end[]; /* _end is set in the linker */ -#define CKB_BRK_MIN ((uintptr_t)&_end) -#endif -#ifndef CKB_BRK_MAX -#define CKB_BRK_MAX 0x00300000 -#endif - -struct chunk { - size_t psize, csize; - struct chunk *next, *prev; -}; - -struct bin { - volatile int lock[2]; - struct chunk *head; - struct chunk *tail; -}; - -#define CKB_SIZE_ALIGN (4 * sizeof(size_t)) -#define CKB_SIZE_MASK (-CKB_SIZE_ALIGN) -#define CKB_OVERHEAD (2 * sizeof(size_t)) -#define CKB_DONTCARE 16 -#define CKB_RECLAIM 163840 -#define CKB_MMAP_THRESHOLD (0x1c00 * CKB_SIZE_ALIGN) - -#define CKB_CHUNK_SIZE(c) ((c)->csize & -2) -#define CKB_CHUNK_PSIZE(c) ((c)->psize & -2) -#define CKB_PREV_CHUNK(c) ((struct chunk *)((char *)(c)-CKB_CHUNK_PSIZE(c))) -#define CKB_NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CKB_CHUNK_SIZE(c))) -#define CKB_MEM_TO_CHUNK(p) (struct chunk *)((char *)(p)-CKB_OVERHEAD) -#define CKB_CHUNK_TO_MEM(c) (void *)((char *)(c) + CKB_OVERHEAD) -#define CKB_BIN_TO_CHUNK(i) (CKB_MEM_TO_CHUNK(&mal.bins[i].head)) -#define CKB_C_INUSE ((size_t)1) -#define CKB_IS_MMAPPED(c) !((c)->csize & (CKB_C_INUSE)) -#define CKB_PAGE_SIZE 4096 -void __bin_chunk(struct chunk *); -int ckb_exit(int8_t code); -static inline void a_crash() { ckb_exit(-1); } -void free(void *p); - -static inline void a_and_64(volatile uint64_t *p, uint64_t v) { *p &= v; } - -static inline void a_or_64(volatile uint64_t *p, uint64_t v) { *p |= v; } - -static uintptr_t s_program_break = 0; -static uintptr_t s_brk_min = CKB_BRK_MIN; -static uintptr_t s_brk_max = CKB_BRK_MAX; - -void malloc_config(uintptr_t min, uintptr_t max) { - s_brk_min = min; - s_brk_max = max; - s_program_break = 0; -} - -size_t malloc_usage() { - size_t high = (size_t)s_program_break; - size_t low = (size_t)s_brk_min; - return high - low; -} - -void *_sbrk(uintptr_t incr) { - if (!s_program_break) { - s_program_break = s_brk_min; - s_program_break += -s_program_break & (CKB_PAGE_SIZE - 1); - } - if ((s_program_break + incr) > s_brk_max) { - return (void *)-1; - } - - uintptr_t start = s_program_break; - s_program_break += incr; - return (void *)start; -} - -static struct { - volatile uint64_t binmap; - struct bin bins[64]; - volatile int split_merge_lock[2]; -} mal; - -static inline void lock_bin(int i) { - if (!mal.bins[i].head) mal.bins[i].head = mal.bins[i].tail = CKB_BIN_TO_CHUNK(i); -} - -static inline void unlock_bin(int i) {} - -#if 0 -static int first_set(uint64_t x) { - // TODO: use RISC-V asm - static const char debruijn64[64] = { - 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, - 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, - 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, - 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12}; - static const char debruijn32[32] = { - 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, - 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14}; - if (sizeof(long) < 8) { - uint32_t y = x; - if (!y) { - y = x >> 32; - return 32 + debruijn32[(y & -y) * 0x076be629 >> 27]; - } - return debruijn32[(y & -y) * 0x076be629 >> 27]; - } - return debruijn64[(x & -x) * 0x022fdd63cc95386dull >> 58]; -} - -#else - -static int __attribute__((naked)) first_set(uint64_t x) { - __asm__(".byte 0x13, 0x15, 0x15, 0x60"); - __asm__("ret"); -} - -#endif - -static const unsigned char bin_tab[60] = { - 32, 33, 34, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41, - 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, - 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, -}; - -static int bin_index(size_t x) { - x = x / CKB_SIZE_ALIGN - 1; - if (x <= 32) return x; - if (x < 512) return bin_tab[x / 8 - 4]; - if (x > 0x1c00) return 63; - return bin_tab[x / 128 - 4] + 16; -} - -static int bin_index_up(size_t x) { - x = x / CKB_SIZE_ALIGN - 1; - if (x <= 32) return x; - x--; - if (x < 512) return bin_tab[x / 8 - 4] + 1; - return bin_tab[x / 128 - 4] + 17; -} - -static void *__expand_heap(size_t *pn) { - size_t n = *pn; - n += -n & (CKB_PAGE_SIZE - 1); - - void *p = _sbrk(n); - if (p == (void *)-1) { - return 0; - } - *pn = n; - return p; -} - -static struct chunk *expand_heap(size_t n) { - static void *end; - void *p; - struct chunk *w; - - /* The argument n already accounts for the caller's chunk - * CKB_OVERHEAD needs, but if the heap can't be extended in-place, - * we need room for an extra zero-sized sentinel chunk. */ - n += CKB_SIZE_ALIGN; - - p = __expand_heap(&n); - if (!p) return 0; - /* If not just expanding existing space, we need to make a - * new sentinel chunk below the allocated space. */ - if (p != end) { - /* Valid/safe because of the prologue increment. */ - n -= CKB_SIZE_ALIGN; - p = (char *)p + CKB_SIZE_ALIGN; - w = CKB_MEM_TO_CHUNK(p); - w->psize = 0 | CKB_C_INUSE; - } - - /* Record new heap end and fill in footer. */ - end = (char *)p + n; - w = CKB_MEM_TO_CHUNK(end); - w->psize = n | CKB_C_INUSE; - w->csize = 0 | CKB_C_INUSE; - - /* Fill in header, which may be new or may be replacing a - * zero-size sentinel header at the old end-of-heap. */ - w = CKB_MEM_TO_CHUNK(p); - w->csize = n | CKB_C_INUSE; - - return w; -} - -static int adjust_size(size_t *n) { - /* Result of pointer difference must fit in ptrdiff_t. */ - if (*n - 1 > INT64_MAX - CKB_SIZE_ALIGN - CKB_PAGE_SIZE) { - if (*n) { - return -1; - } else { - *n = CKB_SIZE_ALIGN; - return 0; - } - } - *n = (*n + CKB_OVERHEAD + CKB_SIZE_ALIGN - 1) & CKB_SIZE_MASK; - return 0; -} - -static void unbin(struct chunk *c, int i) { - if (c->prev == c->next) a_and_64(&mal.binmap, ~(1ULL << i)); - c->prev->next = c->next; - c->next->prev = c->prev; - c->csize |= CKB_C_INUSE; - CKB_NEXT_CHUNK(c)->psize |= CKB_C_INUSE; -} - -static void bin_chunk(struct chunk *self, int i) { - self->next = CKB_BIN_TO_CHUNK(i); - self->prev = mal.bins[i].tail; - self->next->prev = self; - self->prev->next = self; - if (self->prev == CKB_BIN_TO_CHUNK(i)) a_or_64(&mal.binmap, 1ULL << i); -} - -static void trim(struct chunk *self, size_t n) { - size_t n1 = CKB_CHUNK_SIZE(self); - struct chunk *next, *split; - - if (n >= n1 - CKB_DONTCARE) return; - - next = CKB_NEXT_CHUNK(self); - split = (void *)((char *)self + n); - - split->psize = n | CKB_C_INUSE; - split->csize = n1 - n; - next->psize = n1 - n; - self->csize = n | CKB_C_INUSE; - - int i = bin_index(n1 - n); - lock_bin(i); - - bin_chunk(split, i); - - unlock_bin(i); -} - -void *malloc(size_t n) { - struct chunk *c; - int i, j; - uint64_t mask; - - if (adjust_size(&n) < 0) return 0; - - if (n >= CKB_MMAP_THRESHOLD) { - // TODO: don't support too large memory - return 0; - } - - i = bin_index_up(n); - if (i < 63 && (mal.binmap & (1ULL << i))) { - lock_bin(i); - c = mal.bins[i].head; - if (c != CKB_BIN_TO_CHUNK(i) && CKB_CHUNK_SIZE(c) - n <= CKB_DONTCARE) { - unbin(c, i); - unlock_bin(i); - return CKB_CHUNK_TO_MEM(c); - } - unlock_bin(i); - } - for (mask = mal.binmap & -(1ULL << i); mask; mask -= (mask & -mask)) { - j = first_set(mask); - lock_bin(j); - c = mal.bins[j].head; - if (c != CKB_BIN_TO_CHUNK(j)) { - unbin(c, j); - unlock_bin(j); - break; - } - unlock_bin(j); - } - if (!mask) { - c = expand_heap(n); - if (!c) { - return 0; - } - } - trim(c, n); - return CKB_CHUNK_TO_MEM(c); -} - -void *realloc(void *p, size_t n) { - struct chunk *self, *next; - size_t n0; - void *new; - - if (!p) return malloc(n); - - if (adjust_size(&n) < 0) return 0; - - self = CKB_MEM_TO_CHUNK(p); - n0 = CKB_CHUNK_SIZE(self); - - if (n <= n0 && n0 - n <= CKB_DONTCARE) return p; - - next = CKB_NEXT_CHUNK(self); - - /* Crash on corrupted footer (likely from buffer overflow) */ - if (next->psize != self->csize) a_crash(); - - if (n < n0) { - int i = bin_index_up(n); - int j = bin_index(n0); - if (i < j && (mal.binmap & (1ULL << i))) goto copy_realloc; - struct chunk *split = (void *)((char *)self + n); - self->csize = split->psize = n | CKB_C_INUSE; - split->csize = next->psize = (n0 - n) | CKB_C_INUSE; - __bin_chunk(split); - return CKB_CHUNK_TO_MEM(self); - } - - size_t nsize = next->csize & CKB_C_INUSE ? 0 : CKB_CHUNK_SIZE(next); - if (n0 + nsize >= n) { - int i = bin_index(nsize); - lock_bin(i); - if (!(next->csize & CKB_C_INUSE)) { - unbin(next, i); - unlock_bin(i); - next = CKB_NEXT_CHUNK(next); - self->csize = next->psize = (n0 + nsize) | CKB_C_INUSE; - trim(self, n); - return CKB_CHUNK_TO_MEM(self); - } - unlock_bin(i); - } -copy_realloc: - /* As a last resort, allocate a new chunk and copy to it. */ - new = malloc(n - CKB_OVERHEAD); - if (!new) return 0; - memcpy(new, p, (n < n0 ? n : n0) - CKB_OVERHEAD); - free(CKB_CHUNK_TO_MEM(self)); - return new; -} - -void __bin_chunk(struct chunk *self) { - struct chunk *next = CKB_NEXT_CHUNK(self); - - /* Crash on corrupted footer (likely from buffer overflow) */ - if (next->psize != self->csize) a_crash(); - - size_t osize = CKB_CHUNK_SIZE(self), size = osize; - - /* Since we hold split_merge_lock, only transition from free to - * in-use can race; in-use to free is impossible */ - size_t psize = self->psize & CKB_C_INUSE ? 0 : CKB_CHUNK_PSIZE(self); - size_t nsize = next->csize & CKB_C_INUSE ? 0 : CKB_CHUNK_SIZE(next); - - if (psize) { - int i = bin_index(psize); - lock_bin(i); - if (!(self->psize & CKB_C_INUSE)) { - struct chunk *prev = CKB_PREV_CHUNK(self); - unbin(prev, i); - self = prev; - size += psize; - } - unlock_bin(i); - } - if (nsize) { - int i = bin_index(nsize); - lock_bin(i); - if (!(next->csize & CKB_C_INUSE)) { - unbin(next, i); - next = CKB_NEXT_CHUNK(next); - size += nsize; - } - unlock_bin(i); - } - - int i = bin_index(size); - lock_bin(i); - - self->csize = size; - next->psize = size; - bin_chunk(self, i); - - unlock_bin(i); -} - -void free(void *p) { - if (!p) return; - struct chunk *self = CKB_MEM_TO_CHUNK(p); - __bin_chunk(self); -} - -size_t malloc_usable_size(void *ptr) { - struct chunk *c = CKB_MEM_TO_CHUNK(ptr); - return CKB_CHUNK_PSIZE(c); -} diff --git a/include/c-stdlib/src/math_impl.c b/include/c-stdlib/src/math_impl.c deleted file mode 100644 index ce38a64..0000000 --- a/include/c-stdlib/src/math_impl.c +++ /dev/null @@ -1,265 +0,0 @@ -#include "../my_math.h" -#include -#include "my_stdio.h" -#include "my_assert.h" - -#ifndef DBL_EPSILON -#define DBL_EPSILON 2.22044604925031308085e-16 -#endif - -double acos(double x) { - assert(0); - return 0; -} - -double asin(double x) { - assert(0); - return 0; -} - -double atan2(double x, double y) { - assert(0); - return 0; -} - -double cos(double x) { - assert(0); - return 0; -} - -double cosh(double x) { - assert(0); - return 0; -} - -double exp(double x) { - assert(0); - return 0; -} - -#define EPS DBL_EPSILON -double floor(double x) { - static const double toint = 1 / EPS; - union { - double f; - uint64_t i; - } u = {x}; - int e = u.i >> 52 & 0x7ff; - double y; - - if (e >= 0x3ff + 52 || x == 0) return x; - /* y = int(x) - x, where int(x) is an integer neighbor of x */ - if (u.i >> 63) - y = x - toint + toint - x; - else - y = x + toint - toint - x; - /* special case because of non-nearest rounding modes */ - if (e <= 0x3ff - 1) { - FORCE_EVAL(y); - return u.i >> 63 ? -1 : 0; - } - if (y > 0) return x + y - 1; - return x + y; -} - -double ceil(double x) { - static const double toint = 1 / EPS; - union { - double f; - uint64_t i; - } u = {x}; - int e = u.i >> 52 & 0x7ff; - double y; - - if (e >= 0x3ff + 52 || x == 0) return x; - /* y = int(x) - x, where int(x) is an integer neighbor of x */ - if (u.i >> 63) - y = x - toint + toint - x; - else - y = x + toint - toint - x; - /* special case because of non-nearest rounding modes */ - if (e <= 0x3ff - 1) { - FORCE_EVAL(y); - return u.i >> 63 ? -0.0 : 1; - } - if (y < 0) return x + y + 1; - return x + y; -} - -double fabs(double x) { - union { - double f; - uint64_t i; - } u = {x}; - u.i &= -1ULL / 2; - return u.f; -} - -double ldexp(double x, int n) { return scalbn(x, n); } - -double log2(double x) { - assert(0); - return 0; -} - -double log10(double x) { - assert(0); - return 0; -} - -double sin(double x) { - assert(0); - return 0; -} - -double sinh(double x) { - assert(0); - return 0; -} - -double sqrt(double x) { - assert(0); - return 0; -} - -double tan(double x) { - assert(0); - return 0; -} - -double tanh(double x) { - assert(0); - return 0; -} - -double rint(double x) { - static const double toint = 1 / EPS; - union { - double f; - uint64_t i; - } u = {x}; - int e = u.i >> 52 & 0x7ff; - int s = u.i >> 63; - double y; - - if (e >= 0x3ff + 52) return x; - if (s) - y = x - toint + toint; - else - y = x + toint - toint; - if (y == 0) return s ? -0.0 : 0; - return y; -} - -long int lrint(double x) { return rint(x); } - -double cbrt(double x) { - assert(0); - return 0; -} - -double fmod(double numer, double denom); - -double fmin(double x, double y) { return x > y ? y : x; } - -double fmax(double x, double y) { return x < y ? y : x; } - -double hypot(double x, double y) { - assert(0); - return 0; -} - -int signbit(double num) { return num > 0; } - -double frexp(double x, int *e) { - union { - double d; - uint64_t i; - } y = {x}; - int ee = y.i >> 52 & 0x7ff; - - if (!ee) { - if (x) { - x = frexp(x * 0x1p64, e); - *e -= 64; - } else - *e = 0; - return x; - } else if (ee == 0x7ff) { - return x; - } - - *e = ee - 0x3fe; - y.i &= 0x800fffffffffffffull; - y.i |= 0x3fe0000000000000ull; - return y.d; -} - -double fmod(double x, double y) { - union { - double f; - uint64_t i; - } ux = {x}, uy = {y}; - int ex = ux.i >> 52 & 0x7ff; - int ey = uy.i >> 52 & 0x7ff; - int sx = ux.i >> 63; - uint64_t i; - - /* in the followings uxi should be ux.i, but then gcc wrongly adds */ - /* float load/store to inner loops ruining performance and code size */ - uint64_t uxi = ux.i; - - if (uy.i << 1 == 0 || __builtin_isnan(y) || ex == 0x7ff) return (x * y) / (x * y); - if (uxi << 1 <= uy.i << 1) { - if (uxi << 1 == uy.i << 1) return 0 * x; - return x; - } - - /* normalize x and y */ - if (!ex) { - for (i = uxi << 12; i >> 63 == 0; ex--, i <<= 1) - ; - uxi <<= -ex + 1; - } else { - uxi &= -1ULL >> 12; - uxi |= 1ULL << 52; - } - if (!ey) { - for (i = uy.i << 12; i >> 63 == 0; ey--, i <<= 1) - ; - uy.i <<= -ey + 1; - } else { - uy.i &= -1ULL >> 12; - uy.i |= 1ULL << 52; - } - - /* x mod y */ - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 63 == 0) { - if (i == 0) return 0 * x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 63 == 0) { - if (i == 0) return 0 * x; - uxi = i; - } - for (; uxi >> 52 == 0; uxi <<= 1, ex--) - ; - - /* scale result */ - if (ex > 0) { - uxi -= 1ULL << 52; - uxi |= (uint64_t)ex << 52; - } else { - uxi >>= -ex + 1; - } - uxi |= (uint64_t)sx << 63; - ux.i = uxi; - return ux.f; -} - -int abs(int a) { return a > 0 ? a : -a; } diff --git a/include/c-stdlib/src/math_log_impl.c b/include/c-stdlib/src/math_log_impl.c deleted file mode 100644 index 5539cca..0000000 --- a/include/c-stdlib/src/math_log_impl.c +++ /dev/null @@ -1,132 +0,0 @@ -/* @(#)e_log.c 1.3 95/01/18 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -//__FBSDID("$FreeBSD: src/lib/msun/src/e_log.c,v 1.15 2008/03/29 16:37:59 das -// Exp $"); - -/* __ieee754_log(x) - * Return the logrithm of x - * - * Method : - * 1. Argument Reduction: find k and f such that - * x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * 2. Approximation of log(1+f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s - * (the values of Lg1 to Lg7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lg1*s +...+Lg7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log(1+f) = f - s*(f - R) (if f is not too large) - * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) - * - * 3. Finally, log(x) = k*ln2 + log(1+f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log(x) is NaN with signal if x < 0 (including -INF) ; - * log(+INF) is +INF; log(0) is -INF with signal; - * log(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "my_math.h" -#include -#include "my_float.h" - -double log(double x) { - double hfsq, f, s, z, R, w, t1, t2, dk; - int32_t k, hx, i, j; - uint32_t lx; - - EXTRACT_WORDS(hx, lx, x); - - k = 0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx & 0x7fffffff) | lx) == 0) return -two54 / zero; /* log(+-0)=-inf */ - if (hx < 0) return (x - x) / zero; /* log(-#) = NaN */ - k -= 54; - x *= two54; /* subnormal number, scale up x */ - GET_HIGH_WORD(hx, x); - } - if (hx >= 0x7ff00000) return x + x; - k += (hx >> 20) - 1023; - hx &= 0x000fffff; - i = (hx + 0x95f64) & 0x100000; - SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */ - k += (i >> 20); - f = x - 1.0; - if ((0x000fffff & (2 + hx)) < 3) { /* -2**-20 <= f < 2**-20 */ - if (f == zero) { - if (k == 0) { - return zero; - } else { - dk = (double)k; - return dk * ln2_hi + dk * ln2_lo; - } - } - R = f * f * (0.5 - 0.33333333333333333 * f); - if (k == 0) - return f - R; - else { - dk = (double)k; - return dk * ln2_hi - ((R - dk * ln2_lo) - f); - } - } - s = f / (2.0 + f); - dk = (double)k; - z = s * s; - i = hx - 0x6147a; - w = z * z; - j = 0x6b851 - hx; - t1 = w * (Lg2 + w * (Lg4 + w * Lg6)); - t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7))); - i |= j; - R = t2 + t1; - if (i > 0) { - hfsq = 0.5 * f * f; - if (k == 0) - return f - (hfsq - s * (hfsq + R)); - else - return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f); - } else { - if (k == 0) - return f - s * (f - R); - else - return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f); - } -} diff --git a/include/c-stdlib/src/math_pow_impl.c b/include/c-stdlib/src/math_pow_impl.c deleted file mode 100644 index b9ff050..0000000 --- a/include/c-stdlib/src/math_pow_impl.c +++ /dev/null @@ -1,329 +0,0 @@ -/* @(#)e_pow.c 1.5 04/04/22 SMI */ -/* - * ==================================================== - * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. - * - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -//__FBSDID("$FreeBSD: src/lib/msun/src/e_pow.c,v 1.14 2011/10/21 06:26:07 das -// Exp $"); - -/* __ieee754_pow(x,y) return x**y - * - * n - * Method: Let x = 2 * (1+f) - * 1. Compute and return log2(x) in two pieces: - * log2(x) = w1 + w2, - * where w1 has 53-24 = 29 bit trailing zeros. - * 2. Perform y*log2(x) = n+y' by simulating muti-precision - * arithmetic, where |y'|<=0.5. - * 3. Return x**y = 2**n*exp(y'*log2) - * - * Special cases: - * 1. (anything) ** 0 is 1 - * 2. (anything) ** 1 is itself - * 3. (anything) ** NAN is NAN - * 4. NAN ** (anything except 0) is NAN - * 5. +-(|x| > 1) ** +INF is +INF - * 6. +-(|x| > 1) ** -INF is +0 - * 7. +-(|x| < 1) ** +INF is +0 - * 8. +-(|x| < 1) ** -INF is +INF - * 9. +-1 ** +-INF is NAN - * 10. +0 ** (+anything except 0, NAN) is +0 - * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 - * 12. +0 ** (-anything except 0, NAN) is +INF - * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF - * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) - * 15. +INF ** (+anything except 0,NAN) is +INF - * 16. +INF ** (-anything except 0,NAN) is +0 - * 17. -INF ** (anything) = -0 ** (-anything) - * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) - * 19. (-anything except 0 and inf) ** (non-integer) is NAN - * - * Accuracy: - * pow(x,y) returns x**y nearly rounded. In particular - * pow(integer,integer) - * always returns the correct integer provided it is - * representable. - * - * Constants : - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ -#include "my_float.h" -#include "my_math.h" -#include - -double copysign(double x, double y) { - uint32_t hx, hy; - GET_HIGH_WORD(hx, x); - GET_HIGH_WORD(hy, y); - SET_HIGH_WORD(x, (hx & 0x7fffffff) | (hy & 0x80000000)); - return x; -} - -double scalbn(double x, int n) { - int32_t k, hx, lx; - EXTRACT_WORDS(hx, lx, x); - k = (hx & 0x7ff00000) >> 20; /* extract exponent */ - if (k == 0) { /* 0 or subnormal x */ - if ((lx | (hx & 0x7fffffff)) == 0) return x; /* +-0 */ - x *= two54; - GET_HIGH_WORD(hx, x); - k = ((hx & 0x7ff00000) >> 20) - 54; - if (n < -50000) return tiny * x; /*underflow*/ - } - if (k == 0x7ff) return x + x; /* NaN or Inf */ - k = k + n; - if (k > 0x7fe) return huge * copysign(huge, x); /* overflow */ - if (k > 0) /* normal result */ - { - SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20)); - return x; - } - if (k <= -54) { - if (n > 50000) /* in case integer overflow in n+k */ - return huge * copysign(huge, x); /*overflow*/ - else - return tiny * copysign(tiny, x); /*underflow*/ - } - k += 54; /* subnormal result */ - SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20)); - return x * twom54; -} - -double pow(double x, double y) { - double z, ax, z_h, z_l, p_h, p_l; - double y1, t1, t2, r, s, t, u, v, w; - int32_t i, j, k, yisint, n; - int32_t hx, hy, ix, iy; - uint32_t lx, ly; - - EXTRACT_WORDS(hx, lx, x); - EXTRACT_WORDS(hy, ly, y); - ix = hx & 0x7fffffff; - iy = hy & 0x7fffffff; - - /* y==zero: x**0 = 1 */ - if ((iy | ly) == 0) return one; - - /* x==1: 1**y = 1, even if y is NaN */ - if (hx == 0x3ff00000 && lx == 0) return one; - - /* y!=zero: result is NaN if either arg is NaN */ - if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) || iy > 0x7ff00000 || ((iy == 0x7ff00000) && (ly != 0))) - return (x + 0.0) + (y + 0.0); - - /* determine if y is an odd int when x < 0 - * yisint = 0 ... y is not an integer - * yisint = 1 ... y is an odd int - * yisint = 2 ... y is an even int - */ - yisint = 0; - if (hx < 0) { - if (iy >= 0x43400000) - yisint = 2; /* even integer y */ - else if (iy >= 0x3ff00000) { - k = (iy >> 20) - 0x3ff; /* exponent */ - if (k > 20) { - j = ly >> (52 - k); - if ((j << (52 - k)) == (int32_t)ly) yisint = 2 - (j & 1); - } else if (ly == 0) { - j = iy >> (20 - k); - if ((j << (20 - k)) == iy) yisint = 2 - (j & 1); - } - } - } - - /* special value of y */ - if (ly == 0) { - if (iy == 0x7ff00000) { /* y is +-inf */ - if (((ix - 0x3ff00000) | lx) == 0) - return one; /* (-1)**+-inf is NaN */ - else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ - return (hy >= 0) ? y : zero; - else /* (|x|<1)**-,+inf = inf,0 */ - return (hy < 0) ? -y : zero; - } - if (iy == 0x3ff00000) { /* y is +-1 */ - if (hy < 0) - return one / x; - else - return x; - } - if (hy == 0x40000000) return x * x; /* y is 2 */ - if (hy == 0x40080000) return x * x * x; /* y is 3 */ - if (hy == 0x40100000) { /* y is 4 */ - u = x * x; - return u * u; - } - if (hy == 0x3fe00000) { /* y is 0.5 */ - if (hx >= 0) /* x >= +0 */ - return sqrt(x); - } - } - - ax = fabs(x); - /* special value of x */ - if (lx == 0) { - if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { - z = ax; /*x is +-0,+-inf,+-1*/ - if (hy < 0) z = one / z; /* z = (1/|x|) */ - if (hx < 0) { - if (((ix - 0x3ff00000) | yisint) == 0) { - z = (z - z) / (z - z); /* (-1)**non-int is NaN */ - } else if (yisint == 1) - z = -z; /* (x<0)**odd = -(|x|**odd) */ - } - return z; - } - } - - /* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be - n = (hx>>31)+1; - but ANSI C says a right shift of a signed negative quantity is - implementation defined. */ - n = ((uint32_t)hx >> 31) - 1; - - /* (x<0)**(non-int) is NaN */ - if ((n | yisint) == 0) return (x - x) / (x - x); - - s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ - if ((n | (yisint - 1)) == 0) s = -one; /* (-ve)**(odd int) */ - - /* |y| is huge */ - if (iy > 0x41e00000) { /* if |y| > 2**31 */ - if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ - if (ix <= 0x3fefffff) return (hy < 0) ? huge * huge : tiny * tiny; - if (ix >= 0x3ff00000) return (hy > 0) ? huge * huge : tiny * tiny; - } - /* over/underflow if x is not close to one */ - if (ix < 0x3fefffff) return (hy < 0) ? s * huge * huge : s * tiny * tiny; - if (ix > 0x3ff00000) return (hy > 0) ? s * huge * huge : s * tiny * tiny; - /* now |1-x| is tiny <= 2**-20, suffice to compute - log(x) by x-x^2/2+x^3/3-x^4/4 */ - t = ax - one; /* t has 20 trailing zeros */ - w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25)); - u = ivln2_h * t; /* ivln2_h has 21 sig. bits */ - v = t * ivln2_l - w * ivln2; - t1 = u + v; - SET_LOW_WORD(t1, 0); - t2 = v - (t1 - u); - } else { - double ss, s2, s_h, s_l, t_h, t_l; - n = 0; - /* take care subnormal number */ - if (ix < 0x00100000) { - ax *= two53; - n -= 53; - GET_HIGH_WORD(ix, ax); - } - n += ((ix) >> 20) - 0x3ff; - j = ix & 0x000fffff; - /* determine interval */ - ix = j | 0x3ff00000; /* normalize ix */ - if (j <= 0x3988E) - k = 0; /* |x|> 1) | 0x20000000) + 0x00080000 + (k << 18)); - t_l = ax - (t_h - bp[k]); - s_l = v * ((u - s_h * t_h) - s_h * t_l); - /* compute log(ax) */ - s2 = ss * ss; - r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); - r += s_l * (s_h + ss); - s2 = s_h * s_h; - t_h = 3.0 + s2 + r; - SET_LOW_WORD(t_h, 0); - t_l = r - ((t_h - 3.0) - s2); - /* u+v = ss*(1+...) */ - u = s_h * t_h; - v = s_l * t_h + t_l * ss; - /* 2/(3log2)*(ss+...) */ - p_h = u + v; - SET_LOW_WORD(p_h, 0); - p_l = v - (p_h - u); - z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ - z_l = cp_l * p_h + p_l * cp + dp_l[k]; - /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ - t = (double)n; - t1 = (((z_h + z_l) + dp_h[k]) + t); - SET_LOW_WORD(t1, 0); - t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); - } - - /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ - y1 = y; - SET_LOW_WORD(y1, 0); - p_l = (y - y1) * t1 + y * t2; - p_h = y1 * t1; - z = p_l + p_h; - EXTRACT_WORDS(j, i, z); - if (j >= 0x40900000) { /* z >= 1024 */ - if (((j - 0x40900000) | i) != 0) /* if z > 1024 */ - return s * huge * huge; /* overflow */ - else { - if (p_l + ovt > z - p_h) return s * huge * huge; /* overflow */ - } - } else if ((j & 0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ - if (((j - 0xc090cc00) | i) != 0) /* z < -1075 */ - return s * tiny * tiny; /* underflow */ - else { - if (p_l <= z - p_h) return s * tiny * tiny; /* underflow */ - } - } - /* - * compute 2**(p_h+p_l) - */ - i = j & 0x7fffffff; - k = (i >> 20) - 0x3ff; - n = 0; - if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ - n = j + (0x00100000 >> (k + 1)); - k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ - t = zero; - SET_HIGH_WORD(t, n & ~(0x000fffff >> k)); - n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); - if (j < 0) n = -n; - p_h -= t; - } - t = p_l + p_h; - SET_LOW_WORD(t, 0); - u = t * lg2_h; - v = (p_l - (t - p_h)) * lg2 + t * lg2_l; - z = u + v; - w = v - (z - u); - t = z * z; - t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); - r = (z * t1) / (t1 - two) - (w + z * w); - z = one - (r - z); - GET_HIGH_WORD(j, z); - j += (n << 20); - if ((j >> 20) <= 0) - z = scalbn(z, n); /* subnormal output */ - else - SET_HIGH_WORD(z, j); - return s * z; -} diff --git a/include/c-stdlib/src/printf_impl.c b/include/c-stdlib/src/printf_impl.c deleted file mode 100644 index e293b13..0000000 --- a/include/c-stdlib/src/printf_impl.c +++ /dev/null @@ -1,1020 +0,0 @@ -#undef CKB_C_STDLIB_PRINTF -#define CKB_MALLOC_DECLARATION_ONLY 1 - -// Code copied from -// https://github.com/mpaland/printf/tree/d3b984684bb8a8bdc48cc7a1abecb93ce59bbe3e - -#include -#include -#include "my_stddef.h" -#include -#include -#include "my_float.h" - -/** - * Output a character to a custom device like UART, used by the printf() - * function This function is declared here only. You have to write your custom - * implementation somewhere \param character Character to output - */ -void _putchar(char character); - -/** - * Tiny printf implementation - * You have to implement _putchar if you use printf() - * To avoid conflicts with the regular printf() API it is overridden by macro - * defines and internal underscore-appended functions like printf_() are used - * \param format A string that specifies the format of the output - * \return The number of characters that are written into the array, not - * counting the terminating null character - */ -int printf_(const char *format, ...); - -/** - * Tiny sprintf implementation - * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING - * (V)SNPRINTF INSTEAD! \param buffer A pointer to the buffer where to store the - * formatted string. MUST be big enough to store the output! \param format A - * string that specifies the format of the output \return The number of - * characters that are WRITTEN into the buffer, not counting the terminating - * null character - */ -int sprintf(char *buffer, const char *format, ...); - -/** - * Tiny snprintf/vsnprintf implementation - * \param buffer A pointer to the buffer where to store the formatted string - * \param count The maximum number of characters to store in the buffer, - * including a terminating null character \param format A string that specifies - * the format of the output \param va A value identifying a variable arguments - * list \return The number of characters that COULD have been written into the - * buffer, not counting the terminating null character. A value equal or larger - * than count indicates truncation. Only when the returned value is non-negative - * and less than count, the string has been completely written. - */ -int snprintf_(char *buffer, size_t count, const char *format, ...); -int vsnprintf_(char *buffer, size_t count, const char *format, va_list va); - -/** - * Tiny vprintf implementation - * \param format A string that specifies the format of the output - * \param va A value identifying a variable arguments list - * \return The number of characters that are WRITTEN into the buffer, not - * counting the terminating null character - */ -#define vprintf vprintf_ -int vprintf_(const char *format, va_list va); - -/** - * printf with output function - * You may use this as dynamic alternative to printf() with its fixed _putchar() - * output \param out An output function which takes one character and an - * argument pointer \param arg An argument pointer for user data passed to - * output function \param format A string that specifies the format of the - * output \return The number of characters that are sent to the output function, - * not counting the terminating null character - */ -int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...); - -/////////////////////////////////////////////////////////////////////////////// -// \author (c) Marco Paland (info@paland.com) -// 2014-2019, PALANDesign Hannover, Germany -// -// \license The MIT License (MIT) -// -// 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. -// -// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for -// speed on -// embedded systems with a very limited resources. These routines are -// thread safe and reentrant! Use this instead of the bloated -// standard/newlib printf cause these use malloc for printf (and may not -// be thread safe). -// -/////////////////////////////////////////////////////////////////////////////// - -// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the -// printf_config.h header file -// default: undefined -#ifdef PRINTF_INCLUDE_CONFIG_H -#include "printf_config.h" -#endif - -// 'ntoa' conversion buffer size, this must be big enough to hold one converted -// numeric number including padded zeros (dynamically created on stack) -// default: 32 byte -#ifndef PRINTF_NTOA_BUFFER_SIZE -#define PRINTF_NTOA_BUFFER_SIZE 32U -#endif - -// 'ftoa' conversion buffer size, this must be big enough to hold one converted -// float number including padded zeros (dynamically created on stack) -// default: 32 byte -#ifndef PRINTF_FTOA_BUFFER_SIZE -#define PRINTF_FTOA_BUFFER_SIZE 32U -#endif - -// support for the floating point type (%f) -// default: activated -#ifndef PRINTF_DISABLE_SUPPORT_FLOAT -#define PRINTF_SUPPORT_FLOAT -#endif - -// support for exponential floating point notation (%e/%g) -// default: activated -#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL -#define PRINTF_SUPPORT_EXPONENTIAL -#endif - -// define the default floating point precision -// default: 6 digits -#ifndef PRINTF_DEFAULT_FLOAT_PRECISION -#define PRINTF_DEFAULT_FLOAT_PRECISION 6U -#endif - -// define the largest float suitable to print with %f -// default: 1e9 -#ifndef PRINTF_MAX_FLOAT -#define PRINTF_MAX_FLOAT 1e9 -#endif - -// support for the long long types (%llu or %p) -// default: activated -#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG -#define PRINTF_SUPPORT_LONG_LONG -#endif - -// support for the ptrdiff_t type (%t) -// ptrdiff_t is normally defined in as long or long long type -// default: activated -#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T -#define PRINTF_SUPPORT_PTRDIFF_T -#endif - -/////////////////////////////////////////////////////////////////////////////// - -// internal flag definitions -#define FLAGS_ZEROPAD (1U << 0U) -#define FLAGS_LEFT (1U << 1U) -#define FLAGS_PLUS (1U << 2U) -#define FLAGS_SPACE (1U << 3U) -#define FLAGS_HASH (1U << 4U) -#define FLAGS_UPPERCASE (1U << 5U) -#define FLAGS_CHAR (1U << 6U) -#define FLAGS_SHORT (1U << 7U) -#define FLAGS_LONG (1U << 8U) -#define FLAGS_LONG_LONG (1U << 9U) -#define FLAGS_PRECISION (1U << 10U) -#define FLAGS_ADAPT_EXP (1U << 11U) - -// import float.h for DBL_MAX -// #if defined(PRINTF_SUPPORT_FLOAT) -// #include -// #endif - -// output function type -typedef void (*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen); - -// wrapper (used as buffer) for output function type -typedef struct { - void (*fct)(char character, void *arg); - void *arg; -} out_fct_wrap_type; - -// internal buffer output -static inline void _out_buffer(char character, void *buffer, size_t idx, size_t maxlen) { - if (idx < maxlen) { - ((char *)buffer)[idx] = character; - } -} - -// internal null output -static inline void _out_null(char character, void *buffer, size_t idx, size_t maxlen) { - (void)character; - (void)buffer; - (void)idx; - (void)maxlen; -} - -// internal _putchar wrapper -static inline void _out_char(char character, void *buffer, size_t idx, size_t maxlen) { - (void)buffer; - (void)idx; - (void)maxlen; - if (character) { - _putchar(character); - } -} - -// internal output function wrapper -static inline void _out_fct(char character, void *buffer, size_t idx, size_t maxlen) { - (void)idx; - (void)maxlen; - if (character) { - // buffer is the output fct pointer - ((out_fct_wrap_type *)buffer)->fct(character, ((out_fct_wrap_type *)buffer)->arg); - } -} - -// internal secure strlen -// \return The length of the string (excluding the terminating 0) limited by -// 'maxsize' -static inline unsigned int _strnlen_s(const char *str, size_t maxsize) { - const char *s; - for (s = str; *s && maxsize--; ++s) - ; - return (unsigned int)(s - str); -} - -// internal test if char is a digit (0-9) -// \return true if char is a digit -static inline bool _is_digit(char ch) { return (ch >= '0') && (ch <= '9'); } - -// internal ASCII string to unsigned int conversion -unsigned int _atoi(const char **str) { - unsigned int i = 0U; - while (_is_digit(**str)) { - i = i * 10U + (unsigned int)(*((*str)++) - '0'); - } - return i; -} - -int atoi(const char *str) { - if (str[0] == '+') { - const char *sub = str + 1; - return +_atoi(&sub); - } - if (str[0] == '-') { - const char *sub = str + 1; - return -_atoi(&sub); - } - return _atoi(&str); -} - -// output the specified string in reverse, taking care of any zero-padding -static size_t _out_rev(out_fct_type out, char *buffer, size_t idx, size_t maxlen, const char *buf, size_t len, - unsigned int width, unsigned int flags) { - const size_t start_idx = idx; - - // pad spaces up to given width - if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { - for (size_t i = len; i < width; i++) { - out(' ', buffer, idx++, maxlen); - } - } - - // reverse string - while (len) { - out(buf[--len], buffer, idx++, maxlen); - } - - // append pad spaces up to given width - if (flags & FLAGS_LEFT) { - while (idx - start_idx < width) { - out(' ', buffer, idx++, maxlen); - } - } - - return idx; -} - -// internal itoa format -static size_t _ntoa_format(out_fct_type out, char *buffer, size_t idx, size_t maxlen, char *buf, size_t len, - bool negative, unsigned int base, unsigned int prec, unsigned int width, - unsigned int flags) { - // pad leading zeros - if (!(flags & FLAGS_LEFT)) { - if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { - width--; - } - while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - } - - // handle hash - if (flags & FLAGS_HASH) { - if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { - len--; - if (len && (base == 16U)) { - len--; - } - } - if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = 'x'; - } else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = 'X'; - } else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = 'b'; - } - if (len < PRINTF_NTOA_BUFFER_SIZE) { - buf[len++] = '0'; - } - } - - if (len < PRINTF_NTOA_BUFFER_SIZE) { - if (negative) { - buf[len++] = '-'; - } else if (flags & FLAGS_PLUS) { - buf[len++] = '+'; // ignore the space if the '+' exists - } else if (flags & FLAGS_SPACE) { - buf[len++] = ' '; - } - } - - return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); -} - -// internal itoa for 'long' type -static size_t _ntoa_long(out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, - unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) { - char buf[PRINTF_NTOA_BUFFER_SIZE]; - size_t len = 0U; - - // no hash for 0 values - if (!value) { - flags &= ~FLAGS_HASH; - } - - // write if precision != 0 and value is != 0 - if (!(flags & FLAGS_PRECISION) || value) { - do { - const char digit = (char)(value % base); - buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; - value /= base; - } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); - } - - return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); -} - -// internal itoa for 'long long' type -#if defined(PRINTF_SUPPORT_LONG_LONG) -static size_t _ntoa_long_long(out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned long long value, - bool negative, unsigned long long base, unsigned int prec, unsigned int width, - unsigned int flags) { - char buf[PRINTF_NTOA_BUFFER_SIZE]; - size_t len = 0U; - - // no hash for 0 values - if (!value) { - flags &= ~FLAGS_HASH; - } - - // write if precision != 0 and value is != 0 - if (!(flags & FLAGS_PRECISION) || value) { - do { - const char digit = (char)(value % base); - buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; - value /= base; - } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); - } - - return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); -} -#endif // PRINTF_SUPPORT_LONG_LONG - -#if defined(PRINTF_SUPPORT_FLOAT) - -#if defined(PRINTF_SUPPORT_EXPONENTIAL) -// forward declaration so that _ftoa can switch to exp notation for values > -// PRINTF_MAX_FLOAT -static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, - unsigned int width, unsigned int flags); -#endif - -// internal ftoa for fixed decimal floating point -static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, - unsigned int width, unsigned int flags) { - char buf[PRINTF_FTOA_BUFFER_SIZE]; - size_t len = 0U; - double diff = 0.0; - - // powers of 10 - static const double pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; - - // test for special values - if (value != value) return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); - if (value < -DBL_MAX) return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); - if (value > DBL_MAX) - return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, - width, flags); - - // test for very large values - // standard printf behavior is to print EVERY whole number digit -- which - // could be 100s of characters overflowing your buffers == bad - if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { -#if defined(PRINTF_SUPPORT_EXPONENTIAL) - return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); -#else - return 0U; -#endif - } - - // test for negative - bool negative = false; - if (value < 0) { - negative = true; - value = 0 - value; - } - - // set default precision, if not set explicitly - if (!(flags & FLAGS_PRECISION)) { - prec = PRINTF_DEFAULT_FLOAT_PRECISION; - } - // limit precision to 9, cause a prec >= 10 can lead to overflow errors - while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { - buf[len++] = '0'; - prec--; - } - - int whole = (int)value; - double tmp = (value - whole) * pow10[prec]; - unsigned long frac = (unsigned long)tmp; - diff = tmp - frac; - - if (diff > 0.5) { - ++frac; - // handle rollover, e.g. case 0.99 with prec 1 is 1.0 - if (frac >= pow10[prec]) { - frac = 0; - ++whole; - } - } else if (diff < 0.5) { - } else if ((frac == 0U) || (frac & 1U)) { - // if halfway, round up if odd OR if last digit is 0 - ++frac; - } - - if (prec == 0U) { - diff = value - (double)whole; - if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { - // exactly 0.5 and ODD, then round up - // 1.5 -> 2, but 2.5 -> 2 - ++whole; - } - } else { - unsigned int count = prec; - // now do fractional part, as an unsigned number - while (len < PRINTF_FTOA_BUFFER_SIZE) { - --count; - buf[len++] = (char)(48U + (frac % 10U)); - if (!(frac /= 10U)) { - break; - } - } - // add extra 0s - while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { - buf[len++] = '0'; - } - if (len < PRINTF_FTOA_BUFFER_SIZE) { - // add decimal - buf[len++] = '.'; - } - } - - // do whole part, number is reversed - while (len < PRINTF_FTOA_BUFFER_SIZE) { - buf[len++] = (char)(48 + (whole % 10)); - if (!(whole /= 10)) { - break; - } - } - - // pad leading zeros - if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { - if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { - width--; - } - while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - } - - if (len < PRINTF_FTOA_BUFFER_SIZE) { - if (negative) { - buf[len++] = '-'; - } else if (flags & FLAGS_PLUS) { - buf[len++] = '+'; // ignore the space if the '+' exists - } else if (flags & FLAGS_SPACE) { - buf[len++] = ' '; - } - } - - return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); -} - -#if defined(PRINTF_SUPPORT_EXPONENTIAL) -// internal ftoa variant for exponential floating-point type, contributed by -// Martijn Jasperse -static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, - unsigned int width, unsigned int flags) { - // check for NaN and special values - if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { - return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); - } - - // determine the sign - const bool negative = value < 0; - if (negative) { - value = -value; - } - - // default precision - if (!(flags & FLAGS_PRECISION)) { - prec = PRINTF_DEFAULT_FLOAT_PRECISION; - } - - // determine the decimal exponent - // based on the algorithm by David Gay - // (https://www.ampl.com/netlib/fp/dtoa.c) - union { - uint64_t U; - double F; - } conv; - - conv.F = value; - int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 - conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) - // now approximate log10 from the log2 integer part and an expansion of ln - // around 1.5 - int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); - // now we want to compute 10^expval but we want to be sure it won't overflow - exp2 = (int)(expval * 3.321928094887362 + 0.5); - const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; - const double z2 = z * z; - conv.U = (uint64_t)(exp2 + 1023) << 52U; - // compute exp(z) using continued fractions, see - // https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex - conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); - // correct for rounding errors - if (value < conv.F) { - expval--; - conv.F /= 10; - } - - // the exponent format is "%+03d" and largest value is "307", so set aside - // 4-5 characters - unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; - - // in "%g" mode, "prec" is the number of *significant figures* not decimals - if (flags & FLAGS_ADAPT_EXP) { - // do we want to fall-back to "%f" mode? - if ((value >= 1e-4) && (value < 1e6)) { - if ((int)prec > expval) { - prec = (unsigned)((int)prec - expval - 1); - } else { - prec = 0; - } - flags |= FLAGS_PRECISION; // make sure _ftoa respects precision - // no characters in exponent - minwidth = 0U; - expval = 0; - } else { - // we use one sigfig for the whole part - if ((prec > 0) && (flags & FLAGS_PRECISION)) { - --prec; - } - } - } - - // will everything fit? - unsigned int fwidth = width; - if (width > minwidth) { - // we didn't fall-back so subtract the characters required for the - // exponent - fwidth -= minwidth; - } else { - // not enough characters, so go back to default sizing - fwidth = 0U; - } - if ((flags & FLAGS_LEFT) && minwidth) { - // if we're padding on the right, DON'T pad the floating part - fwidth = 0U; - } - - // rescale the float value - if (expval) { - value /= conv.F; - } - - // output the floating part - const size_t start_idx = idx; - idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); - - // output the exponent part - if (minwidth) { - // output the exponential symbol - out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); - // output the exponent value - idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth - 1, - FLAGS_ZEROPAD | FLAGS_PLUS); - // might need to right-pad spaces - if (flags & FLAGS_LEFT) { - while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); - } - } - return idx; -} -#endif // PRINTF_SUPPORT_EXPONENTIAL -#endif // PRINTF_SUPPORT_FLOAT - -// internal vsnprintf -static int _vsnprintf(out_fct_type out, char *buffer, const size_t maxlen, const char *format, va_list va) { - unsigned int flags, width, precision, n; - size_t idx = 0U; - - if (!buffer) { - // use null output function - out = _out_null; - } - - while (*format) { - // format specifier? %[flags][width][.precision][length] - if (*format != '%') { - // no - out(*format, buffer, idx++, maxlen); - format++; - continue; - } else { - // yes, evaluate it - format++; - } - - // evaluate flags - flags = 0U; - do { - switch (*format) { - case '0': - flags |= FLAGS_ZEROPAD; - format++; - n = 1U; - break; - case '-': - flags |= FLAGS_LEFT; - format++; - n = 1U; - break; - case '+': - flags |= FLAGS_PLUS; - format++; - n = 1U; - break; - case ' ': - flags |= FLAGS_SPACE; - format++; - n = 1U; - break; - case '#': - flags |= FLAGS_HASH; - format++; - n = 1U; - break; - default: - n = 0U; - break; - } - } while (n); - - // evaluate width field - width = 0U; - if (_is_digit(*format)) { - width = _atoi(&format); - } else if (*format == '*') { - const int w = va_arg(va, int); - if (w < 0) { - flags |= FLAGS_LEFT; // reverse padding - width = (unsigned int)-w; - } else { - width = (unsigned int)w; - } - format++; - } - - // evaluate precision field - precision = 0U; - if (*format == '.') { - flags |= FLAGS_PRECISION; - format++; - if (_is_digit(*format)) { - precision = _atoi(&format); - } else if (*format == '*') { - const int prec = (int)va_arg(va, int); - precision = prec > 0 ? (unsigned int)prec : 0U; - format++; - } - } - - // evaluate length field - switch (*format) { - case 'l': - flags |= FLAGS_LONG; - format++; - if (*format == 'l') { - flags |= FLAGS_LONG_LONG; - format++; - } - break; - case 'h': - flags |= FLAGS_SHORT; - format++; - if (*format == 'h') { - flags |= FLAGS_CHAR; - format++; - } - break; -#if defined(PRINTF_SUPPORT_PTRDIFF_T) - case 't': - flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; -#endif - case 'j': - flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; - case 'z': - flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; - default: - break; - } - - // evaluate specifier - switch (*format) { - case 'd': - case 'i': - case 'u': - case 'x': - case 'X': - case 'o': - case 'b': { - // set the base - unsigned int base; - if (*format == 'x' || *format == 'X') { - base = 16U; - } else if (*format == 'o') { - base = 8U; - } else if (*format == 'b') { - base = 2U; - } else { - base = 10U; - flags &= ~FLAGS_HASH; // no hash for dec format - } - // uppercase - if (*format == 'X') { - flags |= FLAGS_UPPERCASE; - } - - // no plus or space flag for u, x, X, o, b - if ((*format != 'i') && (*format != 'd')) { - flags &= ~(FLAGS_PLUS | FLAGS_SPACE); - } - - // ignore '0' flag when precision is given - if (flags & FLAGS_PRECISION) { - flags &= ~FLAGS_ZEROPAD; - } - - // convert the integer - if ((*format == 'i') || (*format == 'd')) { - // signed - if (flags & FLAGS_LONG_LONG) { -#if defined(PRINTF_SUPPORT_LONG_LONG) - const long long value = va_arg(va, long long); - idx = _ntoa_long_long(out, buffer, idx, maxlen, - (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, - precision, width, flags); -#endif - } else if (flags & FLAGS_LONG) { - const long value = va_arg(va, long); - idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), - value < 0, base, precision, width, flags); - } else { - const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) - : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) - : va_arg(va, int); - idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), - value < 0, base, precision, width, flags); - } - } else { - // unsigned - if (flags & FLAGS_LONG_LONG) { -#if defined(PRINTF_SUPPORT_LONG_LONG) - idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, - precision, width, flags); -#endif - } else if (flags & FLAGS_LONG) { - idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, - width, flags); - } else { - const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) - : (flags & FLAGS_SHORT) - ? (unsigned short int)va_arg(va, unsigned int) - : va_arg(va, unsigned int); - idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); - } - } - format++; - break; - } -#if defined(PRINTF_SUPPORT_FLOAT) - case 'f': - case 'F': - if (*format == 'F') flags |= FLAGS_UPPERCASE; - idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); - format++; - break; -#if defined(PRINTF_SUPPORT_EXPONENTIAL) - case 'e': - case 'E': - case 'g': - case 'G': - if ((*format == 'g') || (*format == 'G')) flags |= FLAGS_ADAPT_EXP; - if ((*format == 'E') || (*format == 'G')) flags |= FLAGS_UPPERCASE; - idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); - format++; - break; -#endif // PRINTF_SUPPORT_EXPONENTIAL -#endif // PRINTF_SUPPORT_FLOAT - case 'c': { - unsigned int l = 1U; - // pre padding - if (!(flags & FLAGS_LEFT)) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - // char output - out((char)va_arg(va, int), buffer, idx++, maxlen); - // post padding - if (flags & FLAGS_LEFT) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - format++; - break; - } - - case 's': { - const char *p = va_arg(va, char *); - unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); - // pre padding - if (flags & FLAGS_PRECISION) { - l = (l < precision ? l : precision); - } - if (!(flags & FLAGS_LEFT)) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - // string output - while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { - out(*(p++), buffer, idx++, maxlen); - } - // post padding - if (flags & FLAGS_LEFT) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - format++; - break; - } - - case 'p': { - width = sizeof(void *) * 2U; - flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; -#if defined(PRINTF_SUPPORT_LONG_LONG) - const bool is_ll = sizeof(uintptr_t) == sizeof(long long); - if (is_ll) { - idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void *), false, 16U, - precision, width, flags); - } else { -#endif - idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void *)), false, - 16U, precision, width, flags); -#if defined(PRINTF_SUPPORT_LONG_LONG) - } -#endif - format++; - break; - } - - case '%': - out('%', buffer, idx++, maxlen); - format++; - break; - - default: - out(*format, buffer, idx++, maxlen); - format++; - break; - } - } - - // termination - out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); - - // return written chars without terminating \0 - return (int)idx; -} - -/////////////////////////////////////////////////////////////////////////////// - -int printf_(const char *format, ...) { - va_list va; - va_start(va, format); - char buffer[1]; - const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); - va_end(va); - return ret; -} - -int sprintf(char *buffer, const char *format, ...) { - va_list va; - va_start(va, format); - const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); - va_end(va); - return ret; -} - -int snprintf(char *buffer, size_t count, const char *format, ...) { - va_list va; - va_start(va, format); - const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); - va_end(va); - return ret; -} - -int vprintf_(const char *format, va_list va) { - char buffer[1]; - return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); -} - -int vsnprintf(char *buffer, size_t count, const char *format, va_list va) { - return _vsnprintf(_out_buffer, buffer, count, format, va); -} - -int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...) { - va_list va; - va_start(va, format); - const out_fct_wrap_type out_fct_wrap = {out, arg}; - const int ret = _vsnprintf(_out_fct, (char *)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); - va_end(va); - return ret; -} - -// Default PRINTF_BUFFER_SIZE -#ifndef CKB_C_STDLIB_PRINTF_BUFFER_SIZE -#define CKB_C_STDLIB_PRINTF_BUFFER_SIZE 2048 -#endif -// syscall -int ckb_debug(const char *s); - -int printf(const char *format, ...) { - static char buf[CKB_C_STDLIB_PRINTF_BUFFER_SIZE]; - va_list va; - va_start(va, format); - int ret = vsnprintf(buf, CKB_C_STDLIB_PRINTF_BUFFER_SIZE, format, va); - va_end(va); - ckb_debug(buf); - return ret; -} - -int ckb_printf(const char *format, ...) { - static char buf[CKB_C_STDLIB_PRINTF_BUFFER_SIZE]; - va_list va; - va_start(va, format); - int ret = vsnprintf(buf, CKB_C_STDLIB_PRINTF_BUFFER_SIZE, format, va); - va_end(va); - ckb_debug(buf); - return ret; -} - -int ckb_vprintf(const char *format, va_list va) { - static char buf[CKB_C_STDLIB_PRINTF_BUFFER_SIZE]; - int ret = vsnprintf(buf, CKB_C_STDLIB_PRINTF_BUFFER_SIZE, format, va); - ckb_debug(buf); - return ret; -} diff --git a/include/c-stdlib/src/stdio_impl.c b/include/c-stdlib/src/stdio_impl.c deleted file mode 100644 index c8da132..0000000 --- a/include/c-stdlib/src/stdio_impl.c +++ /dev/null @@ -1,343 +0,0 @@ -#include "../my_stdio.h" - -#include -#include - -FILE *stdin; -FILE *stdout; -FILE *stderr; - -int ckb_exit(signed char code); - -static int s_local_access_enabled = 0; -void enable_local_access(int b) { s_local_access_enabled = b; } - -static int s_fs_access_enabled = 0; -void enable_fs_access(int b) { s_fs_access_enabled = b; } -int fs_access_enabled() { return s_fs_access_enabled; } - -#define memory_barrier() asm volatile("fence" ::: "memory") - -static inline long __internal_syscall(long n, long _a0, long _a1, long _a2, long _a3, long _a4, long _a5) { - register long a0 asm("a0") = _a0; - register long a1 asm("a1") = _a1; - register long a2 asm("a2") = _a2; - register long a3 asm("a3") = _a3; - register long a4 asm("a4") = _a4; - register long a5 asm("a5") = _a5; - -#ifdef __riscv_32e - register long syscall_id asm("t0") = n; -#else - register long syscall_id asm("a7") = n; -#endif - - asm volatile("scall" : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(syscall_id)); - /* - * Syscalls might modify memory sent as pointer, adding a barrier here - * ensures gcc won't do incorrect optimization. - */ - memory_barrier(); - - return a0; -} - -#define ckb_syscall(n, a, b, c, d, e, f) \ - __internal_syscall(n, (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) - -#define NOT_IMPL(name) \ - do { \ - printf("The %s is not implemented in mocked_stdio.c ", #name); \ - ckb_exit(-1); \ - } while (0) - -FILE *allocfile() { - FILE *file = malloc(sizeof(FILE)); - file->file = 0; - file->offset = 0; - return file; -} - -void freefile(FILE *file) { - file->file->rc -= 1; - free((void *)file); -} - -int remove(const char *__filename) { - NOT_IMPL(remove); - return 0; -} - -int rename(const char *__old, const char *__new) { - NOT_IMPL(rename); - return 0; -} - -FILE *tmpfile(void) { - NOT_IMPL(tmpfile); - return 0; -} - -char *tmpnam(char *__s) { - NOT_IMPL(tmpnam); - return 0; -} - -char *tempnam(const char *__dir, const char *__pfx) { - NOT_IMPL(tempnam); - return 0; -} - -int fclose(FILE *stream) { - if (s_local_access_enabled) { - return ckb_syscall(9009, stream, 0, 0, 0, 0, 0); - } - if (!fs_access_enabled()) { - NOT_IMPL(fclose); - } - freefile(stream); - return 0; -} - -int fflush(FILE *__stream) { - NOT_IMPL(fflush); - return 0; -} - -FILE *fopen(const char *path, const char *mode) { - if (s_local_access_enabled) { - return (void *)ckb_syscall(9003, path, mode, 0, 0, 0, 0); - } - - if (!fs_access_enabled()) { - NOT_IMPL(fopen); - } - - FILE *file = allocfile(); - if (file == 0) { - return 0; - } - - int ret = ckb_get_file(path, &file->file); - if (ret != 0) { - return 0; - } - return file; -} - -FILE *freopen(const char *path, const char *mode, FILE *stream) { - if (s_local_access_enabled) { - return (void *)ckb_syscall(9004, path, mode, stream, 0, 0, 0); - } - NOT_IMPL(freopen); - return 0; -} - -void setbuf(FILE *__stream, char *__buf) { NOT_IMPL(setbuf); } - -int setvbuf(FILE *__stream, char *__buf, int __modes, size_t __n) { - NOT_IMPL(setvbuf); - return 0; -} - -int fprintf(FILE *__stream, const char *__format, ...) { - NOT_IMPL(fprintf); - return 0; -} - -int vfprintf(FILE *__s, const char *__format, ...) { - NOT_IMPL(vfprintf); - return 0; -} -int vsprintf(char *__s, const char *__format, ...) { - NOT_IMPL(vsprintf); - return 0; -} - -int fscanf(FILE *__stream, const char *__format, ...) { - NOT_IMPL(fscanf); - return 0; -} - -int scanf(const char *__format, ...) { - NOT_IMPL(scanf); - return 0; -} - -int sscanf(const char *__s, const char *__format, ...) { - NOT_IMPL(sscanf); - return 0; -}; - -int fgetc(FILE *stream) { - if (s_local_access_enabled) { - return ckb_syscall(9008, stream, 0, 0, 0, 0, 0); - } - if (!fs_access_enabled()) { - NOT_IMPL(fgetc); - } - if (stream == 0 || stream->file->rc == 0 || stream->offset == stream->file->size) { - return -1; // EOF - } - unsigned char *c = (unsigned char *)stream->file->content + stream->offset; - stream->offset++; - return *c; -} - -int getc(FILE *stream) { return fgetc(stream); } - -int getchar(void) { - NOT_IMPL(getchar); - return 0; -} - -int fputc(int __c, FILE *__stream) { - NOT_IMPL(fputc); - return 0; -} - -int putc(int __c, FILE *__stream) { - NOT_IMPL(putc); - return 0; -} - -int putchar(int __c) { - NOT_IMPL(putchar); - return 0; -} - -char *fgets(char *__s, int __n, FILE *__stream) { - NOT_IMPL(fgets); - return 0; -} - -char *gets(char *__s) { - NOT_IMPL(gets); - return 0; -} - -int getline(char **__lineptr, size_t *__n, FILE *__stream) { - NOT_IMPL(getline); - return 0; -} - -int fputs(const char *__s, FILE *__stream) { - NOT_IMPL(fputs); - return 0; -} - -int puts(const char *__s) { - NOT_IMPL(puts); - return 0; -} - -int ungetc(int __c, FILE *__stream) { - NOT_IMPL(ungetc); - return 0; -} - -int isvalidfile(FILE *stream) { - if (stream == 0 || stream->file->rc == 0) { - return 1; - } - return 0; -} - -void mustbevaildfile(FILE *stream) { - if (isvalidfile(stream) != 0) { - ckb_exit(1); - } -} - -size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream) { - if (s_local_access_enabled) { - return ckb_syscall(9005, ptr, size, nitems, stream, 0, 0); - } - if (!fs_access_enabled()) { - NOT_IMPL(fread); - } - mustbevaildfile(stream); - // TODO: How do we handle error here? - if (stream->offset == stream->file->size) { - return 0; - } - // TODO: handle the case size * nitems is greater than uint32_t max - // handle size * ntimes overflowing - uint32_t bytes_to_read = (uint32_t)size * (uint32_t)nitems; - if (bytes_to_read > stream->file->size - stream->offset) { - bytes_to_read = stream->file->size - stream->offset; - } - memcpy(ptr, stream->file->content + stream->offset, bytes_to_read); - stream->offset = stream->offset + bytes_to_read; - // The return value should be the number of items written to the ptr - uint32_t s = size; - return (bytes_to_read + s - 1) / s; -} - -size_t fwrite(const void *__ptr, size_t __size, size_t __n, FILE *__s) { - NOT_IMPL(fwrite); - return 0; -} - -int fseek(FILE *stream, long int offset, int whence) { - if (s_local_access_enabled) { - return ckb_syscall(9011, stream, offset, whence, 0, 0, 0); - } - NOT_IMPL(fseek); - return 0; -} - -long int ftell(FILE *stream) { - if (s_local_access_enabled) { - return ckb_syscall(9010, stream, 0, 0, 0, 0, 0); - } - NOT_IMPL(ftell); - return 0; -} - -void rewind(FILE *__stream) { NOT_IMPL(rewind); } - -void clearerr(FILE *__stream) { NOT_IMPL(clearerr); } - -int feof(FILE *stream) { - if (s_local_access_enabled) { - return ckb_syscall(9006, stream, 0, 0, 0, 0, 0); - } - if (!fs_access_enabled()) { - NOT_IMPL(feof); - } - if (stream->offset == stream->file->size) { - return 1; - } - return 0; -} - -int ferror(FILE *stream) { - if (s_local_access_enabled) { - return ckb_syscall(9007, stream, 0, 0, 0, 0, 0); - } - if (!fs_access_enabled()) { - NOT_IMPL(ferror); - } - if (stream == 0 || stream->file->rc == 0) { - return 1; - } - return 0; -} - -void perror(const char *__s) { NOT_IMPL(perror); } - -int fileno(FILE *__stream) { - NOT_IMPL(fileno); - return 0; -} - -FILE *popen(const char *__command, const char *__modes) { - NOT_IMPL(popen); - return 0; -} - -int pclose(FILE *__stream) { - NOT_IMPL(pclose); - return 0; -} diff --git a/include/c-stdlib/src/string_impl.c b/include/c-stdlib/src/string_impl.c deleted file mode 100644 index 7df2207..0000000 --- a/include/c-stdlib/src/string_impl.c +++ /dev/null @@ -1,740 +0,0 @@ -#include -#include "my_math.h" -#include "my_setjmp.h" -#include "my_locale.h" -#include -#include -#include -#include -#include - -int ckb_exit(int8_t code); - -#define CKB_SS (sizeof(size_t)) -#define CKB_ALIGN (sizeof(size_t) - 1) -#define CKB_ONES ((size_t)-1 / UCHAR_MAX) -#define CKB_HIGHS (CKB_ONES * (UCHAR_MAX / 2 + 1)) -#define CKB_HASZERO(x) (((x)-CKB_ONES) & ~(x)&CKB_HIGHS) - -void *memchr(const void *src, int c, size_t n) { - const unsigned char *s = src; - c = (unsigned char)c; -#ifdef __GNUC__ - for (; ((uintptr_t)s & CKB_ALIGN) && n && *s != c; s++, n--) - ; - if (n && *s != c) { - typedef size_t __attribute__((__may_alias__)) word; - const word *w; - size_t k = CKB_ONES * c; - for (w = (const void *)s; n >= CKB_SS && !CKB_HASZERO(*w ^ k); w++, n -= CKB_SS) - ; - s = (const void *)w; - } -#endif - for (; n && *s != c; s++, n--) - ; - return n ? (void *)s : 0; -} - -#define BITOP(a, b, op) ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 << ((size_t)(b) % (8 * sizeof *(a)))) - -char *__strchrnul(const char *s, int c) { - c = (unsigned char)c; - if (!c) return (char *)s + strlen(s); - - for (; *s && *(unsigned char *)s != c; s++) - ; - return (char *)s; -} - -char *strchr(const char *s, int c) { - char *r = __strchrnul(s, c); - return *(unsigned char *)r == (unsigned char)c ? r : 0; -} - -int strncmp(const char *_l, const char *_r, size_t n) { - const unsigned char *l = (void *)_l, *r = (void *)_r; - if (!n--) return 0; - for (; *l && *r && n && *l == *r; l++, r++, n--) - ; - return *l - *r; -} - -size_t strspn(const char *s, const char *c) { - const char *a = s; - size_t byteset[32 / sizeof(size_t)] = {0}; - - if (!c[0]) return 0; - if (!c[1]) { - for (; *s == *c; s++) - ; - return s - a; - } - - for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++) - ; - for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++) - ; - return s - a; -} - -size_t strcspn(const char *s, const char *c) { - const char *a = s; - size_t byteset[32 / sizeof(size_t)]; - - if (!c[0] || !c[1]) return __strchrnul(s, *c) - a; - - memset(byteset, 0, sizeof byteset); - for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++) - ; - for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++) - ; - return s - a; -} - -char *strpbrk(const char *s, const char *b) { - s += strcspn(s, b); - return *s ? (char *)s : 0; -} - -static char *twobyte_strstr(const unsigned char *h, const unsigned char *n) { - uint16_t nw = n[0] << 8 | n[1], hw = h[0] << 8 | h[1]; - for (h++; *h && hw != nw; hw = hw << 8 | *++h) - ; - return *h ? (char *)h - 1 : 0; -} - -static char *threebyte_strstr(const unsigned char *h, const unsigned char *n) { - uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8; - uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8; - for (h += 2; *h && hw != nw; hw = (hw | *++h) << 8) - ; - return *h ? (char *)h - 2 : 0; -} - -static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n) { - uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3]; - uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3]; - for (h += 3; *h && hw != nw; hw = hw << 8 | *++h) - ; - return *h ? (char *)h - 3 : 0; -} - -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#define BITOP(a, b, op) ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 << ((size_t)(b) % (8 * sizeof *(a)))) - -static char *twoway_strstr(const unsigned char *h, const unsigned char *n) { - const unsigned char *z; - size_t l, ip, jp, k, p, ms, p0, mem, mem0; - size_t byteset[32 / sizeof(size_t)] = {0}; - size_t shift[256]; - - /* Computing length of needle and fill shift table */ - for (l = 0; n[l] && h[l]; l++) BITOP(byteset, n[l], |=), shift[n[l]] = l + 1; - if (n[l]) return 0; /* hit the end of h */ - - /* Compute maximal suffix */ - ip = -1; - jp = 0; - k = p = 1; - while (jp + k < l) { - if (n[ip + k] == n[jp + k]) { - if (k == p) { - jp += p; - k = 1; - } else - k++; - } else if (n[ip + k] > n[jp + k]) { - jp += k; - k = 1; - p = jp - ip; - } else { - ip = jp++; - k = p = 1; - } - } - ms = ip; - p0 = p; - - /* And with the opposite comparison */ - ip = -1; - jp = 0; - k = p = 1; - while (jp + k < l) { - if (n[ip + k] == n[jp + k]) { - if (k == p) { - jp += p; - k = 1; - } else - k++; - } else if (n[ip + k] < n[jp + k]) { - jp += k; - k = 1; - p = jp - ip; - } else { - ip = jp++; - k = p = 1; - } - } - if (ip + 1 > ms + 1) - ms = ip; - else - p = p0; - - /* Periodic needle? */ - if (memcmp(n, n + p, ms + 1)) { - mem0 = 0; - p = MAX(ms, l - ms - 1) + 1; - } else - mem0 = l - p; - mem = 0; - - /* Initialize incremental end-of-haystack pointer */ - z = h; - - /* Search loop */ - for (;;) { - /* Update incremental end-of-haystack pointer */ - if (z - h < l) { - /* Fast estimate for MAX(l,63) */ - size_t grow = l | 63; - const unsigned char *z2 = memchr(z, 0, grow); - if (z2) { - z = z2; - if (z - h < l) return 0; - } else - z += grow; - } - - /* Check last byte first; advance by shift on mismatch */ - if (BITOP(byteset, h[l - 1], &)) { - k = l - shift[h[l - 1]]; - if (k) { - if (k < mem) k = mem; - h += k; - mem = 0; - continue; - } - } else { - h += l; - mem = 0; - continue; - } - - /* Compare right half */ - for (k = MAX(ms + 1, mem); n[k] && n[k] == h[k]; k++) - ; - if (n[k]) { - h += k - ms; - mem = 0; - continue; - } - /* Compare left half */ - for (k = ms + 1; k > mem && n[k - 1] == h[k - 1]; k--) - ; - if (k <= mem) return (char *)h; - h += p; - mem = mem0; - } -} - -char *strstr(const char *h, const char *n) { - /* Return immediately on empty needle */ - if (!n[0]) return (char *)h; - - /* Use faster algorithms for short needles */ - h = strchr(h, *n); - if (!h || !n[1]) return (char *)h; - if (!h[1]) return 0; - if (!n[2]) return twobyte_strstr((void *)h, (void *)n); - if (!h[2]) return 0; - if (!n[3]) return threebyte_strstr((void *)h, (void *)n); - if (!h[3]) return 0; - if (!n[4]) return fourbyte_strstr((void *)h, (void *)n); - - return twoway_strstr((void *)h, (void *)n); -} - -/* Copied from - * https://github.com/bminor/musl/blob/46d1c7801bb509e1097e8fadbaf359367fa4ef0b/src/setjmp/riscv64/setjmp.S - */ -/* We need to use inline asm for easier compilation, - * https://stackoverflow.com/a/42358235. */ -/* We need __attribute__((naked)) to remove prologue and epilogue, - * https://stackoverflow.com/a/42637729 */ -__attribute__((naked)) int setjmp(jmp_buf b) { - asm volatile( - "sd s0, 0(a0)\n" - "sd s1, 8(a0)\n" - "sd s2, 16(a0)\n" - "sd s3, 24(a0)\n" - "sd s4, 32(a0)\n" - "sd s5, 40(a0)\n" - "sd s6, 48(a0)\n" - "sd s7, 56(a0)\n" - "sd s8, 64(a0)\n" - "sd s9, 72(a0)\n" - "sd s10, 80(a0)\n" - "sd s11, 88(a0)\n" - "sd sp, 96(a0)\n" - "sd ra, 104(a0)\n" - "li a0, 0\n" - "ret\n"); -} - -__attribute__((naked)) void longjmp(jmp_buf b, int n) { - asm volatile( - "ld s0, 0(a0)\n" - "ld s1, 8(a0)\n" - "ld s2, 16(a0)\n" - "ld s3, 24(a0)\n" - "ld s4, 32(a0)\n" - "ld s5, 40(a0)\n" - "ld s6, 48(a0)\n" - "ld s7, 56(a0)\n" - "ld s8, 64(a0)\n" - "ld s9, 72(a0)\n" - "ld s10, 80(a0)\n" - "ld s11, 88(a0)\n" - "ld sp, 96(a0)\n" - "ld ra, 104(a0)\n" - "seqz a0, a1\n" - "add a0, a0, a1\n" - "ret\n"); -} - -__attribute__((naked)) void _longjmp(jmp_buf b, int n) { - asm volatile( - "ld s0, 0(a0)\n" - "ld s1, 8(a0)\n" - "ld s2, 16(a0)\n" - "ld s3, 24(a0)\n" - "ld s4, 32(a0)\n" - "ld s5, 40(a0)\n" - "ld s6, 48(a0)\n" - "ld s7, 56(a0)\n" - "ld s8, 64(a0)\n" - "ld s9, 72(a0)\n" - "ld s10, 80(a0)\n" - "ld s11, 88(a0)\n" - "ld sp, 96(a0)\n" - "ld ra, 104(a0)\n" - "seqz a0, a1\n" - "add a0, a0, a1\n" - "ret\n"); -} - -int strcoll(const char *l, const char *r) { return strcmp(l, r); } - -int *__errno_location(void) { - static int error = -1; - return &error; -} - -char *strerror(int e) { - static char *errorstr = "There is an error"; - return errorstr; -} - -int islower(int c) { return (unsigned)c - 'a' < 26; } - -int isupper(int c) { return (unsigned)c - 'A' < 26; } - -int tolower(int c) { - if (isupper(c)) return c | 32; - return c; -} - -int toupper(int c) { - if (islower(c)) return c & 0x5f; - return c; -} - -#define X(x) (((x) / 256 | (x)*256) % 65536) - -const unsigned short **__ctype_b_loc(void) { - static const unsigned short table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 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(0x200), X(0x200), X(0x200), X(0x200), - X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x320), X(0x220), X(0x220), X(0x220), X(0x220), X(0x200), - X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), - X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x160), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), - X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), - X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x4c0), - X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x8d5), X(0x8d5), X(0x8d5), X(0x8d5), X(0x8d5), - X(0x8d5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), - X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x4c0), - X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), - X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), - X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x4c0), X(0x4c0), - X(0x4c0), X(0x4c0), X(0x200), 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; - - static const unsigned short *const ptable = table + 128; - return (void *)&ptable; -} - -const int32_t **__ctype_toupper_loc(void) { - static const int32_t table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'A', 'B', 'C', 'D', 'E', - 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 91, - 92, 93, 94, 95, 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 123, 124, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; - - static const int32_t *const ptable = table + 128; - - return (void *)&ptable; -} - -const int32_t **__ctype_tolower_loc(void) { - static const int32_t table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'a', 'b', 'c', 'd', 'e', - 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 91, - 92, 93, 94, 95, 96, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', - 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 123, 124, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; - - static const int32_t *const ptable = table + 128; - - return (void *)&ptable; -} - -char *getenv(const char *name) { return 0; } - -int isspace(int c) { return c == ' ' || (unsigned)c - '\t' < 5; } - -// Copied from dietlibc -float strtof(const char *s, char **endptr) { - register const char *p = s; - register float value = 0.; - int sign = +1; - float factor; - unsigned int expo; - - while (isspace(*p)) p++; - - switch (*p) { - case '-': - sign = -1; /* fall through */ - case '+': - p++; - default: - break; - } - - while ((unsigned int)(*p - '0') < 10u) value = value * 10 + (*p++ - '0'); - - if (*p == '.') { - factor = 1.; - - p++; - while ((unsigned int)(*p - '0') < 10u) { - factor *= 0.1; - value += (*p++ - '0') * factor; - } - } - - if ((*p | 32) == 'e') { - expo = 0; - factor = 10.L; - - switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem - // 'E' folgenden MUSS. - case '-': - factor = 0.1; /* fall through */ - case '+': - p++; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - default: - value = 0.L; - p = s; - goto done; - } - - while ((unsigned int)(*p - '0') < 10u) expo = 10 * expo + (*p++ - '0'); - - while (1) { - if (expo & 1) value *= factor; - if ((expo >>= 1) == 0) break; - factor *= factor; - } - } - -done: - if (endptr != NULL) *endptr = (char *)p; - - return value * sign; -} - -// Convert char to an int in base `base`, -// `base` must be 10 or 16, return -1 on error. -int char2int(char ch, unsigned int base) { - if (ch >= '0' && ch <= '9') return ch - '0'; - if (base == 16) { - if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10; - if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10; - } - return -1; -} - -#define ldbltype long double -double strtod(const char *s, char **endptr) { - register const char *p = s; - register ldbltype value = 0.; - int sign = +1; - unsigned int base = 10; - ldbltype base_inverse = (ldbltype)1 / (ldbltype)base; - ldbltype factor; - unsigned int expo; - unsigned int has_digits = 0; - - while (isspace(*p)) p++; - - switch (*p) { - case '-': - sign = -1; /* fall through */ - case '+': - p++; - case '0': - p++; - if ((*p | 32) == 'x') { - base = 16; - base_inverse = (ldbltype)1 / (ldbltype)base; - p++; - } else { - p--; - } - default: - break; - } - - unsigned int current_value; - while ((current_value = char2int(*p, base)) != -1) { - p++; - value = value * base + current_value; - has_digits = 1; - } - - if (*p == '.') { - factor = 1.; - - p++; - while ((current_value = char2int(*p, base)) != -1) { - p++; - factor *= base_inverse; - value += current_value * factor; - has_digits = 1; - } - } - - if ((*p | 32) == 'e' && base == 10) { - expo = 0; - factor = 10.; - - switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem - // 'E' folgenden MUSS. - case '-': - factor = 0.1; /* fall through */ - case '+': - p++; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - default: - value = 0.; - p = s; - goto done; - } - - while ((unsigned int)(*p - '0') < 10u) expo = 10 * expo + (*p++ - '0'); - - while (1) { - if (expo & 1) value *= factor; - if ((expo >>= 1) == 0) break; - factor *= factor; - } - } - - if ((*p | 32) == 'p' && base == 16) { - // TODO: add specifier p support - // https://cplusplus.com/reference/cstdlib/strtod/ - // - A 0x or 0X prefix, then a sequence of hexadecimal digits (as in - // isxdigit) optionally containing a period which separates the whole - // and fractional number parts. Optionally followed by a power of 2 - // exponent (a p or P character followed by an optional sign and a - // sequence of hexadecimal digits). - } -done: - if (endptr != NULL) { - if (has_digits) { - *endptr = (char *)p; - } else { - *endptr = (char *)s; - } - } - - return value * sign; -} - -long double strtold(const char *s, char **endptr) { - register const char *p = s; - register long double value = 0.L; - int sign = +1; - long double factor; - unsigned int expo; - - while (isspace(*p)) p++; - - switch (*p) { - case '-': - sign = -1; /* fall through */ - case '+': - p++; - default: - break; - } - - while ((unsigned int)(*p - '0') < 10u) value = value * 10 + (*p++ - '0'); - - if (*p == '.') { - factor = 1.; - - p++; - while ((unsigned int)(*p - '0') < 10u) { - factor *= 0.1; - value += (*p++ - '0') * factor; - } - } - - if ((*p | 32) == 'e') { - expo = 0; - factor = 10.L; - - switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem - // 'E' folgenden MUSS. - case '-': - factor = 0.1; /* fall through */ - case '+': - p++; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - default: - value = 0.L; - p = s; - goto done; - } - - while ((unsigned int)(*p - '0') < 10u) expo = 10 * expo + (*p++ - '0'); - - while (1) { - if (expo & 1) value *= factor; - if ((expo >>= 1) == 0) break; - factor *= factor; - } - } - -done: - if (endptr != NULL) *endptr = (char *)p; - - return value * sign; -} - -void exit(int status) { ckb_exit(status); } -void abort(void) { ckb_exit(-1); } - -static void *__memrchr(const void *m, int c, size_t n) { - const unsigned char *s = m; - c = (unsigned char)c; - while (n--) - if (s[n] == c) return (void *)(s + n); - return 0; -} - -char *strrchr(char *s, int c) { return __memrchr(s, c, strlen(s) + 1); } - -char *strcat(char *dest, const char *src) { - strcpy(dest + strlen(dest), src); - return dest; -} diff --git a/include/ckb_cell_fs.c b/include/ckb_cell_fs.c index 6a3060e..06f726d 100644 --- a/include/ckb_cell_fs.c +++ b/include/ckb_cell_fs.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/quickjs/ckb_module.c b/quickjs/ckb_module.c index 73bf8e1..9ba6532 100644 --- a/quickjs/ckb_module.c +++ b/quickjs/ckb_module.c @@ -13,7 +13,7 @@ // argument 3: length (optional, default to full length) // argument 4: offset (optional, default to 0) // -#define NO_VALUE ((size_t)-1) +#define NO_VALUE ((size_t) - 1) enum SyscallErrorCode { SyscallErrorUnknown = 80, @@ -364,123 +364,6 @@ static int get_property(JSContext *ctx, JSValueConst *obj, const char *prop, int exit: return err; } -/* -ckb.spawn_cell -argument 1: code_hash, ArrayBuffer -argument 2: hash_type, int -argument 3: spawn_args, including: - content_length, optional, int - memory_limit, optional, int - offset, optional, int - length, optional, int - argument 4~n: arguments -return: object with - exit_code, int - content, ArrayBuffer -Example usage: -```javascript -let code_hash = new ArrayBuffer(32); -code_hash[0] = 0x01; -... -... -let hash_type = ckb.SCRIPT_HASH_TYPE_TYPE; -let spawn_args = { - content_length: 1024, - memory_limit: 8, - offset: 0, - length: 0, -}; -let arg1 = "hello"; -let arg2 = "world"; -let ret = ckb.spawn_cell(code_hash, hash_type, spawn_args, arg1, arg2, arg3); -let exit_code = ret.exit_code; -let content = ret.content; -``` -*/ -static JSValue syscall_spawn_cell(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { - int err = 0; - JSValue ret = JS_UNDEFINED; - const size_t argv_offset = 3; - size_t code_hash_len = 0; - uint32_t hash_type = 0; - int64_t content_length = 0; - int64_t memory_limit = 8; // default value - int64_t offset = 0; - int64_t length = 0; - const char *passed_argv[256] = {0}; - int8_t exit_code = 0; - uint8_t code_hash[32]; - - JSValue buffer = JS_GetTypedArrayBuffer(ctx, argv[0], NULL, NULL, NULL); - CHECK2(!JS_IsException(buffer), SyscallErrorArgument); - uint8_t *p = JS_GetArrayBuffer(ctx, &code_hash_len, buffer); - CHECK2(code_hash_len == 32 && p != NULL, -1); - memcpy(code_hash, p, 32); - - err = JS_ToUint32(ctx, &hash_type, argv[1]); - CHECK(err); - err = get_property(ctx, &argv[2], "content_length", &content_length); - CHECK(err); - err = get_property(ctx, &argv[2], "memory_limit", &memory_limit); - CHECK(err); - err = get_property(ctx, &argv[2], "offset", &offset); - CHECK(err); - err = get_property(ctx, &argv[2], "length", &length); - CHECK(err); - - for (int i = argv_offset; i < argc; i++) { - passed_argv[i - argv_offset] = JS_ToCString(ctx, argv[i]); - } - void *content = malloc(content_length); - CHECK2(content != NULL, SyscallErrorArgument); - spawn_args_t spgs = { - .memory_limit = memory_limit, - .exit_code = &exit_code, - .content = content, - .content_length = (uint64_t *)&content_length, - }; - err = ckb_spawn_cell(code_hash, (uint8_t)hash_type, offset, length, argc - argv_offset, passed_argv, &spgs); - CHECK(err); - ret = JS_NewObject(ctx); - CHECK2(!JS_IsException(ret), SyscallErrorMemory); - JS_DefinePropertyValueStr(ctx, ret, "exit_code", JS_NewUint32(ctx, (uint32_t)exit_code), JS_PROP_C_W_E); - JSValue content2 = JS_NewArrayBuffer(ctx, spgs.content, *spgs.content_length, my_free, spgs.content, false); - JS_DefinePropertyValueStr(ctx, ret, "content", content2, JS_PROP_C_W_E); -exit: - if (err != 0) { - return JS_EXCEPTION; - } else { - return ret; - } -} - -static JSValue syscall_set_content(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { - int err = 0; - size_t content_length = 0; - JSValue buffer = JS_GetTypedArrayBuffer(ctx, argv[0], NULL, NULL, NULL); - CHECK2(!JS_IsException(buffer), SyscallErrorArgument); - uint8_t *content = JS_GetArrayBuffer(ctx, &content_length, buffer); - CHECK2(content != NULL, SyscallErrorUnknown); - uint64_t content_length2 = (uint64_t)content_length; - err = ckb_set_content(content, &content_length2); - CHECK(err); -exit: - if (err != 0) { - return JS_EXCEPTION; - } else { - return JS_UNDEFINED; - } -} - -static JSValue syscall_get_memory_limit(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { - int memory_limit = ckb_get_memory_limit(); - return JS_NewUint32(ctx, (uint32_t)memory_limit); -} - -static JSValue syscall_current_memory(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { - int size = ckb_current_memory(); - return JS_NewUint32(ctx, (uint32_t)size); -} static JSValue mount(JSContext *ctx, JSValueConst this_value, int argc, JSValueConst *argv) { JSValue buf = syscall_load_cell_data(ctx, this_value, argc, argv); @@ -533,11 +416,6 @@ int js_init_module_ckb(JSContext *ctx) { JS_SetPropertyStr(ctx, ckb, "vm_version", JS_NewCFunction(ctx, syscall_vm_version, "vm_version", 0)); JS_SetPropertyStr(ctx, ckb, "current_cycles", JS_NewCFunction(ctx, syscall_current_cycles, "current_cycles", 0)); JS_SetPropertyStr(ctx, ckb, "exec_cell", JS_NewCFunction(ctx, syscall_exec_cell, "exec_cell", 4)); - JS_SetPropertyStr(ctx, ckb, "spawn_cell", JS_NewCFunction(ctx, syscall_spawn_cell, "spawn_cell", 3)); - JS_SetPropertyStr(ctx, ckb, "set_content", JS_NewCFunction(ctx, syscall_set_content, "set_content", 1)); - JS_SetPropertyStr(ctx, ckb, "get_memory_limit", - JS_NewCFunction(ctx, syscall_get_memory_limit, "get_memory_limit", 0)); - JS_SetPropertyStr(ctx, ckb, "current_memory", JS_NewCFunction(ctx, syscall_current_memory, "current_memory", 0)); JS_SetPropertyStr(ctx, ckb, "mount", JS_NewCFunction(ctx, mount, "mount", 2)); JS_SetPropertyStr(ctx, ckb, "SOURCE_INPUT", JS_NewInt64(ctx, CKB_SOURCE_INPUT)); JS_SetPropertyStr(ctx, ckb, "SOURCE_OUTPUT", JS_NewInt64(ctx, CKB_SOURCE_OUTPUT)); @@ -577,7 +455,7 @@ int js_init_module_ckb(JSContext *ctx) { #define JS_LOADER_ARGS_SIZE 2 #define BLAKE2B_BLOCK_SIZE 32 -int load_cell_code_info_explicit(size_t *buf_size, size_t *index, const uint8_t* code_hash, uint8_t hash_type) { +int load_cell_code_info_explicit(size_t *buf_size, size_t *index, const uint8_t *code_hash, uint8_t hash_type) { int err = 0; *index = 0; err = ckb_look_for_dep_with_hash2(code_hash, hash_type, index); diff --git a/quickjs/ckb_module.h b/quickjs/ckb_module.h index cad861b..f91c81f 100644 --- a/quickjs/ckb_module.h +++ b/quickjs/ckb_module.h @@ -10,7 +10,7 @@ int js_init_module_ckb(JSContext *ctx); int read_local_file(char *buf, int size); -int load_cell_code_info_explicit(size_t *buf_size, size_t *index, const uint8_t* code_hash, uint8_t hash_type); +int load_cell_code_info_explicit(size_t *buf_size, size_t *index, const uint8_t *code_hash, uint8_t hash_type); int load_cell_code_info(size_t *buf_size, size_t *index); int load_cell_code(size_t buf_size, size_t index, uint8_t *buf); diff --git a/quickjs/cmdopt.c b/quickjs/cmdopt.c index bcfc20c..eb9d128 100644 --- a/quickjs/cmdopt.c +++ b/quickjs/cmdopt.c @@ -26,13 +26,10 @@ * THE SOFTWARE. */ #include -#include "my_stdlib.h" #include -#include "my_stdio.h" #include #include -#include "my_string.h" -#include "my_assert.h" +#include #include "cmdopt.h" typedef struct { @@ -51,14 +48,13 @@ struct CMDOption { static const char *cmd_prog_name; -int ckb_vprintf(const char *format, va_list va); void cmd_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); printf("%s:", cmd_prog_name); - ckb_vprintf(fmt, ap); + vprintf(fmt, ap); exit(1); } diff --git a/quickjs/cutils.c b/quickjs/cutils.c index 95ddd2a..b4960f9 100644 --- a/quickjs/cutils.c +++ b/quickjs/cutils.c @@ -1,6 +1,6 @@ /* * C utilities - * + * * Copyright (c) 2017 Fabrice Bellard * Copyright (c) 2018 Charlie Gordon * @@ -23,12 +23,9 @@ * THE SOFTWARE. */ #include -#include "my_stdlib.h" #include -#include "my_stdio.h" #include #include -#include "my_string.h" #include "cutils.h" @@ -175,7 +172,7 @@ int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, va_list ap; char buf[128]; int len; - + va_start(ap, fmt); len = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); diff --git a/quickjs/cutils.h b/quickjs/cutils.h index 5eecd95..eefb8a8 100644 --- a/quickjs/cutils.h +++ b/quickjs/cutils.h @@ -1,6 +1,6 @@ /* * C utilities - * + * * Copyright (c) 2017 Fabrice Bellard * Copyright (c) 2018 Charlie Gordon * @@ -26,7 +26,7 @@ #define CUTILS_H #include -// #include +#include /* set if CPU is big endian */ #undef WORDS_BIGENDIAN @@ -220,13 +220,13 @@ static inline uint32_t bswap32(uint32_t v) 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)) | + 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)); } @@ -298,7 +298,7 @@ void rqsort(void *base, size_t nmemb, size_t size, do { \ if (!(cond)) { \ err = code; \ - printf("checking failed on %s:%d, code = %d", __FILE__, __LINE__, code); \ + printf("checking failed on %s:%d, code = %d\n", __FILE__, __LINE__, code); \ goto exit; \ } \ } while (0) @@ -308,7 +308,7 @@ void rqsort(void *base, size_t nmemb, size_t size, int code = (_code); \ if (code != 0) { \ err = code; \ - printf("checking failed on %s:%d, code = %d", __FILE__, __LINE__, code); \ + printf("checking failed on %s:%d, code = %d\n", __FILE__, __LINE__, code); \ goto exit; \ } \ } while (0) diff --git a/quickjs/libbf.c b/quickjs/libbf.c index d9601bf..c1c0ac2 100644 --- a/quickjs/libbf.c +++ b/quickjs/libbf.c @@ -1,6 +1,6 @@ /* * 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 @@ -22,14 +22,12 @@ * THE SOFTWARE. */ #include -#include "my_stdlib.h" #include #include -#include "my_stdint.h" -#include "my_inttypes.h" -#include +#include +#include #include -#include +#include #ifdef __AVX2__ #include @@ -58,8 +56,8 @@ #define UDIV1NORM_THRESHOLD 3 #if LIMB_BITS == 64 -#define FMT_LIMB1 "%" PRIx64 -#define FMT_LIMB "%016" PRIx64 +#define FMT_LIMB1 "%" PRIx64 +#define FMT_LIMB "%016" PRIx64 #define PRId_LIMB PRId64 #define PRIu_LIMB PRIu64 @@ -197,7 +195,7 @@ void bf_init(bf_context_t *s, bf_t *r) int bf_resize(bf_t *r, limb_t len) { limb_t *tab; - + if (len != r->len) { tab = bf_realloc(r->ctx, r->tab, len * sizeof(limb_t)); if (!tab && len != 0) @@ -215,7 +213,7 @@ int bf_set_ui(bf_t *r, uint64_t a) if (a == 0) { r->expn = BF_EXP_ZERO; bf_resize(r, 0); /* cannot fail */ - } + } #if LIMB_BITS == 32 else if (a <= 0xffffffff) #else @@ -377,7 +375,7 @@ static inline limb_t scan_bit_nz(const bf_t *r, slimb_t bit_pos) { slimb_t pos; limb_t v; - + pos = bit_pos >> LIMB_LOG2_BITS; if (pos < 0) return 0; @@ -400,7 +398,7 @@ static int bf_get_rnd_add(int *pret, const bf_t *r, limb_t l, { int add_one, inexact; limb_t bit1, bit0; - + if (rnd_mode == BF_RNDF) { bit0 = 1; /* faithful rounding does not honor the INEXACT flag */ } else { @@ -411,7 +409,7 @@ static int bf_get_rnd_add(int *pret, const bf_t *r, limb_t l, /* get the bit at 'prec' */ bit1 = get_bit(r->tab, l, l * LIMB_BITS - 1 - prec); inexact = (bit1 | bit0) != 0; - + add_one = 0; switch(rnd_mode) { case BF_RNDZ: @@ -442,7 +440,7 @@ static int bf_get_rnd_add(int *pret, const bf_t *r, limb_t l, default: abort(); } - + if (inexact) *pret |= BF_ST_INEXACT; return add_one; @@ -452,7 +450,7 @@ static int bf_set_overflow(bf_t *r, int sign, limb_t prec, bf_flags_t flags) { slimb_t i, l, e_max; int rnd_mode; - + rnd_mode = flags & BF_RND_MASK; if (prec == BF_PREC_INF || rnd_mode == BF_RNDN || @@ -495,7 +493,7 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, e_range = (limb_t)1 << (bf_get_exp_bits(flags) - 1); e_min = -e_range + 3; e_max = e_range; - + if (flags & BF_FLAG_RADPNT_PREC) { /* 'prec' is the precision after the radix point */ if (prec1 != BF_PREC_INF) @@ -514,7 +512,7 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, /* round to prec bits */ rnd_mode = flags & BF_RND_MASK; add_one = bf_get_rnd_add(&ret, r, l, prec, rnd_mode); - + if (prec <= 0) { if (add_one) { bf_resize(r, 1); /* cannot fail */ @@ -527,12 +525,12 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, } } else if (add_one) { limb_t carry; - + /* add one starting at digit 'prec - 1' */ bit_pos = l * LIMB_BITS - 1 - (prec - 1); pos = bit_pos >> LIMB_LOG2_BITS; carry = (limb_t)1 << (bit_pos & (LIMB_BITS - 1)); - + for(i = pos; i < l; i++) { v = r->tab[i] + carry; carry = (v < carry); @@ -551,7 +549,7 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, r->expn++; } } - + /* check underflow */ if (unlikely(r->expn < e_min)) { if (flags & BF_FLAG_SUBNORMAL) { @@ -565,11 +563,11 @@ static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l, return ret; } } - + /* check overflow */ if (unlikely(r->expn > e_max)) return bf_set_overflow(r, r->sign, prec1, flags); - + /* keep the bits starting at 'prec - 1' */ bit_pos = l * LIMB_BITS - 1 - (prec - 1); i = bit_pos >> LIMB_LOG2_BITS; @@ -597,7 +595,7 @@ int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags) limb_t l, v, a; int shift, ret; slimb_t i; - + // bf_print_str("bf_renorm", r); l = r->len; while (l > 0 && r->tab[l - 1] == 0) @@ -636,7 +634,7 @@ int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k) BOOL is_rndn; slimb_t bit_pos, n; limb_t bit; - + if (a->expn == BF_EXP_INF || a->expn == BF_EXP_NAN) return FALSE; if (rnd_mode == BF_RNDF) { @@ -650,7 +648,7 @@ int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k) bit_pos = a->len * LIMB_BITS - 1 - prec; n = k - prec; /* bit pattern for RNDN or RNDNA: 0111.. or 1000... - for other rounding modes: 000... or 111... + for other rounding modes: 000... or 111... */ bit = get_bit(a->tab, a->len, bit_pos); bit_pos--; @@ -743,7 +741,7 @@ int bf_cmpu(const bf_t *a, const bf_t *b) { slimb_t i; limb_t len, v1, v2; - + if (a->expn != b->expn) { if (a->expn < b->expn) return -1; @@ -768,7 +766,7 @@ int bf_cmpu(const bf_t *a, const bf_t *b) int bf_cmp_full(const bf_t *a, const bf_t *b) { int res; - + if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { if (a->expn == b->expn) res = 0; @@ -792,7 +790,7 @@ int bf_cmp_full(const bf_t *a, const bf_t *b) int bf_cmp(const bf_t *a, const bf_t *b) { int res; - + if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { res = 2; } else if (a->sign != b->sign) { @@ -811,7 +809,7 @@ int bf_cmp(const bf_t *a, const bf_t *b) /* Compute the number of bits 'n' matching the pattern: a= X1000..0 b= X0111..1 - + When computing a-b, the result will have at least n leading zero bits. @@ -926,7 +924,7 @@ static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, } else { cancelled_bits = 0; } - + /* add two extra bits for rounding */ precl = (cancelled_bits + prec + 2 + LIMB_BITS - 1) / LIMB_BITS; tot_len = bf_max(a->len, b->len + (d + LIMB_BITS - 1) / LIMB_BITS); @@ -944,7 +942,7 @@ static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, while (i < 0) { slimb_t ap, bp; BOOL inflag; - + ap = a_offset + i; bp = b_bit_offset + i * LIMB_BITS; inflag = FALSE; @@ -968,7 +966,7 @@ static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, if (ap < 0) i = bf_min(i, -a_offset); /* b_bit_offset + i * LIMB_BITS + LIMB_BITS >= 1 - equivalent to + equivalent to i >= ceil(-b_bit_offset + 1 - LIMB_BITS) / LIMB_BITS) */ if (bp + LIMB_BITS <= 0) @@ -1025,12 +1023,12 @@ static int __bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, return bf_add_internal(r, a, b, prec, flags, 1); } -limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2, +limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2, limb_t n, limb_t carry) { slimb_t i; limb_t k, a, v, k1; - + k = carry; for(i=0;i> shift. Return the remainder r (0 <= r < 2^shift). +/* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift). 1 <= shift <= LIMB_BITS - 1 */ -static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n, +static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n, int shift, limb_t high) { mp_size_t i; @@ -1131,7 +1129,7 @@ static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n, } /* tabr[] = taba[] * b + l. Return the high carry */ -static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n, +static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n, limb_t b, limb_t l) { limb_t i; @@ -1151,7 +1149,7 @@ static limb_t mp_add_mul1(limb_t *tabr, const limb_t *taba, limb_t n, { limb_t i, l; dlimb_t t; - + l = 0; for(i = 0; i < n; i++) { t = (dlimb_t)taba[i] * (dlimb_t)b + l + tabr[i]; @@ -1162,12 +1160,12 @@ static limb_t mp_add_mul1(limb_t *tabr, const limb_t *taba, limb_t n, } /* size of the result : op1_size + op2_size. */ -static void mp_mul_basecase(limb_t *result, - const limb_t *op1, limb_t op1_size, - const limb_t *op2, limb_t op2_size) +static void mp_mul_basecase(limb_t *result, + const limb_t *op1, limb_t op1_size, + const limb_t *op2, limb_t op2_size) { limb_t i, r; - + result[op1_size] = mp_mul1(result, op1, op1_size, op2[0], 0); for(i=1;i= FFT_MUL_THRESHOLD)) { @@ -1204,7 +1202,7 @@ static limb_t mp_sub_mul1(limb_t *tabr, const limb_t *taba, limb_t n, { limb_t i, l; dlimb_t t; - + l = 0; for(i = 0; i < n; i++) { t = tabr[i] - (dlimb_t)taba[i] * (dlimb_t)b - l; @@ -1268,15 +1266,15 @@ static limb_t mp_div1norm(limb_t *tabr, const limb_t *taba, limb_t n, return r; } -static int mp_divnorm_large(bf_context_t *s, - limb_t *tabq, limb_t *taba, limb_t na, +static int mp_divnorm_large(bf_context_t *s, + limb_t *tabq, limb_t *taba, limb_t na, const limb_t *tabb, limb_t nb); /* base case division: divides taba[0..na-1] by tabb[0..nb-1]. tabb[nb - 1] must be >= 1 << (LIMB_BITS - 1). na - nb must be >= 0. 'taba' is modified and contains the remainder (nb limbs). tabq[0..na-nb] contains the quotient with tabq[na - nb] <= 1. */ -static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, +static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, const limb_t *tabb, limb_t nb) { limb_t r, a, c, q, v, b1, b1_inv, n, dummy_r; @@ -1291,7 +1289,7 @@ static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, if (bf_min(n, nb) >= DIVNORM_LARGE_THRESHOLD) { return mp_divnorm_large(s, tabq, taba, na, tabb, nb); } - + if (n >= UDIV1NORM_THRESHOLD) b1_inv = udiv1norm_init(b1); else @@ -1310,7 +1308,7 @@ static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, if (q) { mp_sub(taba + n, taba + n, tabb, nb, 0); } - + for(i = n - 1; i >= 0; i--) { if (unlikely(taba[i + nb] >= b1)) { q = -1; @@ -1349,14 +1347,14 @@ static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na, /* compute r=B^(2*n)/a such as a*r < B^(2*n) < a*r + 2 with n >= 1. 'a' has n limbs with a[n-1] >= B/2 and 'r' has n+1 limbs with r[n] = 1. - + See Modern Computer Arithmetic by Richard P. Brent and Paul Zimmermann, algorithm 3.5 */ int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n) { mp_size_t l, h, k, i; limb_t *tabxh, *tabt, c, *tabu; - + if (n <= 2) { /* return ceil(B^(2*n)/a) - 1 */ /* XXX: could avoid allocation */ @@ -1434,8 +1432,8 @@ static int mp_cmp(const limb_t *taba, const limb_t *tabb, mp_size_t n) //#define DEBUG_DIVNORM_LARGE2 /* subquadratic divnorm */ -static int mp_divnorm_large(bf_context_t *s, - limb_t *tabq, limb_t *taba, limb_t na, +static int mp_divnorm_large(bf_context_t *s, + limb_t *tabq, limb_t *taba, limb_t na, const limb_t *tabb, limb_t nb) { limb_t *tabb_inv, nq, *tabt, i, n; @@ -1448,7 +1446,7 @@ static int mp_divnorm_large(bf_context_t *s, assert(nq >= 1); n = nq; if (nq < nb) - n++; + n++; tabb_inv = bf_malloc(s, sizeof(limb_t) * (n + 1)); tabt = bf_malloc(s, sizeof(limb_t) * 2 * (n + 1)); if (!tabb_inv || !tabt) @@ -1477,7 +1475,7 @@ static int mp_divnorm_large(bf_context_t *s, /* Q=A*B^-1 */ if (mp_mul(s, tabt, tabb_inv, n + 1, taba + na - (n + 1), n + 1)) goto fail; - + for(i = 0; i < nq + 1; i++) tabq[i] = tabt[i + 2 * (n + 1) - (nq + 1)]; #ifdef DEBUG_DIVNORM_LARGE @@ -1487,7 +1485,7 @@ static int mp_divnorm_large(bf_context_t *s, bf_free(s, tabt); bf_free(s, tabb_inv); tabb_inv = NULL; - + /* R=A-B*Q */ tabt = bf_malloc(s, sizeof(limb_t) * (na + 1)); if (!tabt) @@ -1558,10 +1556,10 @@ int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_t tmp, *r1 = NULL; limb_t a_len, b_len, precl; limb_t *a_tab, *b_tab; - + a_len = a->len; b_len = b->len; - + if ((flags & BF_RND_MASK) == BF_RNDF) { /* faithful rounding does not require using the full inputs */ precl = (prec + 2 + LIMB_BITS - 1) / LIMB_BITS; @@ -1570,7 +1568,7 @@ int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, } a_tab = a->tab + a->len - a_len; b_tab = b->tab + b->len - b_len; - + #ifdef USE_FFT_MUL if (b_len >= FFT_MUL_THRESHOLD) { int mul_flags = 0; @@ -1626,7 +1624,7 @@ slimb_t bf_get_exp_min(const bf_t *a) slimb_t i; limb_t v; int k; - + for(i = 0; i < a->len; i++) { v = a->tab[i]; if (v != 0) { @@ -1659,7 +1657,7 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_context_t *s = r->ctx; int ret, r_sign; limb_t n, nb, precl; - + r_sign = a->sign ^ b->sign; if (a->expn >= BF_EXP_INF || b->expn >= BF_EXP_INF) { if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { @@ -1692,11 +1690,11 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, precl = (prec + 2 + LIMB_BITS - 1) / LIMB_BITS; nb = b->len; n = bf_max(a->len, precl); - + { limb_t *taba, na; slimb_t d; - + na = n + nb; taba = bf_malloc(s, (na + 1) * sizeof(limb_t)); if (!taba) @@ -1725,8 +1723,8 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, return BF_ST_MEM_ERROR; } -/* division and remainder. - +/* division and remainder. + rnd_mode is the rounding mode for the quotient. The additional rounding mode BF_RND_EUCLIDIAN is supported. @@ -1740,11 +1738,11 @@ int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b, bf_t b1_s, *b1 = &b1_s; int q_sign, ret; BOOL is_ceil, is_rndn; - + assert(q != a && q != b); assert(r != a && r != b); assert(q != r); - + if (a->len == 0 || b->len == 0) { bf_set_zero(q, 0); if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { @@ -1786,7 +1784,7 @@ int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b, a1->tab = a->tab; a1->len = a->len; a1->sign = 0; - + b1->expn = b->expn; b1->tab = b->tab; b1->len = b->len; @@ -1832,7 +1830,7 @@ int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, { bf_t q_s, *q = &q_s; int ret; - + bf_init(r->ctx, q); ret = bf_divrem(q, r, a, b, prec, flags, rnd_mode); bf_delete(q); @@ -1853,7 +1851,7 @@ int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, { bf_t q_s, *q = &q_s; int ret; - + bf_init(r->ctx, q); ret = bf_divrem(q, r, a, b, prec, flags, rnd_mode); bf_get_limb(pq, q, BF_GET_INT_MOD); @@ -1891,7 +1889,7 @@ static const uint16_t sqrt_table[192] = { static limb_t mp_sqrtrem1(limb_t *pr, limb_t a) { limb_t s1, r1, s, r, q, u, num; - + /* use a table for the 16 -> 8 bit sqrt */ s1 = sqrt_table[(a >> (LIMB_BITS - 8)) - 64]; r1 = (a >> (LIMB_BITS - 16)) - s1 * s1; @@ -1899,7 +1897,7 @@ static limb_t mp_sqrtrem1(limb_t *pr, limb_t a) r1 -= 2 * s1 + 1; s1++; } - + /* one iteration to get a 32 -> 16 bit sqrt */ num = (r1 << 8) | ((a >> (LIMB_BITS - 32 + 8)) & 0xff); q = num / (2 * s1); /* q <= 2^8 */ @@ -1981,7 +1979,7 @@ static int mp_sqrtrem_rec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n, limb_t *tmp_buf, limb_t *prh) { limb_t l, h, rh, ql, qh, c, i; - + if (n == 1) { *prh = mp_sqrtrem2(tabs, taba); return 0; @@ -1998,7 +1996,7 @@ static int mp_sqrtrem_rec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n, mp_print_str_h("r1", taba + 2 * l, h, qh); mp_print_str_h("r2", taba + l, n, qh); #endif - + /* the remainder is in taba + 2 * l. Its high bit is in qh */ if (qh) { mp_sub(taba + 2 * l, taba + 2 * l, tabs + l, h, 0); @@ -2020,12 +2018,12 @@ static int mp_sqrtrem_rec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n, mp_print_str_h("q", tabs, l, qh); mp_print_str_h("u", taba + l, h, rh); #endif - + mp_add_ui(tabs + l, qh, h); #ifdef DEBUG_SQRTREM mp_print_str_h("s2", tabs, n, sh); #endif - + /* q = qh, tabs[l - 1 ... 0], r = taba[n - 1 ... l] */ /* subtract q^2. if qh = 1 then q = B^l, so we can take shortcuts */ if (qh) { @@ -2077,7 +2075,7 @@ int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n) int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a) { int ret; - + if (a->len == 0) { if (a->expn == BF_EXP_NAN) { bf_set_nan(r); @@ -2097,7 +2095,7 @@ int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a) ret = BF_ST_INVALID_OP; } else { bf_t rem_s, *rem; - + bf_sqrt(r, a, (a->expn + 1) / 2, BF_RNDZ); bf_rint(r, BF_RNDZ); /* see if the result is exact by computing the remainder */ @@ -2151,7 +2149,7 @@ int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) limb_t *a1; slimb_t n, n1; limb_t res; - + /* convert the mantissa to an integer with at least 2 * prec + 4 bits */ n = (2 * (prec + 2) + 2 * LIMB_BITS - 1) / (2 * LIMB_BITS); @@ -2196,7 +2194,7 @@ static no_inline int bf_op2(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, { bf_t tmp; int ret; - + if (r == a || r == b) { bf_init(r->ctx, &tmp); ret = func(&tmp, a, b, prec, flags); @@ -2254,7 +2252,7 @@ int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, { bf_t b; int ret; - + bf_init(r->ctx, &b); ret = bf_set_si(&b, b1); ret |= bf_add(r, a, &b, prec, flags); @@ -2266,7 +2264,7 @@ static int bf_pow_ui(bf_t *r, const bf_t *a, limb_t b, limb_t prec, bf_flags_t flags) { int ret, n_bits, i; - + assert(r != a); if (b == 0) return bf_set_ui(r, 1); @@ -2285,7 +2283,7 @@ static int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b, { bf_t a; int ret; - + if (a1 == 10 && b <= LIMB_DIGITS) { /* use precomputed powers. We do not round at this point because we expect the caller to do it */ @@ -2330,7 +2328,7 @@ static int bf_logic_op(bf_t *r, const bf_t *a1, const bf_t *b1, int op) slimb_t l, i, a_bit_offset, b_bit_offset; limb_t v1, v2, v1_mask, v2_mask, r_mask; int ret; - + assert(r != a1 && r != b1); if (a1->expn <= 0) @@ -2342,7 +2340,7 @@ static int bf_logic_op(bf_t *r, const bf_t *a1, const bf_t *b1, int op) b_sign = 0; /* minus zero is considered as positive */ else b_sign = b1->sign; - + if (a_sign) { a = &a1_s; bf_init(r->ctx, a); @@ -2362,7 +2360,7 @@ static int bf_logic_op(bf_t *r, const bf_t *a1, const bf_t *b1, int op) } else { b = (bf_t *)b1; } - + r_sign = bf_logic_op1(a_sign, b_sign, op); if (op == BF_LOGIC_AND && r_sign == 0) { /* no need to compute extra zeros for and */ @@ -2439,13 +2437,13 @@ int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode) Float64Union u; int e, ret; uint64_t m; - + ret = 0; if (a->expn == BF_EXP_NAN) { u.u = 0x7ff8000000000000; /* quiet nan */ } else { bf_t b_s, *b = &b_s; - + bf_init(a->ctx, b); bf_set(b, a); if (bf_is_finite(b)) { @@ -2488,7 +2486,7 @@ int bf_set_float64(bf_t *a, double d) Float64Union u; uint64_t m; int shift, e, sgn; - + u.d = d; sgn = u.u >> 63; e = (u.u >> 52) & ((1 << 11) - 1); @@ -2559,7 +2557,7 @@ int bf_get_int32(int *pres, const bf_t *a, int flags) ret = BF_ST_INVALID_OP; if (a->sign) { v = (uint32_t)INT32_MAX + 1; - if (a->expn == 32 && + if (a->expn == 32 && (a->tab[a->len - 1] >> (LIMB_BITS - 32)) == v) { ret = 0; } @@ -2567,7 +2565,7 @@ int bf_get_int32(int *pres, const bf_t *a, int flags) v = INT32_MAX; } } else { - v = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn); + v = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn); if (a->sign) v = -v; ret = 0; @@ -2625,7 +2623,7 @@ int bf_get_int64(int64_t *pres, const bf_t *a, int flags) } } else { slimb_t bit_pos = a->len * LIMB_BITS - a->expn; - v = get_bits(a->tab, a->len, bit_pos); + v = get_bits(a->tab, a->len, bit_pos); #if LIMB_BITS == 32 v |= (uint64_t)get_bits(a->tab, a->len, bit_pos + 32) << 32; #endif @@ -2685,7 +2683,7 @@ static limb_t get_limb_radix(int radix) { int i, k; limb_t radixl; - + k = digits_per_limb_table[radix - 2]; radixl = radix; for(i = 1; i < k; i++) @@ -2704,7 +2702,7 @@ static int bf_integer_from_radix_rec(bf_t *r, const limb_t *tab, } else { bf_t T_s, *T = &T_s, *B; limb_t n1, n2; - + n2 = (((n0 * 2) >> (level + 1)) + 1) / 2; n1 = n - n2; // printf("level=%d n0=%ld n1=%ld n2=%ld\n", level, n0, n1, n2); @@ -2740,7 +2738,7 @@ static int bf_integer_from_radix(bf_t *r, const limb_t *tab, int pow_tab_len, i, ret; limb_t radixl; bf_t *pow_tab; - + radixl = get_limb_radix(radix); pow_tab_len = ceil_log2(n) + 2; /* XXX: check */ pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len); @@ -2889,7 +2887,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, slimb_t pos, expn, int_len, digit_count; BOOL has_decpt, is_bin_exp; bf_t a_s, *a; - + *pexponent = 0; p = str; if (!(flags & BF_ATOF_NO_NAN_INF) && radix <= 16 && @@ -2899,7 +2897,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, goto done; } is_neg = 0; - + if (p[0] == '+') { p++; p_start = p; @@ -2942,7 +2940,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, goto done; } } - + if (radix == 0) radix = 10; if (is_dec) { @@ -3033,7 +3031,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, goto done; } } - + /* reset the next limbs to zero (we prefer to reallocate in the renormalization) */ memset(a->tab, 0, (pos + 1) * sizeof(limb_t)); @@ -3091,7 +3089,7 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, } else if (radix_bits) { /* XXX: may overflow */ if (!is_bin_exp) - expn *= radix_bits; + expn *= radix_bits; a->expn = expn + (int_len * radix_bits); a->sign = is_neg; ret = bf_normalize_and_round(a, prec, flags); @@ -3130,9 +3128,9 @@ static int bf_atof_internal(bf_t *r, slimb_t *pexponent, return ret; } -/* +/* Return (status, n, exp). 'status' is the floating point status. 'n' - is the parsed number. + is the parsed number. If (flags & BF_ATOF_EXPONENT) and if the radix is not a power of two, the parsed number is equal to r * @@ -3347,7 +3345,7 @@ slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv, const uint32_t *tab; limb_t b0, b1; dlimb_t t; - + if (is_inv) { tab = inv_log2_radix[radix - 2]; #if LIMB_BITS == 32 @@ -3381,7 +3379,7 @@ static int bf_integer_to_radix_rec(bf_t *pow_tab, { limb_t n1, n2, q_prec; int ret; - + assert(n >= 1); if (n == 1) { out[0] = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn); @@ -3421,7 +3419,7 @@ static int bf_integer_to_radix_rec(bf_t *pow_tab, q_prec = n1 * radixl_bits; ret |= bf_mul(&Q, a, B_inv, q_prec, BF_RNDN); ret |= bf_rint(&Q, BF_RNDZ); - + ret |= bf_mul(&R, &Q, B, BF_PREC_INF, BF_RNDZ); ret |= bf_sub(&R, a, &R, BF_PREC_INF, BF_RNDZ); @@ -3466,7 +3464,7 @@ static int bf_integer_to_radix(bf_t *r, const bf_t *a, limb_t radixl) limb_t r_len; bf_t *pow_tab; int i, pow_tab_len, ret; - + r_len = r->len; pow_tab_len = (ceil_log2(r_len) + 2) * 2; /* XXX: check */ pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len); @@ -3496,7 +3494,7 @@ static int bf_convert_to_radix(bf_t *r, slimb_t *pE, slimb_t E, e, prec, extra_bits, ziv_extra_bits, prec0; bf_t B_s, *B = &B_s; int e_sign, ret, res; - + if (a->len == 0) { /* zero case */ *pE = 0; @@ -3511,7 +3509,7 @@ static int bf_convert_to_radix(bf_t *r, slimb_t *pE, } // bf_print_str("a", a); // printf("E=%ld P=%ld radix=%d\n", E, P, radix); - + for(;;) { e = P - E; e_sign = 0; @@ -3707,7 +3705,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix, bf_context_t *ctx = a2->ctx; DynBuf s_s, *s = &s_s; int radix_bits; - + // bf_print_str("ftoa", a2); // printf("radix=%d\n", radix); dbuf_init2(s, ctx, bf_dbuf_realloc); @@ -3789,7 +3787,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix, a->len = a2->len; a->expn = a2->expn; a->sign = 0; - + /* one more digit for the rounding */ n = 1 + bf_mul_log2_radix(bf_max(a->expn, 0), radix, TRUE, TRUE); n_digits = n + prec; @@ -3864,19 +3862,19 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix, n = ceil_div(a1->expn, radix_bits); } else { bf_t a_s, *a = &a_s; - + /* make a positive number */ a->tab = a2->tab; a->len = a2->len; a->expn = a2->expn; a->sign = 0; - + if (fmt == BF_FTOA_FORMAT_FIXED) { n_digits = prec; n_max = n_digits; } else { slimb_t n_digits_max, n_digits_min; - + assert(prec != BF_PREC_INF); n_digits = 1 + bf_mul_log2_radix(prec, radix, TRUE, TRUE); /* max number of digits for non exponential @@ -3885,7 +3883,7 @@ static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix, n_max = n_digits + 4; if (fmt == BF_FTOA_FORMAT_FREE_MIN) { bf_t b_s, *b = &b_s; - + /* find the minimum number of digits by dichotomy. */ /* XXX: inefficient */ @@ -4024,7 +4022,7 @@ static void bf_const_log2_rec(bf_t *T, bf_t *P, bf_t *Q, limb_t n1, bf_t T1_s, *T1 = &T1_s; bf_t P1_s, *P1 = &P1_s; bf_t Q1_s, *Q1 = &Q1_s; - + m = n1 + ((n2 - n1) >> 1); bf_const_log2_rec(T, P, Q, n1, m, TRUE); bf_init(s, T1); @@ -4075,7 +4073,7 @@ static void chud_bs(bf_t *P, bf_t *Q, bf_t *G, int64_t a, int64_t b, int need_g, if (a == (b - 1)) { bf_t T0, T1; - + bf_init(s, &T0); bf_init(s, &T1); bf_set_ui(G, 2 * b - 1); @@ -4096,7 +4094,7 @@ static void chud_bs(bf_t *P, bf_t *Q, bf_t *G, int64_t a, int64_t b, int need_g, bf_delete(&T1); } else { bf_t P2, Q2, G2; - + bf_init(s, &P2); bf_init(s, &Q2); bf_init(s, &G2); @@ -4104,7 +4102,7 @@ static void chud_bs(bf_t *P, bf_t *Q, bf_t *G, int64_t a, int64_t b, int need_g, c = (a + b) / 2; chud_bs(P, Q, G, a, c, 1, prec); chud_bs(&P2, &Q2, &G2, c, b, need_g, prec); - + /* Q = Q1 * Q2 */ /* G = G1 * G2 */ /* P = P1 * Q2 + P2 * G1 */ @@ -4140,11 +4138,11 @@ static void bf_const_pi_internal(bf_t *Q, limb_t prec) bf_init(s, &G); chud_bs(&P, Q, &G, 0, n, 0, BF_PREC_INF); - + bf_mul_ui(&G, Q, CHUD_A, prec1, BF_RNDN); bf_add(&P, &G, &P, prec1, BF_RNDN); bf_div(Q, Q, &P, prec1, BF_RNDF); - + bf_set_ui(&P, CHUD_C); bf_sqrt(&G, &P, prec1, BF_RNDF); bf_mul_ui(&G, &G, (uint64_t)CHUD_C / 12, prec1, BF_RNDF); @@ -4227,7 +4225,7 @@ static int bf_ziv_rounding(bf_t *r, const bf_t *a, { int rnd_mode, ret; slimb_t prec1, ziv_extra_bits; - + rnd_mode = flags & BF_RND_MASK; if (rnd_mode == BF_RNDF) { /* no need to iterate */ @@ -4286,7 +4284,7 @@ static int bf_exp_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_context_t *s = r->ctx; bf_t T_s, *T = &T_s; slimb_t n, K, l, i, prec1; - + assert(r != a); /* argument reduction: @@ -4319,14 +4317,14 @@ static int bf_exp_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) /* reduce the range of T */ bf_mul_2exp(T, -K, BF_PREC_INF, BF_RNDZ); - + /* Taylor expansion around zero : - 1 + x + x^2/2 + ... + x^n/n! + 1 + x + x^2/2 + ... + x^n/n! = (1 + x * (1 + x/2 * (1 + ... (x/n)))) */ { bf_t U_s, *U = &U_s; - + bf_init(s, U); bf_set_ui(r, 1); for(i = l ; i >= 1; i--) { @@ -4338,7 +4336,7 @@ static int bf_exp_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_delete(U); } bf_delete(T); - + /* undo the range reduction */ for(i = 0; i < K; i++) { bf_mul(r, r, r, prec1, BF_RNDN | BF_FLAG_EXT_EXP); @@ -4358,7 +4356,7 @@ static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r, bf_t T_s, *T = &T_s; bf_t log2_s, *log2 = &log2_s; slimb_t e_min, e_max; - + if (a_high->expn <= 0) return 0; @@ -4366,7 +4364,7 @@ static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r, e_min = -e_max + 3; if (flags & BF_FLAG_SUBNORMAL) e_min -= (prec - 1); - + bf_init(s, T); bf_init(s, log2); bf_const_log2(log2, LIMB_BITS, BF_RNDU); @@ -4383,7 +4381,7 @@ static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r, bf_mul_si(T, log2, e_min - 2, LIMB_BITS, BF_RNDD); if (bf_cmp_lt(a_high, T)) { int rnd_mode = flags & BF_RND_MASK; - + /* underflow */ bf_delete(T); bf_delete(log2); @@ -4423,12 +4421,12 @@ int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) ret = check_exp_underflow_overflow(s, r, a, a, prec, flags); if (ret) return ret; - if (a->expn < 0 && (-a->expn) >= (prec + 2)) { + if (a->expn < 0 && (-a->expn) >= (prec + 2)) { /* small argument case: result = 1 + epsilon * sign(x) */ bf_set_ui(r, 1); return bf_add_epsilon(r, r, -(prec + 2), a->sign, prec, flags); } - + return bf_ziv_rounding(r, a, prec, flags, bf_exp_internal, NULL); } @@ -4439,7 +4437,7 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_t U_s, *U = &U_s; bf_t V_s, *V = &V_s; slimb_t n, prec1, l, i, K; - + assert(r != a); bf_init(s, T); @@ -4452,7 +4450,7 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) T->expn = 0; /* U= ~ 2/3 */ bf_init(s, U); - bf_set_ui(U, 0xaaaaaaaa); + bf_set_ui(U, 0xaaaaaaaa); U->expn = 0; if (bf_cmp_lt(T, U)) { T->expn++; @@ -4465,18 +4463,18 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) /* XXX: precision analysis */ /* number of iterations for argument reduction 2 */ - K = bf_isqrt((prec + 1) / 2); + K = bf_isqrt((prec + 1) / 2); /* order of Taylor expansion */ - l = prec / (2 * K) + 1; + l = prec / (2 * K) + 1; /* precision of the intermediate computations */ prec1 = prec + K + 2 * l + 32; bf_init(s, U); bf_init(s, V); - + /* Note: cancellation occurs here, so we use more precision (XXX: reduce the precision by computing the exact cancellation) */ - bf_add_si(T, T, -1, BF_PREC_INF, BF_RNDN); + bf_add_si(T, T, -1, BF_PREC_INF, BF_RNDN); /* argument reduction 2 */ for(i = 0; i < K; i++) { @@ -4494,7 +4492,7 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_init(s, Y2); /* compute ln(1+x) = ln((1+y)/(1-y)) with y=x/(2+x) - = y + y^3/3 + ... + y^(2*l + 1) / (2*l+1) + = y + y^3/3 + ... + y^(2*l + 1) / (2*l+1) with Y=Y^2 = y*(1+Y/3+Y^2/5+...) = y*(1+Y*(1/3+Y*(1/5 + ...))) */ @@ -4521,12 +4519,12 @@ static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) /* multiplication by 2 for the Taylor expansion and undo the argument reduction 2*/ bf_mul_2exp(r, K + 1, BF_PREC_INF, BF_RNDZ); - + /* undo the argument reduction 1 */ bf_const_log2(T, prec1, BF_RNDF); bf_mul_si(T, T, n, prec1, BF_RNDN); bf_add(r, r, T, prec1, BF_RNDN); - + bf_delete(T); return BF_ST_INEXACT; } @@ -4535,7 +4533,7 @@ int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) { bf_context_t *s = r->ctx; bf_t T_s, *T = &T_s; - + assert(r != a); if (a->len == 0) { if (a->expn == BF_EXP_NAN) { @@ -4600,7 +4598,7 @@ static int bf_pow_int(bf_t *r, const bf_t *x, limb_t prec, void *opaque) limb_t prec1; int ret; slimb_t y1; - + bf_get_limb(&y1, y, 0); if (y1 < 0) y1 = -y1; @@ -4625,7 +4623,7 @@ static BOOL check_exact_power2n(bf_t *r, const bf_t *x, slimb_t n) bf_t T_s, *T = &T_s; slimb_t e, i, er; limb_t v; - + /* x = m*2^e with m odd integer */ e = bf_get_exp_min(x); /* fast check on the exponent */ @@ -4665,7 +4663,7 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags) BOOL y_is_int, y_is_odd; int r_sign, ret, rnd_mode; slimb_t y_emin; - + if (x->len == 0 || y->len == 0) { if (y->expn == BF_EXP_ZERO) { /* pow(x, 0) = 1 */ @@ -4739,7 +4737,7 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags) bf_t al_s, *al = &al_s; bf_t ah_s, *ah = &ah_s; limb_t precl = LIMB_BITS; - + bf_init(s, al); bf_init(s, ah); /* compute bounds of log(abs(x)) * y with a low precision */ @@ -4755,7 +4753,7 @@ int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags) if (ret) goto done; } - + if (y_is_int) { slimb_t T_bits, e; int_pow: @@ -4850,18 +4848,18 @@ static int bf_sincos(bf_t *s, bf_t *c, const bf_t *a, limb_t prec) bf_t r_s, *r = &r_s; slimb_t K, prec1, i, l, mod, prec2; int is_neg; - + assert(c != a && s != a); bf_init(s1, T); bf_init(s1, U); bf_init(s1, r); - + /* XXX: precision analysis */ K = bf_isqrt(prec / 2); l = prec / (2 * K) + 1; prec1 = prec + 2 * K + l + 8; - + /* after the modulo reduction, -pi/4 <= T <= pi/4 */ if (a->expn <= -1) { /* abs(a) <= 0.25: no modulo reduction needed */ @@ -4884,13 +4882,13 @@ static int bf_sincos(bf_t *s, bf_t *c, const bf_t *a, limb_t prec) } mod &= 3; } - + is_neg = T->sign; - + /* compute cosm1(x) = cos(x) - 1 */ bf_mul(T, T, T, prec1, BF_RNDN); bf_mul_2exp(T, -2 * K, BF_PREC_INF, BF_RNDZ); - + /* Taylor expansion: -x^2/2 + x^4/4! - x^6/6! + ... */ @@ -4969,7 +4967,7 @@ int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) return bf_add_epsilon(r, r, e, 1, prec, flags); } } - + return bf_ziv_rounding(r, a, prec, flags, bf_cos_internal, NULL); } @@ -5012,7 +5010,7 @@ static int bf_tan_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) bf_context_t *s = r->ctx; bf_t T_s, *T = &T_s; limb_t prec1; - + /* XXX: precision analysis */ prec1 = prec + 8; bf_init(s, T); @@ -5048,7 +5046,7 @@ int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) return bf_add_epsilon(r, r, e, a->sign, prec, flags); } } - + return bf_ziv_rounding(r, a, prec, flags, bf_tan_internal, NULL); } @@ -5065,13 +5063,13 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec, bf_t X2_s, *X2 = &X2_s; int cmp_1; slimb_t prec1, i, K, l; - + /* XXX: precision analysis */ K = bf_isqrt((prec + 1) / 2); l = prec / (2 * K) + 1; prec1 = prec + K + 2 * l + 32; // printf("prec=%d K=%d l=%d prec1=%d\n", (int)prec, (int)K, (int)l, (int)prec1); - + bf_init(s, T); cmp_1 = (a->expn >= 1); /* a >= 1 */ if (cmp_1) { @@ -5097,8 +5095,8 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec, bf_div(T, T, V, prec1, BF_RNDN); } - /* Taylor series: - x - x^3/3 + ... + (-1)^ l * y^(2*l + 1) / (2*l+1) + /* Taylor series: + x - x^3/3 + ... + (-1)^ l * y^(2*l + 1) / (2*l+1) */ bf_mul(X2, T, T, prec1, BF_RNDN); bf_set_ui(r, 0); @@ -5116,7 +5114,7 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec, /* undo the argument reduction */ bf_mul_2exp(r, K, BF_PREC_INF, BF_RNDZ); - + bf_delete(U); bf_delete(V); bf_delete(X2); @@ -5135,7 +5133,7 @@ static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec, T->sign = (i < 0); bf_add(r, T, r, prec1, BF_RNDN); } - + bf_delete(T); return BF_ST_INEXACT; } @@ -5145,7 +5143,7 @@ int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) bf_context_t *s = r->ctx; bf_t T_s, *T = &T_s; int res; - + if (a->len == 0) { if (a->expn == BF_EXP_NAN) { bf_set_nan(r); @@ -5160,7 +5158,7 @@ int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) return 0; } } - + bf_init(s, T); bf_set_ui(T, 1); res = bf_cmpu(a, T); @@ -5182,7 +5180,7 @@ int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) return bf_add_epsilon(r, r, e, 1 - a->sign, prec, flags); } } - + return bf_ziv_rounding(r, a, prec, flags, bf_atan_internal, (void *)FALSE); } @@ -5193,7 +5191,7 @@ static int bf_atan2_internal(bf_t *r, const bf_t *y, limb_t prec, void *opaque) bf_t T_s, *T = &T_s; limb_t prec1; int ret; - + if (y->expn == BF_EXP_NAN || x->expn == BF_EXP_NAN) { bf_set_nan(r); return 0; @@ -5236,8 +5234,8 @@ static int bf_asin_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque) BOOL is_acos = (BOOL)(intptr_t)opaque; bf_t T_s, *T = &T_s; limb_t prec1, prec2; - - /* asin(x) = atan(x/sqrt(1-x^2)) + + /* asin(x) = atan(x/sqrt(1-x^2)) acos(x) = pi/2 - asin(x) */ prec1 = prec + 8; /* increase the precision in x^2 to compensate the cancellation in @@ -5287,7 +5285,7 @@ int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) bf_set_nan(r); return BF_ST_INVALID_OP; } - + /* small argument case: result = x+r(x) with r(x) = x^3/6 + O(X^5). We assume r(x) < 2^(3*EXP(x) - 2). */ if (a->expn < 0) { @@ -5332,7 +5330,7 @@ int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags) bf_set_zero(r, 0); return 0; } - + return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)TRUE); } @@ -5565,8 +5563,8 @@ static inline limb_t fast_shr_dec(limb_t a, int shift) /* division and remainder by 10^shift */ #define fast_shr_rem_dec(q, r, a, shift) q = fast_shr_dec(a, shift), r = a - q * mp_pow_dec[shift] - -limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2, + +limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2, mp_size_t n, limb_t carry) { limb_t base = BF_DEC_BASE; @@ -5579,7 +5577,7 @@ limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2, v = op1[i]; a = v + op2[i] + k - base; k = a <= v; - if (!k) + if (!k) a += base; res[i]=a; } @@ -5597,7 +5595,7 @@ limb_t mp_add_ui_dec(limb_t *tab, limb_t b, mp_size_t n) v = tab[i]; a = v + k - base; k = a <= v; - if (!k) + if (!k) a += base; tab[i] = a; if (k == 0) @@ -5606,7 +5604,7 @@ limb_t mp_add_ui_dec(limb_t *tab, limb_t b, mp_size_t n) return k; } -limb_t mp_sub_dec(limb_t *res, const limb_t *op1, const limb_t *op2, +limb_t mp_sub_dec(limb_t *res, const limb_t *op1, const limb_t *op2, mp_size_t n, limb_t carry) { limb_t base = BF_DEC_BASE; @@ -5630,7 +5628,7 @@ limb_t mp_sub_ui_dec(limb_t *tab, limb_t b, mp_size_t n) limb_t base = BF_DEC_BASE; mp_size_t i; limb_t k, v, a; - + k=b; for(i=0;i= UDIV1NORM_THRESHOLD) { shift = clz(b); @@ -5819,7 +5817,7 @@ static __maybe_unused void mp_print_str_h_dec(const char *str, #define DIV_STATIC_ALLOC_LEN 16 -/* return q = a / b and r = a % b. +/* return q = a / b and r = a % b. taba[na] must be allocated if tabb1[nb - 1] < B / 2. tabb1[nb - 1] must be != zero. na must be >= nb. 's' can be NULL if tabb1[nb - 1] @@ -5833,14 +5831,14 @@ static __maybe_unused void mp_print_str_h_dec(const char *str, */ /* XXX: optimize */ static int mp_div_dec(bf_context_t *s, limb_t *tabq, - limb_t *taba, mp_size_t na, + limb_t *taba, mp_size_t na, const limb_t *tabb1, mp_size_t nb) { limb_t base = BF_DEC_BASE; limb_t r, mult, t0, t1, a, c, q, v, *tabb; mp_size_t i, j; limb_t static_tabb[DIV_STATIC_ALLOC_LEN]; - + #ifdef DEBUG_DIV_SLOW mp_print_str_dec("a", taba, na); mp_print_str_dec("b", tabb1, nb); @@ -5938,7 +5936,7 @@ static int mp_div_dec(bf_context_t *s, limb_t *tabq, } /* divide by 10^shift */ -static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, +static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, limb_t shift, limb_t high) { mp_size_t i; @@ -5956,7 +5954,7 @@ static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, } /* multiply by 10^shift */ -static limb_t mp_shl_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, +static limb_t mp_shl_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n, limb_t shift, limb_t low) { mp_size_t i; @@ -6002,7 +6000,7 @@ static limb_t mp_sqrtrem_rec_dec(limb_t *tabs, limb_t *taba, limb_t n, limb_t *tmp_buf) { limb_t l, h, rh, ql, qh, c, i; - + if (n == 1) return mp_sqrtrem2_dec(tabs, taba); #ifdef DEBUG_SQRTREM_DEC @@ -6016,7 +6014,7 @@ static limb_t mp_sqrtrem_rec_dec(limb_t *tabs, limb_t *taba, limb_t n, mp_print_str_h_dec("r1", taba + 2 * l, h, qh); mp_print_str_h_dec("r2", taba + l, n, qh); #endif - + /* the remainder is in taba + 2 * l. Its high bit is in qh */ if (qh) { mp_sub_dec(taba + 2 * l, taba + 2 * l, tabs + l, h, 0); @@ -6037,12 +6035,12 @@ static limb_t mp_sqrtrem_rec_dec(limb_t *tabs, limb_t *taba, limb_t n, mp_print_str_h_dec("q", tabs, l, qh); mp_print_str_h_dec("u", taba + l, h, rh); #endif - + mp_add_ui_dec(tabs + l, qh, h); #ifdef DEBUG_SQRTREM_DEC mp_print_str_dec("s2", tabs, n); #endif - + /* q = qh, tabs[l - 1 ... 0], r = taba[n - 1 ... l] */ /* subtract q^2. if qh = 1 then q = B^l, so we can take shortcuts */ if (qh) { @@ -6336,7 +6334,7 @@ static limb_t get_digits(const limb_t *tab, limb_t len, slimb_t pos) limb_t a0, a1; int shift; slimb_t i; - + i = floor_div(pos, LIMB_DIGITS); shift = pos - i * LIMB_DIGITS; if (i >= 0 && i < len) @@ -6364,7 +6362,7 @@ static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l, { int add_one, inexact; limb_t digit1, digit0; - + // bfdec_print_str("get_rnd_add", r); if (rnd_mode == BF_RNDF) { digit0 = 1; /* faithful rounding does not honor the INEXACT flag */ @@ -6376,7 +6374,7 @@ static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l, /* get the digit at 'prec' */ digit1 = get_digit(r->tab, l, l * LIMB_DIGITS - 1 - prec); inexact = (digit1 | digit0) != 0; - + add_one = 0; switch(rnd_mode) { case BF_RNDZ: @@ -6409,7 +6407,7 @@ static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l, default: abort(); } - + if (inexact) *pret |= BF_ST_INEXACT; return add_one; @@ -6429,7 +6427,7 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) e_range = (limb_t)1 << (bf_get_exp_bits(flags) - 1); e_min = -e_range + 3; e_max = e_range; - + if (flags & BF_FLAG_RADPNT_PREC) { /* 'prec' is the precision after the decimal point */ if (prec1 != BF_PREC_INF) @@ -6444,12 +6442,12 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) } else { prec = prec1; } - + /* round to prec bits */ rnd_mode = flags & BF_RND_MASK; ret = 0; add_one = bfdec_get_rnd_add(&ret, r, l, prec, rnd_mode); - + if (prec <= 0) { if (add_one) { bfdec_resize(r, 1); /* cannot fail because r is non zero */ @@ -6462,7 +6460,7 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) } } else if (add_one) { limb_t carry; - + /* add one starting at digit 'prec - 1' */ bit_pos = l * LIMB_DIGITS - 1 - (prec - 1); pos = bit_pos / LIMB_DIGITS; @@ -6474,7 +6472,7 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) r->expn++; } } - + /* check underflow */ if (unlikely(r->expn < e_min)) { if (flags & BF_FLAG_SUBNORMAL) { @@ -6488,14 +6486,14 @@ static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l) return ret; } } - + /* check overflow */ if (unlikely(r->expn > e_max)) { bfdec_set_inf(r, r->sign); ret |= BF_ST_OVERFLOW | BF_ST_INEXACT; return ret; } - + /* keep the bits starting at 'prec - 1' */ bit_pos = l * LIMB_DIGITS - 1 - (prec - 1); i = floor_div(bit_pos, LIMB_DIGITS); @@ -6532,7 +6530,7 @@ int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags) { limb_t l, v; int shift, ret; - + // bfdec_print_str("bf_renorm", r); l = r->len; while (l > 0 && r->tab[l - 1] == 0) @@ -6649,7 +6647,7 @@ static int bfdec_add_internal(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, li limb_t *b1_tab; int b_shift; mp_size_t b1_len; - + d = a->expn - b->expn; /* XXX: not efficient in time and memory if the precision is @@ -6665,7 +6663,7 @@ static int bfdec_add_internal(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, li r->tab[i] = 0; for(i = 0; i < a->len; i++) r->tab[a_offset + i] = a->tab[i]; - + b_shift = d % LIMB_DIGITS; if (b_shift == 0) { b1_len = b->len; @@ -6679,7 +6677,7 @@ static int bfdec_add_internal(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, li mp_pow_dec[LIMB_DIGITS - b_shift]; } b_offset = r_len - (b->len + (d + LIMB_DIGITS - 1) / LIMB_DIGITS); - + if (is_sub) { carry = mp_sub_dec(r->tab + b_offset, r->tab + b_offset, b1_tab, b1_len, 0); @@ -6775,12 +6773,12 @@ int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bfdec_t tmp, *r1 = NULL; limb_t a_len, b_len; limb_t *a_tab, *b_tab; - + a_len = a->len; b_len = b->len; a_tab = a->tab; b_tab = b->tab; - + if (r == a || r == b) { bfdec_init(r->ctx, &tmp); r1 = r; @@ -6819,7 +6817,7 @@ int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec, { bfdec_t b; int ret; - + bfdec_init(r->ctx, &b); ret = bfdec_set_si(&b, b1); ret |= bfdec_add(r, a, &b, prec, flags); @@ -6832,7 +6830,7 @@ static int __bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, { int ret, r_sign; limb_t n, nb, precl; - + r_sign = a->sign ^ b->sign; if (a->expn >= BF_EXP_INF || b->expn >= BF_EXP_INF) { if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { @@ -6877,11 +6875,11 @@ static int __bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, precl = (prec + 2 + LIMB_DIGITS - 1) / LIMB_DIGITS; } n = bf_max(a->len, precl); - + { limb_t *taba, na, i; slimb_t d; - + na = n + nb; taba = bf_malloc(r->ctx, (na + 1) * sizeof(limb_t)); if (!taba) @@ -6942,8 +6940,8 @@ static void bfdec_tdivremu(bf_context_t *s, bfdec_t *q, bfdec_t *r, } } -/* division and remainder. - +/* division and remainder. + rnd_mode is the rounding mode for the quotient. The additional rounding mode BF_RND_EUCLIDIAN is supported. @@ -6959,11 +6957,11 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b, bfdec_t r1_s, *r1 = &r1_s; int q_sign, res; BOOL is_ceil, is_rndn; - + assert(q != a && q != b); assert(r != a && r != b); assert(q != r); - + if (a->len == 0 || b->len == 0) { bfdec_set_zero(q, 0); if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) { @@ -7005,7 +7003,7 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b, a1->tab = a->tab; a1->len = a->len; a1->sign = 0; - + b1->expn = b->expn; b1->tab = b->tab; b1->len = b->len; @@ -7019,7 +7017,7 @@ int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b, goto fail; // bfdec_print_str("q", q); // bfdec_print_str("r", r); - + if (r->len != 0) { if (is_rndn) { bfdec_init(s, r1); @@ -7060,7 +7058,7 @@ int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, { bfdec_t q_s, *q = &q_s; int ret; - + bfdec_init(r->ctx, q); ret = bfdec_divrem(q, r, a, b, prec, flags, rnd_mode); bfdec_delete(q); @@ -7208,7 +7206,7 @@ int bfdec_get_int32(int *pres, const bfdec_t *a) int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b) { int ret, n_bits, i; - + assert(r != a); if (b == 0) return bfdec_set_ui(r, 1); @@ -7348,7 +7346,7 @@ static const limb_t ntt_mods_cr[NB_MODS * (NB_MODS - 1) / 2] = { typedef struct BFNTTState { bf_context_t *ctx; - + /* used for mul_mod_fast() */ limb_t ntt_mods_div[NB_MODS]; @@ -7388,16 +7386,16 @@ static inline limb_t sub_mod(limb_t a, limb_t b, limb_t m) return r; } -/* return (r0+r1*B) mod m - precondition: 0 <= r0+r1*B < 2^(64+NTT_MOD_LOG2_MIN) +/* return (r0+r1*B) mod m + precondition: 0 <= r0+r1*B < 2^(64+NTT_MOD_LOG2_MIN) */ -static inline limb_t mod_fast(dlimb_t r, +static inline limb_t mod_fast(dlimb_t r, limb_t m, limb_t m_inv) { limb_t a1, q, t0, r1, r0; - + a1 = r >> NTT_MOD_LOG2_MIN; - + q = ((dlimb_t)a1 * m_inv) >> LIMB_BITS; r = r - (dlimb_t)q * m - m * 2; r1 = r >> LIMB_BITS; @@ -7409,9 +7407,9 @@ static inline limb_t mod_fast(dlimb_t r, return r0; } -/* faster version using precomputed modulo inverse. +/* faster version using precomputed modulo inverse. precondition: 0 <= a * b < 2^(64+NTT_MOD_LOG2_MIN) */ -static inline limb_t mul_mod_fast(limb_t a, limb_t b, +static inline limb_t mul_mod_fast(limb_t a, limb_t b, limb_t m, limb_t m_inv) { dlimb_t r; @@ -7430,7 +7428,7 @@ static inline limb_t init_mul_mod_fast(limb_t m) /* Faster version used when the multiplier is constant. 0 <= a < 2^64, 0 <= b < m. */ -static inline limb_t mul_mod_fast2(limb_t a, limb_t b, +static inline limb_t mul_mod_fast2(limb_t a, limb_t b, limb_t m, limb_t b_inv) { limb_t r, q; @@ -7445,7 +7443,7 @@ static inline limb_t mul_mod_fast2(limb_t a, limb_t b, /* Faster version used when the multiplier is constant. 0 <= a < 2^64, 0 <= b < m. Let r = a * b mod m. The return value is 'r' or 'r + m'. */ -static inline limb_t mul_mod_fast3(limb_t a, limb_t b, +static inline limb_t mul_mod_fast3(limb_t a, limb_t b, limb_t m, limb_t b_inv) { limb_t r, q; @@ -7551,9 +7549,9 @@ static no_inline int ntt_fft(BFNTTState *s, __m256d m_inv, mf, m2f, c, a0, a1, b0, b1; limb_t m; int l; - + m = ntt_mods[m_idx]; - + m_inv = _mm256_set1_pd(1.0 / (double)m); mf = _mm256_set1_pd(m); m2f = _mm256_set1_pd(m * 2); @@ -7607,7 +7605,7 @@ static no_inline int ntt_fft(BFNTTState *s, tmp = tab_in; tab_in = tab_out; tab_out = tmp; - + nb_blocks = n / 4; fft_per_block = 4; @@ -7658,7 +7656,7 @@ static void ntt_vec_mul(BFNTTState *s, { limb_t i, c_inv, n, m; __m256d m_inv, mf, a, b, c; - + m = ntt_mods[m_idx]; c_inv = s->ntt_len_inv[m_idx][k_tot][0]; m_inv = _mm256_set1_pd(1.0 / (double)m); @@ -7680,7 +7678,7 @@ static no_inline void mul_trig(NTTLimb *buf, limb_t i, c2, c3, c4; __m256d c, c_mul, a0, mf, m_inv; assert(n >= 2); - + mf = _mm256_set1_pd(m); m_inv = _mm256_set1_pd(1.0 / (double)m); @@ -7729,7 +7727,7 @@ static no_inline int ntt_fft(BFNTTState *s, NTTLimb *out_buf, NTTLimb *in_buf, limb_t nb_blocks, fft_per_block, p, k, n, stride_in, i, j, m, m2; NTTLimb *tab_in, *tab_out, *tmp, a0, a1, b0, b1, c, *trig, c_inv; int l; - + m = ntt_mods[m_idx]; m2 = 2 * m; n = (limb_t)1 << fft_len_log2; @@ -7769,7 +7767,7 @@ static no_inline int ntt_fft(BFNTTState *s, NTTLimb *out_buf, NTTLimb *in_buf, tab_out = tmp; } /* no twiddle in last step */ - tab_out = out_buf; + tab_out = out_buf; for(k = 0; k < stride_in; k++) { a0 = tab_in[k]; a1 = tab_in[k + stride_in]; @@ -7786,7 +7784,7 @@ static void ntt_vec_mul(BFNTTState *s, int k_tot, int m_idx) { limb_t i, norm, norm_inv, a, n, m, m_inv; - + m = ntt_mods[m_idx]; m_inv = s->ntt_mods_div[m_idx]; norm = s->ntt_len_inv[m_idx][k_tot][0]; @@ -7808,7 +7806,7 @@ static no_inline void mul_trig(NTTLimb *buf, limb_t n, limb_t c_mul, limb_t m, limb_t m_inv) { limb_t i, c0, c_mul_inv; - + c0 = 1; c_mul_inv = init_mul_mod_fast2(c_mul, m); for(i = 0; i < n; i++) { @@ -7824,7 +7822,7 @@ static no_inline NTTLimb *get_trig(BFNTTState *s, { NTTLimb *tab; limb_t i, n2, c, c_mul, m, c_mul_inv; - + if (k > NTT_TRIG_K_MAX) return NULL; @@ -7889,7 +7887,7 @@ static int ntt_fft_partial(BFNTTState *s, NTTLimb *buf1, { limb_t i, j, c_mul, c0, m, m_inv, strip_len, l; NTTLimb *buf2, *buf3; - + buf2 = NULL; buf3 = ntt_malloc(s, sizeof(NTTLimb) * n1); if (!buf3) @@ -7922,7 +7920,7 @@ static int ntt_fft_partial(BFNTTState *s, NTTLimb *buf1, mul_trig(buf2 + l * n1, n1, c_mul, m, m_inv); c_mul = mul_mod_fast(c_mul, c0, m, m_inv); } - + for(i = 0; i < n1; i++) { for(l = 0; l < strip_len; l++) { buf1[i * n2 + (j + l)] = buf2[i + l *n1]; @@ -7946,7 +7944,7 @@ static int ntt_conv(BFNTTState *s, NTTLimb *buf1, NTTLimb *buf2, { limb_t n1, n2, i; int k1, k2; - + if (k <= NTT_TRIG_K_MAX) { k1 = k; } else { @@ -7956,7 +7954,7 @@ static int ntt_conv(BFNTTState *s, NTTLimb *buf1, NTTLimb *buf2, k2 = k - k1; n1 = (limb_t)1 << k1; n2 = (limb_t)1 << k2; - + if (ntt_fft_partial(s, buf1, k1, k2, n1, n2, 0, m_idx)) return -1; if (ntt_fft_partial(s, buf2, k1, k2, n1, n2, 0, m_idx)) @@ -7983,13 +7981,13 @@ static no_inline void limb_to_ntt(BFNTTState *s, dlimb_t a, b; int j, shift; limb_t base_mask1, a0, a1, a2, r, m, m_inv; - + #if 0 for(i = 0; i < a_len; i++) { printf("%" PRId64 ": " FMT_LIMB "\n", (int64_t)i, taba[i]); } -#endif +#endif memset(tabr, 0, sizeof(NTTLimb) * fft_len * nb_mods); shift = dpl & (LIMB_BITS - 1); if (shift == 0) @@ -8054,21 +8052,21 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, slimb_t i, len, pos; int j, k, l, shift, n_limb1, p; dlimb_t t; - + j = NB_MODS * (NB_MODS - 1) / 2 - nb_mods * (nb_mods - 1) / 2; mods_cr_vec = s->ntt_mods_cr_vec + j; mf = s->ntt_mods_vec + NB_MODS - nb_mods; m_inv = s->ntt_mods_inv_vec + NB_MODS - nb_mods; - + shift = dpl & (LIMB_BITS - 1); if (shift == 0) base_mask1 = -1; else base_mask1 = ((limb_t)1 << shift) - 1; n_limb1 = ((unsigned)dpl - 1) / LIMB_BITS; - for(j = 0; j < NB_MODS; j++) + for(j = 0; j < NB_MODS; j++) carry[j] = 0; - for(j = 0; j < NB_MODS; j++) + for(j = 0; j < NB_MODS; j++) u[j] = 0; /* avoid warnings */ memset(tabr, 0, sizeof(limb_t) * r_len); fft_len = (limb_t)1 << fft_len_log2; @@ -8090,7 +8088,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, } } y[j].v = ntt_mod1(y[j].v, mf[j]); - + for(p = 0; p < VEC_LEN; p++) { /* back to normal representation */ u[0] = (int64_t)y[nb_mods - 1].d[p]; @@ -8106,7 +8104,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, l++; } /* XXX: for nb_mods = 5, l should be 4 */ - + /* last step adds the carry */ r = (int64_t)y[0].d[p]; for(k = 0; k < l; k++) { @@ -8123,7 +8121,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, } printf("\n"); #endif - + /* write the digits */ pos = i * dpl; for(j = 0; j < n_limb1; j++) { @@ -8157,7 +8155,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, slimb_t i, len, pos; int j, k, l, shift, n_limb1; dlimb_t t; - + j = NB_MODS * (NB_MODS - 1) / 2 - nb_mods * (nb_mods - 1) / 2; mods_cr = ntt_mods_cr + j; mods_cr_inv = s->ntt_mods_cr_inv + j; @@ -8168,9 +8166,9 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, else base_mask1 = ((limb_t)1 << shift) - 1; n_limb1 = ((unsigned)dpl - 1) / LIMB_BITS; - for(j = 0; j < NB_MODS; j++) + for(j = 0; j < NB_MODS; j++) carry[j] = 0; - for(j = 0; j < NB_MODS; j++) + for(j = 0; j < NB_MODS; j++) u[j] = 0; /* avoid warnings */ memset(tabr, 0, sizeof(limb_t) * r_len); fft_len = (limb_t)1 << fft_len_log2; @@ -8188,12 +8186,12 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, m = mods[k]; /* Note: there is no overflow in the sub_mod() because the modulos are sorted by increasing order */ - y[k] = mul_mod_fast2(y[k] - y[j] + m, + y[k] = mul_mod_fast2(y[k] - y[j] + m, mods_cr[l], m, mods_cr_inv[l]); l++; } } - + /* back to normal representation */ u[0] = y[nb_mods - 1]; l = 1; @@ -8207,7 +8205,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, u[l] = r; l++; } - + /* last step adds the carry */ r = y[0]; for(k = 0; k < l; k++) { @@ -8224,7 +8222,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len, } printf("\n"); #endif - + /* write the digits */ pos = i * dpl; for(j = 0; j < n_limb1; j++) { @@ -8265,7 +8263,7 @@ static int ntt_static_init(bf_context_t *s1) memset(s, 0, sizeof(*s)); s1->ntt_state = s; s->ctx = s1; - + for(j = 0; j < NB_MODS; j++) { m = ntt_mods[j]; m_inv = init_mul_mod_fast(m); @@ -8314,7 +8312,7 @@ int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len) int dpl, fft_len_log2, n_bits, nb_mods, dpl_found, fft_len_log2_found; int int_bits, nb_mods_found; limb_t cost, min_cost; - + min_cost = -1; dpl_found = 0; nb_mods_found = 4; @@ -8370,11 +8368,11 @@ static no_inline int fft_mul(bf_context_t *s1, #if defined(USE_MUL_CHECK) limb_t ha, hb, hr, h_ref; #endif - + if (ntt_static_init(s1)) return -1; s = s1->ntt_state; - + /* find the optimal number of digits per limb (dpl) */ len = a_len + b_len; fft_len_log2 = bf_get_fft_size(&dpl, &nb_mods, len); @@ -8402,7 +8400,7 @@ static no_inline int fft_mul(bf_context_t *s1, return -1; limb_to_ntt(s, buf1, fft_len, a_tab, a_len, dpl, NB_MODS - nb_mods, nb_mods); - if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) == + if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) == FFT_MUL_R_OVERLAP_A) { if (!(mul_flags & FFT_MUL_R_NORESIZE)) bf_resize(res, 0); @@ -8452,7 +8450,7 @@ static no_inline int fft_mul(bf_context_t *s1, // printf("ha=0x" FMT_LIMB" hb=0x" FMT_LIMB " hr=0x" FMT_LIMB " expected=0x" FMT_LIMB "\n", ha, hb, hr, h_ref); exit(1); } -#endif +#endif return 0; fail: ntt_free(s, buf1); diff --git a/quickjs/libregexp.c b/quickjs/libregexp.c index 6aef656..ea9ff8c 100644 --- a/quickjs/libregexp.c +++ b/quickjs/libregexp.c @@ -1,6 +1,6 @@ /* * Regular Expression Engine - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -22,15 +22,12 @@ * THE SOFTWARE. */ #include -#include "my_stdlib.h" #include -#include "my_stdio.h" #include -// #include +#include #include #include -#include "my_string.h" -#include "my_assert.h" +#include #include "cutils.h" #include "libregexp.h" @@ -230,7 +227,7 @@ static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c) BOOL invert; const uint16_t *c_pt; int len, i; - + invert = c & 1; c_pt = char_range_table[c >> 1]; len = *c_pt++; @@ -280,7 +277,7 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, { int pos, len, opcode, bc_len, re_flags, i; uint32_t val; - + assert(buf_len >= RE_HEADER_LEN); re_flags= buf[0]; @@ -452,7 +449,7 @@ static int parse_digits(const uint8_t **pp, BOOL allow_overflow) const uint8_t *p; uint64_t v; int c; - + p = *pp; v = 0; for(;;) { @@ -524,7 +521,7 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) { int h, n, i; uint32_t c1; - + if (*p == '{' && allow_utf16) { p++; c = 0; @@ -718,7 +715,7 @@ static int get_class_atom(REParseState *s, CharRange *cr, const uint8_t *p; uint32_t c; int ret; - + p = *pp; c = *p; @@ -826,7 +823,7 @@ static int re_emit_range(REParseState *s, const CharRange *cr) { int len, i; uint32_t high; - + len = (unsigned)cr->len / 2; if (len >= 65535) return re_parse_error(s, "too many ranges"); @@ -867,7 +864,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp) CharRange cr_s, *cr = &cr_s; CharRange cr1_s, *cr1 = &cr1_s; BOOL invert; - + cr_init(cr, s->opaque, lre_realloc); p = *pp; p++; /* skip '[' */ @@ -957,12 +954,12 @@ static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len) uint32_t val, last; BOOL has_back_reference; uint8_t capture_bitmap[CAPTURE_COUNT_MAX]; - + ret = -2; /* not known yet */ pos = 0; has_back_reference = FALSE; memset(capture_bitmap, 0, sizeof(capture_bitmap)); - + while (pos < bc_buf_len) { opcode = bc_buf[pos]; len = reopcode_info[opcode].size; @@ -1039,7 +1036,7 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len) { int pos, opcode, len, count; uint32_t val; - + count = 0; pos = 0; while (pos < bc_buf_len) { @@ -1199,7 +1196,7 @@ static int find_group_name(REParseState *s, const char *name) const char *p, *buf_end; size_t len, name_len; int capture_index; - + name_len = strlen(name); p = (char *)s->group_names.buf; buf_end = (char *)s->group_names.buf + s->group_names.size; @@ -1222,7 +1219,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) int c, last_atom_start, quant_min, quant_max, last_capture_count; BOOL greedy, add_zero_advance_check, is_neg, is_backward_lookahead; CharRange cr_s, *cr = &cr_s; - + last_atom_start = -1; last_capture_count = 0; p = s->buf_ptr; @@ -1345,15 +1342,15 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) capture_index = s->capture_count++; re_emit_op_u8(s, REOP_save_start + is_backward_dir, capture_index); - + s->buf_ptr = p; if (re_parse_disjunction(s, is_backward_dir)) return -1; p = s->buf_ptr; - + re_emit_op_u8(s, REOP_save_start + 1 - is_backward_dir, capture_index); - + if (re_parse_expect(s, &p, ')')) return -1; } @@ -1369,7 +1366,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) { const uint8_t *p1; int dummy_res; - + p1 = p; if (p1[2] != '<') { /* annex B: we tolerate invalid group names in non @@ -1422,10 +1419,10 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) goto normal_char; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': - case '9': + case '9': { const uint8_t *q = ++p; - + c = parse_digits(&p, FALSE); if (c < 0 || (c >= s->capture_count && c >= re_count_captures(s))) { if (!s->is_utf16) { @@ -1566,7 +1563,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) } if (greedy) { int len, pos; - + if (quant_max > 0) { /* specific optimization for simple quantifiers */ if (dbuf_error(&s->byte_code)) @@ -1575,7 +1572,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) s->byte_code.size - last_atom_start); if (len > 0) { re_emit_op(s, REOP_match); - + if (dbuf_insert(&s->byte_code, last_atom_start, 17)) goto out_of_memory; pos = last_atom_start; @@ -1592,7 +1589,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) goto done; } } - + if (dbuf_error(&s->byte_code)) goto out_of_memory; add_zero_advance_check = (re_check_advance(s->byte_code.buf + last_atom_start, @@ -1600,7 +1597,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) } else { add_zero_advance_check = FALSE; } - + { int len, pos; len = s->byte_code.size - last_atom_start; @@ -1635,7 +1632,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) atom (only works if the atom has no side effect) */ s->byte_code.buf[last_atom_start + 1 + 4] = REOP_push_char_pos; - re_emit_goto(s, REOP_bne_char_pos, last_atom_start); + re_emit_goto(s, REOP_bne_char_pos, last_atom_start); } else { re_emit_goto(s, REOP_goto, last_atom_start); } @@ -1686,7 +1683,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir) re_emit_op_u32(s, REOP_split_goto_first + greedy, len + 5); /* copy the atom */ dbuf_put_self(&s->byte_code, last_atom_start, len); - + re_emit_goto(s, REOP_loop, pos); re_emit_op(s, REOP_drop); } @@ -1738,14 +1735,14 @@ static int re_parse_alternative(REParseState *s, BOOL is_backward_dir) } return 0; } - + static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir) { int start, len, pos; if (lre_check_stack_overflow(s->opaque, 0)) return re_parse_error(s, "stack overflow"); - + start = s->byte_code.size; if (re_parse_alternative(s, is_backward_dir)) return -1; @@ -1765,7 +1762,7 @@ static int re_parse_disjunction(REParseState *s, BOOL is_backward_dir) if (re_parse_alternative(s, is_backward_dir)) return -1; - + /* patch the goto */ len = s->byte_code.size - (pos + 4); put_u32(s->byte_code.buf + pos, len); @@ -1778,7 +1775,7 @@ static int compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) { int stack_size, stack_size_max, pos, opcode, len; uint32_t val; - + stack_size = 0; stack_size_max = 0; bc_buf += RE_HEADER_LEN; @@ -1829,7 +1826,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, REParseState s_s, *s = &s_s; int stack_size; BOOL is_sticky; - + memset(s, 0, sizeof(*s)); s->opaque = opaque; s->buf_ptr = (const uint8_t *)buf; @@ -1843,7 +1840,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, s->capture_count = 1; s->total_capture_count = -1; s->has_named_captures = -1; - + dbuf_init2(&s->byte_code, opaque, lre_realloc); dbuf_init2(&s->group_names, opaque, lre_realloc); @@ -1851,7 +1848,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, dbuf_putc(&s->byte_code, 0); /* second element is the number of captures */ dbuf_putc(&s->byte_code, 0); /* stack size */ dbuf_put_u32(&s->byte_code, 0); /* bytecode length */ - + if (!is_sticky) { /* iterate thru all positions (about the same as .*?( ... ) ) . We do it without an explicit loop so that lock step @@ -1873,7 +1870,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, } re_emit_op_u8(s, REOP_save_end, 0); - + re_emit_op(s, REOP_match); if (*s->buf_ptr != '\0') { @@ -1885,13 +1882,13 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, re_parse_out_of_memory(s); goto error; } - + stack_size = compute_stack_size(s->byte_code.buf, s->byte_code.size); if (stack_size < 0) { re_parse_error(s, "too many imbricated quantifiers"); goto error; } - + s->byte_code.buf[RE_HEADER_CAPTURE_COUNT] = s->capture_count; s->byte_code.buf[RE_HEADER_STACK_SIZE] = stack_size; put_u32(s->byte_code.buf + 3, s->byte_code.size - RE_HEADER_LEN); @@ -1902,11 +1899,11 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, s->byte_code.buf[RE_HEADER_FLAGS] |= LRE_FLAG_NAMED_GROUPS; } dbuf_free(&s->group_names); - + #ifdef DUMP_REOP lre_dump_bytecode(s->byte_code.buf, s->byte_code.size); #endif - + error_msg[0] = '\0'; *plen = s->byte_code.size; return s->byte_code.buf; @@ -2037,7 +2034,7 @@ typedef struct { const uint8_t *cbuf; const uint8_t *cbuf_end; /* 0 = 8 bit chars, 1 = 16 bit chars, 2 = 16 bit chars, UTF-16 */ - int cbuf_type; + int cbuf_type; int capture_count; int stack_size_max; BOOL multi_line; @@ -2099,7 +2096,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, int cbuf_type; uint32_t val, c; const uint8_t *cbuf_end; - + cbuf_type = s->cbuf_type; cbuf_end = s->cbuf_end; @@ -2197,7 +2194,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, case REOP_split_next_first: { const uint8_t *pc1; - + val = get_u32(pc); pc += 4; if (opcode == REOP_split_next_first) { @@ -2223,7 +2220,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, if (ret < 0) return -1; break; - + case REOP_goto: val = get_u32(pc); pc += 4 + (int)val; @@ -2329,7 +2326,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, { const uint8_t *cptr1, *cptr1_end, *cptr1_start; uint32_t c1, c2; - + val = *pc++; if (val >= s->capture_count) goto no_match; @@ -2372,7 +2369,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, { int n; uint32_t low, high, idx_min, idx_max, idx; - + n = get_u16(pc); /* n must be >= 1 */ pc += 2; if (cptr >= cbuf_end) @@ -2412,7 +2409,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, { int n; uint32_t low, high, idx_min, idx_max, idx; - + n = get_u16(pc); /* n must be >= 1 */ pc += 2; if (cptr >= cbuf_end) @@ -2457,14 +2454,14 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, size_t q; intptr_t res; const uint8_t *pc1; - + next_pos = get_u32(pc); quant_min = get_u32(pc + 4); quant_max = get_u32(pc + 8); pc += 16; pc1 = pc; pc += (int)next_pos; - + q = 0; for(;;) { res = lre_exec_backtrack(s, capture, stack, stack_len, @@ -2507,7 +2504,7 @@ int lre_exec(uint8_t **capture, REExecContext s_s, *s = &s_s; int re_flags, i, alloca_size, ret; StackInt *stack_buf; - + re_flags = bc_buf[RE_HEADER_FLAGS]; s->multi_line = (re_flags & LRE_FLAG_MULTILINE) != 0; s->ignore_case = (re_flags & LRE_FLAG_IGNORECASE) != 0; @@ -2527,7 +2524,7 @@ int lre_exec(uint8_t **capture, s->state_stack = NULL; s->state_stack_len = 0; s->state_stack_size = 0; - + for(i = 0; i < s->capture_count * 2; i++) capture[i] = NULL; alloca_size = s->stack_size_max * sizeof(stack_buf[0]); @@ -2579,7 +2576,7 @@ int main(int argc, char **argv) uint8_t *capture[CAPTURE_COUNT_MAX * 2]; const char *input; int input_len, capture_count; - + if (argc < 3) { printf("usage: %s regexp input\n", argv[0]); exit(1); @@ -2593,7 +2590,7 @@ int main(int argc, char **argv) input = argv[2]; input_len = strlen(input); - + ret = lre_exec(capture, bc, (uint8_t *)input, 0, input_len, 0, NULL); printf("ret=%d\n", ret); if (ret == 1) { diff --git a/quickjs/libunicode.c b/quickjs/libunicode.c index 9508b18..91d131a 100644 --- a/quickjs/libunicode.c +++ b/quickjs/libunicode.c @@ -1,6 +1,6 @@ /* * Unicode utilities - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -22,13 +22,10 @@ * THE SOFTWARE. */ #include -#include "my_stdlib.h" #include -#include "my_stdio.h" #include #include -#include "my_string.h" -#include "my_assert.h" +#include #include "cutils.h" #include "libunicode.h" @@ -52,9 +49,9 @@ enum { }; /* conv_type: - 0 = to upper + 0 = to upper 1 = to lower - 2 = case folding (= to lower with modifications) + 2 = case folding (= to lower with modifications) */ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type) { @@ -71,7 +68,7 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type) } else { uint32_t v, code, data, type, len, a, is_lower; int idx, idx_min, idx_max; - + is_lower = (conv_type != 0); idx_min = 0; idx_max = countof(case_conv_table1) - 1; @@ -211,7 +208,7 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table, uint32_t code, b, bit; int pos; const uint8_t *p; - + pos = get_index_pos(&code, c, index_table, index_table_len); if (pos < 0) return FALSE; /* outside the table */ @@ -244,7 +241,7 @@ BOOL lre_is_cased(uint32_t c) { uint32_t v, code, len; int idx, idx_min, idx_max; - + idx_min = 0; idx_max = countof(case_conv_table1) - 1; while (idx_min <= idx_max) { @@ -303,7 +300,7 @@ int cr_realloc(CharRange *cr, int size) { int new_size; uint32_t *new_buf; - + if (size > cr->size) { new_size = max_int(size, cr->size * 3 / 2); new_buf = cr->realloc_func(cr->mem_opaque, cr->points, @@ -330,7 +327,7 @@ static void cr_compress(CharRange *cr) { int i, j, k, len; uint32_t *pt; - + pt = cr->points; len = cr->len; i = 0; @@ -360,7 +357,7 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, { int a_idx, b_idx, is_in; uint32_t v; - + a_idx = 0; b_idx = 0; for(;;) { @@ -661,7 +658,7 @@ static int unicode_decomp_char(uint32_t *res, uint32_t c, BOOL is_compat1) { uint32_t v, type, is_compat, code, len; int idx_min, idx_max, idx; - + idx_min = 0; idx_max = countof(unicode_decomp_table1) - 1; while (idx_min <= idx_max) { @@ -691,7 +688,7 @@ static int unicode_compose_pair(uint32_t c0, uint32_t c1) uint32_t code, len, type, v, idx1, d_idx, d_offset, ch; int idx_min, idx_max, idx, d; uint32_t pair[2]; - + idx_min = 0; idx_max = countof(unicode_comp_table) - 1; while (idx_min <= idx_max) { @@ -727,7 +724,7 @@ static int unicode_get_cc(uint32_t c) uint32_t code, n, type, cc, c1, b; int pos; const uint8_t *p; - + pos = get_index_pos(&code, c, unicode_cc_index, sizeof(unicode_cc_index) / 3); if (pos < 0) @@ -776,7 +773,7 @@ static int unicode_get_cc(uint32_t c) static void sort_cc(int *buf, int len) { int i, j, k, cc, cc1, start, ch1; - + for(i = 0; i < len; i++) { cc = unicode_get_cc(buf[i]); if (cc != 0) { @@ -815,7 +812,7 @@ static void to_nfd_rec(DynBuf *dbuf, uint32_t c, v; int i, l; uint32_t res[UNICODE_DECOMP_LEN_MAX]; - + for(i = 0; i < src_len; i++) { c = src[i]; if (c >= 0xac00 && c < 0xd7a4) { @@ -860,7 +857,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, int *buf, buf_len, i, p, starter_pos, cc, last_cc, out_len; BOOL is_compat; DynBuf dbuf_s, *dbuf = &dbuf_s; - + is_compat = n_type >> 1; dbuf_init2(dbuf, opaque, realloc_func); @@ -888,15 +885,15 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, } buf = (int *)dbuf->buf; buf_len = dbuf->size / sizeof(int); - + sort_cc(buf, buf_len); - + if (buf_len <= 1 || (n_type & 1) != 0) { /* NFD / NFKD */ *pdst = (uint32_t *)buf; return buf_len; } - + i = 1; out_len = 1; while (i < buf_len) { @@ -933,7 +930,7 @@ static int unicode_find_name(const char *name_table, const char *name) const char *p, *r; int pos; size_t name_len, len; - + p = name_table; pos = 0; name_len = strlen(name); @@ -966,13 +963,13 @@ int unicode_script(CharRange *cr, CharRange cr1_s, *cr1; CharRange cr2_s, *cr2 = &cr2_s; BOOL is_common; - + script_idx = unicode_find_name(unicode_script_name_table, script_name); if (script_idx < 0) return -2; /* Note: we remove the "Unknown" Script */ script_idx += UNICODE_SCRIPT_Unknown + 1; - + is_common = (script_idx == UNICODE_SCRIPT_Common || script_idx == UNICODE_SCRIPT_Inherited); if (is_ext) { @@ -1239,7 +1236,7 @@ static int unicode_case1(CharRange *cr, int case_mask) } return 0; } - + typedef enum { POP_GC, POP_PROP, @@ -1259,7 +1256,7 @@ static int unicode_prop_ops(CharRange *cr, ...) CharRange stack[POP_STACK_LEN_MAX]; int stack_len, op, ret, i; uint32_t a; - + va_start(ap, cr); stack_len = 0; for(;;) { @@ -1345,7 +1342,7 @@ int unicode_general_category(CharRange *cr, const char *gc_name) { int gc_idx; uint32_t gc_mask; - + gc_idx = unicode_find_name(unicode_gc_name_table, gc_name); if (gc_idx < 0) return -2; @@ -1363,7 +1360,7 @@ int unicode_general_category(CharRange *cr, const char *gc_name) int unicode_prop(CharRange *cr, const char *prop_name) { int prop_idx, ret; - + prop_idx = unicode_find_name(unicode_prop_name_table, prop_name); if (prop_idx < 0) return -2; diff --git a/quickjs/libunicode.h b/quickjs/libunicode.h index e974105..0acc209 100644 --- a/quickjs/libunicode.h +++ b/quickjs/libunicode.h @@ -1,6 +1,6 @@ /* * Unicode utilities - * + * * Copyright (c) 2017-2018 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,7 +24,7 @@ #ifndef LIBUNICODE_H #define LIBUNICODE_H -// #include +#include #define LRE_BOOL int /* for documentation purposes */ diff --git a/quickjs/mocked.c b/quickjs/mocked.c index 032a6a3..028a6d0 100644 --- a/quickjs/mocked.c +++ b/quickjs/mocked.c @@ -1,15 +1,12 @@ +#include +#include +int __wrap_fesetround(int _round) { return 0; } -#include "mocked.h" -#include "ckb_syscall_apis.h" - -int fesetround(int _round) { return 0; } - -int fegetround() { return 0; } - -struct tm *localtime_r(const time_t *a, struct tm *b) { - return 0; +int __wrap_gettimeofday(struct timeval *restrict tv, struct timezone *restrict tz) { + return 0; } -int gettimeofday(struct timeval *restrict tv, struct timezone *restrict tz) { + +struct tm *__wrap_localtime_r(const time_t *a, struct tm *b) { return 0; -} \ No newline at end of file +} diff --git a/quickjs/mocked.h b/quickjs/mocked.h index 478536d..25525fb 100644 --- a/quickjs/mocked.h +++ b/quickjs/mocked.h @@ -1,32 +1,4 @@ - - #ifndef __MOCKED_H__ #define __MOCKED_H__ -#define FE_TONEAREST 0 -#define assert(f) (void)(f) - -typedef unsigned long long suseconds_t; -typedef unsigned int time_t; - -struct tm { - int tm_gmtoff; -}; - -#ifndef _STRUCT_TIMEVAL -struct timeval { - time_t tv_sec; /* seconds */ - suseconds_t tv_usec; /* microseconds */ -}; -#endif - -struct timezone { - int tz_minuteswest; /* minutes west of Greenwich */ - int tz_dsttime; /* type of DST correction */ -}; - -int fesetround(int round); -int fegetround(); -struct tm *localtime_r(const time_t *timer, struct tm *buf); -int gettimeofday(struct timeval *restrict tv, struct timezone *restrict tz); #endif diff --git a/quickjs/qjs.c b/quickjs/qjs.c index d2c5188..9eaec38 100644 --- a/quickjs/qjs.c +++ b/quickjs/qjs.c @@ -23,19 +23,19 @@ * THE SOFTWARE. */ #include -#include "my_stdlib.h" #include -#include "my_stdio.h" #include #include #include #include -#include "my_malloc.h" +#include #include "cutils.h" #include "std_module.h" #include "ckb_module.h" #include "ckb_exec.h" #include "cmdopt.h" +#include "ckb_cell_fs.h" +#include "mocked.h" #define MAIN_FILE_NAME "main.js" #define MAIN_FILE_NAME_BC "main.bc" @@ -90,7 +90,6 @@ void js_std_loop(JSContext *ctx) { } int compile_from_file(JSContext *ctx) { - enable_local_access(1); char buf[1024 * 512]; int buf_len = read_local_file(buf, sizeof(buf)); if (buf_len < 0 || buf_len == sizeof(buf)) { @@ -117,7 +116,7 @@ int compile_from_file(JSContext *ctx) { uint32_t size = i + 32 > out_buf_len ? out_buf_len - i : 32; _exec_bin2hex(&out_buf[i], size, msg_buf, 65, &size, true); msg_buf[size - 1] = 0; - printf("%s", msg_buf); + printf("%s\n", msg_buf); } return 0; } @@ -182,8 +181,7 @@ int run_from_file_system_buf(JSContext *ctx, char *buf, size_t buf_size) { } static int run_from_local_file(JSContext *ctx, bool enable_fs) { - printf("Run from file, local access enabled. For Testing only."); - enable_local_access(1); + printf("Run from file, local access enabled. For Testing only.\n"); char buf[1024 * 512]; int count = read_local_file(buf, sizeof(buf)); if (count < 0 || count == sizeof(buf)) { @@ -280,13 +278,13 @@ static JSContext *JS_NewCustomContext(JSRuntime *rt) { } static const CMDOptDesc js_vm_options[] = { - { "h,help", 0, "show the help" }, - { "c", 0, "compile javascript to bytecode" }, - { "e", CMD_HAS_ARG, "run javascript from argument value" }, - { "r", 0, "read from file" }, - { "t", CMD_HAS_ARG, "specify target code_hash and hash_type in hex" }, - { "f", 0, "use file system" }, - { NULL }, + {"h,help", 0, "show the help"}, + {"c", 0, "compile javascript to bytecode"}, + {"e", CMD_HAS_ARG, "run javascript from argument value"}, + {"r", 0, "read from file"}, + {"t", CMD_HAS_ARG, "specify target code_hash and hash_type in hex"}, + {"f", 0, "use file system"}, + {NULL}, }; int main(int argc, const char **argv) { @@ -358,9 +356,9 @@ int main(int argc, const char **argv) { #ifdef MEMORY_USAGE size_t heap_usage = malloc_usage(); - printf("Total bytes used by allocator(malloc/realloc) is %d K", heap_usage / 1024); + printf("Total bytes used by allocator(malloc/realloc) is %d K\n", heap_usage / 1024); size_t stack_usage = JS_GetStackPeak(); - printf("Total bytes used by stack(peak value) is %d K", (4 * 1024 * 1024 - stack_usage) / 1024); + printf("Total bytes used by stack(peak value) is %d K\n", (4 * 1024 * 1024 - stack_usage) / 1024); #endif exit: diff --git a/quickjs/quickjs-libc.c.removed b/quickjs/quickjs-libc.c.removed deleted file mode 100644 index cedd6b8..0000000 --- a/quickjs/quickjs-libc.c.removed +++ /dev/null @@ -1,3932 +0,0 @@ -/* - * QuickJS C library - * - * 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 -#include "my_stdlib.h" -#include -#include "my_stdio.h" -#include -// #include -#include -#include -#include "my_string.h" -// #include -#include "my_assert.h" -// #include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(_WIN32) -#include -#include -#include -#else -#include -#include -#include -#include - -#if defined(__APPLE__) -typedef sig_t sighandler_t; -#if !defined(environ) -#include -#define environ (*_NSGetEnviron()) -#endif -#endif /* __APPLE__ */ - -#endif - -#if !defined(_WIN32) -/* enable the os.Worker API. IT relies on POSIX threads */ -#define USE_WORKER -#endif - -#ifdef USE_WORKER -#include -#include -#endif - -#include "cutils.h" -#include "list.h" -#include "quickjs-libc.h" - -/* TODO: - - add socket calls -*/ - -typedef struct { - struct list_head link; - int fd; - JSValue rw_func[2]; -} JSOSRWHandler; - -typedef struct { - struct list_head link; - int sig_num; - JSValue func; -} JSOSSignalHandler; - -typedef struct { - struct list_head link; - BOOL has_object; - int64_t timeout; - JSValue func; -} JSOSTimer; - -typedef struct { - struct list_head link; - uint8_t *data; - size_t data_len; - /* list of SharedArrayBuffers, necessary to free the message */ - uint8_t **sab_tab; - size_t sab_tab_len; -} JSWorkerMessage; - -typedef struct { - int ref_count; -#ifdef USE_WORKER - pthread_mutex_t mutex; -#endif - struct list_head msg_queue; /* list of JSWorkerMessage.link */ - int read_fd; - int write_fd; -} JSWorkerMessagePipe; - -typedef struct { - struct list_head link; - JSWorkerMessagePipe *recv_pipe; - JSValue on_message_func; -} JSWorkerMessageHandler; - -typedef struct JSThreadState { - struct list_head os_rw_handlers; /* list of JSOSRWHandler.link */ - struct list_head os_signal_handlers; /* list JSOSSignalHandler.link */ - struct list_head os_timers; /* list of JSOSTimer.link */ - struct list_head port_list; /* list of JSWorkerMessageHandler.link */ - int eval_script_recurse; /* only used in the main thread */ - /* not used in the main thread */ - JSWorkerMessagePipe *recv_pipe, *send_pipe; -} JSThreadState; - -static uint64_t os_pending_signals; -static int (*os_poll_func)(JSContext *ctx); - -static void js_std_dbuf_init(JSContext *ctx, DynBuf *s) -{ - dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc *)js_realloc_rt); -} - -static BOOL my_isdigit(int c) -{ - return (c >= '0' && c <= '9'); -} - -static JSValue js_printf_internal(JSContext *ctx, - int argc, JSValueConst *argv, FILE *fp) -{ - char fmtbuf[32]; - uint8_t cbuf[UTF8_CHAR_LEN_MAX+1]; - JSValue res; - DynBuf dbuf; - const char *fmt_str; - const uint8_t *fmt, *fmt_end; - const uint8_t *p; - char *q; - int i, c, len, mod; - size_t fmt_len; - int32_t int32_arg; - int64_t int64_arg; - double double_arg; - const char *string_arg; - /* Use indirect call to dbuf_printf to prevent gcc warning */ - int (*dbuf_printf_fun)(DynBuf *s, const char *fmt, ...) = (void*)dbuf_printf; - - js_std_dbuf_init(ctx, &dbuf); - - if (argc > 0) { - fmt_str = JS_ToCStringLen(ctx, &fmt_len, argv[0]); - if (!fmt_str) - goto fail; - - i = 1; - fmt = (const uint8_t *)fmt_str; - fmt_end = fmt + fmt_len; - while (fmt < fmt_end) { - for (p = fmt; fmt < fmt_end && *fmt != '%'; fmt++) - continue; - dbuf_put(&dbuf, p, fmt - p); - if (fmt >= fmt_end) - break; - q = fmtbuf; - *q++ = *fmt++; /* copy '%' */ - - /* flags */ - for(;;) { - c = *fmt; - if (c == '0' || c == '#' || c == '+' || c == '-' || c == ' ' || - c == '\'') { - if (q >= fmtbuf + sizeof(fmtbuf) - 1) - goto invalid; - *q++ = c; - fmt++; - } else { - break; - } - } - /* width */ - if (*fmt == '*') { - if (i >= argc) - goto missing; - if (JS_ToInt32(ctx, &int32_arg, argv[i++])) - goto fail; - q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg); - fmt++; - } else { - while (my_isdigit(*fmt)) { - if (q >= fmtbuf + sizeof(fmtbuf) - 1) - goto invalid; - *q++ = *fmt++; - } - } - if (*fmt == '.') { - if (q >= fmtbuf + sizeof(fmtbuf) - 1) - goto invalid; - *q++ = *fmt++; - if (*fmt == '*') { - if (i >= argc) - goto missing; - if (JS_ToInt32(ctx, &int32_arg, argv[i++])) - goto fail; - q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg); - fmt++; - } else { - while (my_isdigit(*fmt)) { - if (q >= fmtbuf + sizeof(fmtbuf) - 1) - goto invalid; - *q++ = *fmt++; - } - } - } - - /* we only support the "l" modifier for 64 bit numbers */ - mod = ' '; - if (*fmt == 'l') { - mod = *fmt++; - } - - /* type */ - c = *fmt++; - if (q >= fmtbuf + sizeof(fmtbuf) - 1) - goto invalid; - *q++ = c; - *q = '\0'; - - switch (c) { - case 'c': - if (i >= argc) - goto missing; - if (JS_IsString(argv[i])) { - string_arg = JS_ToCString(ctx, argv[i++]); - if (!string_arg) - goto fail; - int32_arg = unicode_from_utf8((uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p); - JS_FreeCString(ctx, string_arg); - } else { - if (JS_ToInt32(ctx, &int32_arg, argv[i++])) - goto fail; - } - /* handle utf-8 encoding explicitly */ - if ((unsigned)int32_arg > 0x10FFFF) - int32_arg = 0xFFFD; - /* ignore conversion flags, width and precision */ - len = unicode_to_utf8(cbuf, int32_arg); - dbuf_put(&dbuf, cbuf, len); - break; - - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - if (i >= argc) - goto missing; - if (JS_ToInt64Ext(ctx, &int64_arg, argv[i++])) - goto fail; - if (mod == 'l') { - /* 64 bit number */ -#if defined(_WIN32) - if (q >= fmtbuf + sizeof(fmtbuf) - 3) - goto invalid; - q[2] = q[-1]; - q[-1] = 'I'; - q[0] = '6'; - q[1] = '4'; - q[3] = '\0'; - dbuf_printf_fun(&dbuf, fmtbuf, (int64_t)int64_arg); -#else - if (q >= fmtbuf + sizeof(fmtbuf) - 2) - goto invalid; - q[1] = q[-1]; - q[-1] = q[0] = 'l'; - q[2] = '\0'; - dbuf_printf_fun(&dbuf, fmtbuf, (long long)int64_arg); -#endif - } else { - dbuf_printf_fun(&dbuf, fmtbuf, (int)int64_arg); - } - break; - - case 's': - if (i >= argc) - goto missing; - /* XXX: handle strings containing null characters */ - string_arg = JS_ToCString(ctx, argv[i++]); - if (!string_arg) - goto fail; - dbuf_printf_fun(&dbuf, fmtbuf, string_arg); - JS_FreeCString(ctx, string_arg); - break; - - case 'e': - case 'f': - case 'g': - case 'a': - case 'E': - case 'F': - case 'G': - case 'A': - if (i >= argc) - goto missing; - if (JS_ToFloat64(ctx, &double_arg, argv[i++])) - goto fail; - dbuf_printf_fun(&dbuf, fmtbuf, double_arg); - break; - - case '%': - dbuf_putc(&dbuf, '%'); - break; - - default: - /* XXX: should support an extension mechanism */ - invalid: - JS_ThrowTypeError(ctx, "invalid conversion specifier in format string"); - goto fail; - missing: - JS_ThrowReferenceError(ctx, "missing argument for conversion specifier"); - goto fail; - } - } - JS_FreeCString(ctx, fmt_str); - } - if (dbuf.error) { - res = JS_ThrowOutOfMemory(ctx); - } else { - if (fp) { - len = fwrite(dbuf.buf, 1, dbuf.size, fp); - res = JS_NewInt32(ctx, len); - } else { - res = JS_NewStringLen(ctx, (char *)dbuf.buf, dbuf.size); - } - } - dbuf_free(&dbuf); - return res; - -fail: - dbuf_free(&dbuf); - return JS_EXCEPTION; -} - -uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) -{ - FILE *f; - uint8_t *buf; - size_t buf_len; - long lret; - - f = fopen(filename, "rb"); - if (!f) - return NULL; - if (fseek(f, 0, SEEK_END) < 0) - goto fail; - lret = ftell(f); - if (lret < 0) - goto fail; - /* XXX: on Linux, ftell() return LONG_MAX for directories */ - if (lret == LONG_MAX) { - errno = EISDIR; - goto fail; - } - buf_len = lret; - if (fseek(f, 0, SEEK_SET) < 0) - goto fail; - if (ctx) - buf = js_malloc(ctx, buf_len + 1); - else - buf = malloc(buf_len + 1); - if (!buf) - goto fail; - if (fread(buf, 1, buf_len, f) != buf_len) { - errno = EIO; - if (ctx) - js_free(ctx, buf); - else - free(buf); - fail: - fclose(f); - return NULL; - } - buf[buf_len] = '\0'; - fclose(f); - *pbuf_len = buf_len; - return buf; -} - -/* load and evaluate a file */ -static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - uint8_t *buf; - const char *filename; - JSValue ret; - size_t buf_len; - - filename = JS_ToCString(ctx, argv[0]); - if (!filename) - return JS_EXCEPTION; - buf = js_load_file(ctx, &buf_len, filename); - if (!buf) { - JS_ThrowReferenceError(ctx, "could not load '%s'", filename); - JS_FreeCString(ctx, filename); - return JS_EXCEPTION; - } - ret = JS_Eval(ctx, (char *)buf, buf_len, filename, - JS_EVAL_TYPE_GLOBAL); - js_free(ctx, buf); - JS_FreeCString(ctx, filename); - return ret; -} - -/* load a file as a UTF-8 encoded string */ -static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - uint8_t *buf; - const char *filename; - JSValue ret; - size_t buf_len; - - filename = JS_ToCString(ctx, argv[0]); - if (!filename) - return JS_EXCEPTION; - buf = js_load_file(ctx, &buf_len, filename); - JS_FreeCString(ctx, filename); - if (!buf) - return JS_NULL; - ret = JS_NewStringLen(ctx, (char *)buf, buf_len); - js_free(ctx, buf); - return ret; -} - -typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx, - const char *module_name); - - -#if defined(_WIN32) -static JSModuleDef *js_module_loader_so(JSContext *ctx, - const char *module_name) -{ - JS_ThrowReferenceError(ctx, "shared library modules are not supported yet"); - return NULL; -} -#else -static JSModuleDef *js_module_loader_so(JSContext *ctx, - const char *module_name) -{ - JSModuleDef *m; - void *hd; - JSInitModuleFunc *init; - char *filename; - - if (!strchr(module_name, '/')) { - /* must add a '/' so that the DLL is not searched in the - system library paths */ - filename = js_malloc(ctx, strlen(module_name) + 2 + 1); - if (!filename) - return NULL; - strcpy(filename, "./"); - strcpy(filename + 2, module_name); - } else { - filename = (char *)module_name; - } - - /* C module */ - hd = dlopen(filename, RTLD_NOW | RTLD_LOCAL); - if (filename != module_name) - js_free(ctx, filename); - if (!hd) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library", - module_name); - goto fail; - } - - init = dlsym(hd, "js_init_module"); - if (!init) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s': js_init_module not found", - module_name); - goto fail; - } - - m = init(ctx, module_name); - if (!m) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s': initialization error", - module_name); - fail: - if (hd) - dlclose(hd); - return NULL; - } - return m; -} -#endif /* !_WIN32 */ - -int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, - JS_BOOL use_realpath, JS_BOOL is_main) -{ - JSModuleDef *m; - char buf[PATH_MAX + 16]; - JSValue meta_obj; - JSAtom module_name_atom; - const char *module_name; - - assert(JS_VALUE_GET_TAG(func_val) == JS_TAG_MODULE); - m = JS_VALUE_GET_PTR(func_val); - - module_name_atom = JS_GetModuleName(ctx, m); - module_name = JS_AtomToCString(ctx, module_name_atom); - JS_FreeAtom(ctx, module_name_atom); - if (!module_name) - return -1; - if (!strchr(module_name, ':')) { - strcpy(buf, "file://"); -#if !defined(_WIN32) - /* realpath() cannot be used with modules compiled with qjsc - because the corresponding module source code is not - necessarily present */ - if (use_realpath) { - char *res = realpath(module_name, buf + strlen(buf)); - if (!res) { - JS_ThrowTypeError(ctx, "realpath failure"); - JS_FreeCString(ctx, module_name); - return -1; - } - } else -#endif - { - pstrcat(buf, sizeof(buf), module_name); - } - } else { - pstrcpy(buf, sizeof(buf), module_name); - } - JS_FreeCString(ctx, module_name); - - meta_obj = JS_GetImportMeta(ctx, m); - if (JS_IsException(meta_obj)) - return -1; - JS_DefinePropertyValueStr(ctx, meta_obj, "url", - JS_NewString(ctx, buf), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, meta_obj, "main", - JS_NewBool(ctx, is_main), - JS_PROP_C_W_E); - JS_FreeValue(ctx, meta_obj); - return 0; -} - -JSModuleDef *js_module_loader(JSContext *ctx, - const char *module_name, void *opaque) -{ - JSModuleDef *m; - - if (has_suffix(module_name, ".so")) { - m = js_module_loader_so(ctx, module_name); - } else { - size_t buf_len; - uint8_t *buf; - JSValue func_val; - - 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; - /* XXX: could propagate the exception */ - js_module_set_import_meta(ctx, func_val, TRUE, FALSE); - /* 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 JSValue js_std_exit(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int status; - if (JS_ToInt32(ctx, &status, argv[0])) - status = -1; - exit(status); - return JS_UNDEFINED; -} - -static JSValue js_std_getenv(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *name, *str; - name = JS_ToCString(ctx, argv[0]); - if (!name) - return JS_EXCEPTION; - str = getenv(name); - JS_FreeCString(ctx, name); - if (!str) - return JS_UNDEFINED; - else - return JS_NewString(ctx, str); -} - -#if defined(_WIN32) -static void setenv(const char *name, const char *value, int overwrite) -{ - char *str; - size_t name_len, value_len; - name_len = strlen(name); - value_len = strlen(value); - str = malloc(name_len + 1 + value_len + 1); - memcpy(str, name, name_len); - str[name_len] = '='; - memcpy(str + name_len + 1, value, value_len); - str[name_len + 1 + value_len] = '\0'; - _putenv(str); - free(str); -} - -static void unsetenv(const char *name) -{ - setenv(name, "", TRUE); -} -#endif /* _WIN32 */ - -static JSValue js_std_setenv(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *name, *value; - name = JS_ToCString(ctx, argv[0]); - if (!name) - return JS_EXCEPTION; - value = JS_ToCString(ctx, argv[1]); - if (!value) { - JS_FreeCString(ctx, name); - return JS_EXCEPTION; - } - setenv(name, value, TRUE); - JS_FreeCString(ctx, name); - JS_FreeCString(ctx, value); - return JS_UNDEFINED; -} - -static JSValue js_std_unsetenv(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *name; - name = JS_ToCString(ctx, argv[0]); - if (!name) - return JS_EXCEPTION; - unsetenv(name); - JS_FreeCString(ctx, name); - return JS_UNDEFINED; -} - -/* return an object containing the list of the available environment - variables. */ -static JSValue js_std_getenviron(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - char **envp; - const char *name, *p, *value; - JSValue obj; - uint32_t idx; - size_t name_len; - JSAtom atom; - int ret; - - obj = JS_NewObject(ctx); - if (JS_IsException(obj)) - return JS_EXCEPTION; - envp = environ; - for(idx = 0; envp[idx] != NULL; idx++) { - name = envp[idx]; - p = strchr(name, '='); - name_len = p - name; - if (!p) - continue; - value = p + 1; - atom = JS_NewAtomLen(ctx, name, name_len); - if (atom == JS_ATOM_NULL) - goto fail; - ret = JS_DefinePropertyValue(ctx, obj, atom, JS_NewString(ctx, value), - JS_PROP_C_W_E); - JS_FreeAtom(ctx, atom); - if (ret < 0) - goto fail; - } - return obj; - fail: - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - -static JSValue js_std_gc(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JS_RunGC(JS_GetRuntime(ctx)); - return JS_UNDEFINED; -} - -static int interrupt_handler(JSRuntime *rt, void *opaque) -{ - return (os_pending_signals >> SIGINT) & 1; -} - -static int get_bool_option(JSContext *ctx, BOOL *pbool, - JSValueConst obj, - const char *option) -{ - JSValue val; - val = JS_GetPropertyStr(ctx, obj, option); - if (JS_IsException(val)) - return -1; - if (!JS_IsUndefined(val)) { - *pbool = JS_ToBool(ctx, val); - } - JS_FreeValue(ctx, val); - return 0; -} - -static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - const char *str; - size_t len; - JSValue ret; - JSValueConst options_obj; - BOOL backtrace_barrier = FALSE; - int flags; - - if (argc >= 2) { - options_obj = argv[1]; - if (get_bool_option(ctx, &backtrace_barrier, options_obj, - "backtrace_barrier")) - return JS_EXCEPTION; - } - - str = JS_ToCStringLen(ctx, &len, argv[0]); - if (!str) - return JS_EXCEPTION; - if (!ts->recv_pipe && ++ts->eval_script_recurse == 1) { - /* install the interrupt handler */ - JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL); - } - flags = JS_EVAL_TYPE_GLOBAL; - if (backtrace_barrier) - flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER; - ret = JS_Eval(ctx, str, len, "", flags); - JS_FreeCString(ctx, str); - if (!ts->recv_pipe && --ts->eval_script_recurse == 0) { - /* remove the interrupt handler */ - JS_SetInterruptHandler(JS_GetRuntime(ctx), NULL, NULL); - os_pending_signals &= ~((uint64_t)1 << SIGINT); - /* convert the uncatchable "interrupted" error into a normal error - so that it can be caught by the REPL */ - if (JS_IsException(ret)) - JS_ResetUncatchableError(ctx); - } - return ret; -} - -static JSClassID js_std_file_class_id; - -typedef struct { - FILE *f; - BOOL close_in_finalizer; - BOOL is_popen; -} JSSTDFile; - -static void js_std_file_finalizer(JSRuntime *rt, JSValue val) -{ - JSSTDFile *s = JS_GetOpaque(val, js_std_file_class_id); - if (s) { - if (s->f && s->close_in_finalizer) { - if (s->is_popen) - pclose(s->f); - else - fclose(s->f); - } - js_free_rt(rt, s); - } -} - -static ssize_t js_get_errno(ssize_t ret) -{ - if (ret == -1) - ret = -errno; - return ret; -} - -static JSValue js_std_strerror(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int err; - if (JS_ToInt32(ctx, &err, argv[0])) - return JS_EXCEPTION; - return JS_NewString(ctx, strerror(err)); -} - -static JSValue js_std_parseExtJSON(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue obj; - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - if (!str) - return JS_EXCEPTION; - obj = JS_ParseJSON2(ctx, str, len, "", JS_PARSE_JSON_EXT); - JS_FreeCString(ctx, str); - return obj; -} - -static JSValue js_new_std_file(JSContext *ctx, FILE *f, - BOOL close_in_finalizer, - BOOL is_popen) -{ - JSSTDFile *s; - JSValue obj; - obj = JS_NewObjectClass(ctx, js_std_file_class_id); - if (JS_IsException(obj)) - return obj; - s = js_mallocz(ctx, sizeof(*s)); - if (!s) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - s->close_in_finalizer = close_in_finalizer; - s->is_popen = is_popen; - s->f = f; - JS_SetOpaque(obj, s); - return obj; -} - -static void js_set_error_object(JSContext *ctx, JSValue obj, int err) -{ - if (!JS_IsUndefined(obj)) { - JS_SetPropertyStr(ctx, obj, "errno", JS_NewInt32(ctx, err)); - } -} - -static JSValue js_std_open(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *filename, *mode = NULL; - FILE *f; - int err; - - filename = JS_ToCString(ctx, argv[0]); - if (!filename) - goto fail; - mode = JS_ToCString(ctx, argv[1]); - if (!mode) - goto fail; - if (mode[strspn(mode, "rwa+b")] != '\0') { - JS_ThrowTypeError(ctx, "invalid file mode"); - goto fail; - } - - f = fopen(filename, mode); - if (!f) - err = errno; - else - err = 0; - if (argc >= 3) - js_set_error_object(ctx, argv[2], err); - JS_FreeCString(ctx, filename); - JS_FreeCString(ctx, mode); - if (!f) - return JS_NULL; - return js_new_std_file(ctx, f, TRUE, FALSE); - fail: - JS_FreeCString(ctx, filename); - JS_FreeCString(ctx, mode); - return JS_EXCEPTION; -} - -static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *filename, *mode = NULL; - FILE *f; - int err; - - filename = JS_ToCString(ctx, argv[0]); - if (!filename) - goto fail; - mode = JS_ToCString(ctx, argv[1]); - if (!mode) - goto fail; - if (mode[strspn(mode, "rw")] != '\0') { - JS_ThrowTypeError(ctx, "invalid file mode"); - goto fail; - } - - f = popen(filename, mode); - if (!f) - err = errno; - else - err = 0; - if (argc >= 3) - js_set_error_object(ctx, argv[2], err); - JS_FreeCString(ctx, filename); - JS_FreeCString(ctx, mode); - if (!f) - return JS_NULL; - return js_new_std_file(ctx, f, TRUE, TRUE); - fail: - JS_FreeCString(ctx, filename); - JS_FreeCString(ctx, mode); - return JS_EXCEPTION; -} - -static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *mode; - FILE *f; - int fd, err; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - mode = JS_ToCString(ctx, argv[1]); - if (!mode) - goto fail; - if (mode[strspn(mode, "rwa+")] != '\0') { - JS_ThrowTypeError(ctx, "invalid file mode"); - goto fail; - } - - f = fdopen(fd, mode); - if (!f) - err = errno; - else - err = 0; - if (argc >= 3) - js_set_error_object(ctx, argv[2], err); - JS_FreeCString(ctx, mode); - if (!f) - return JS_NULL; - return js_new_std_file(ctx, f, TRUE, FALSE); - fail: - JS_FreeCString(ctx, mode); - return JS_EXCEPTION; -} - -static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f; - f = tmpfile(); - if (argc >= 1) - js_set_error_object(ctx, argv[0], f ? 0 : errno); - if (!f) - return JS_NULL; - return js_new_std_file(ctx, f, TRUE, FALSE); -} - -static JSValue js_std_sprintf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return js_printf_internal(ctx, argc, argv, NULL); -} - -static JSValue js_std_printf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return js_printf_internal(ctx, argc, argv, stdout); -} - -static FILE *js_std_file_get(JSContext *ctx, JSValueConst obj) -{ - JSSTDFile *s = JS_GetOpaque2(ctx, obj, js_std_file_class_id); - if (!s) - return NULL; - if (!s->f) { - JS_ThrowTypeError(ctx, "invalid file handle"); - return NULL; - } - return s->f; -} - -static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - FILE *f; - int i; - const char *str; - size_t len; - - if (magic == 0) { - f = stdout; - } else { - f = js_std_file_get(ctx, this_val); - if (!f) - return JS_EXCEPTION; - } - - for(i = 0; i < argc; i++) { - str = JS_ToCStringLen(ctx, &len, argv[i]); - if (!str) - return JS_EXCEPTION; - fwrite(str, 1, len, f); - JS_FreeCString(ctx, str); - } - return JS_UNDEFINED; -} - -static JSValue js_std_file_close(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSSTDFile *s = JS_GetOpaque2(ctx, this_val, js_std_file_class_id); - int err; - if (!s) - return JS_EXCEPTION; - if (!s->f) - return JS_ThrowTypeError(ctx, "invalid file handle"); - if (s->is_popen) - err = js_get_errno(pclose(s->f)); - else - err = js_get_errno(fclose(s->f)); - s->f = NULL; - return JS_NewInt32(ctx, err); -} - -static JSValue js_std_file_printf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - if (!f) - return JS_EXCEPTION; - return js_printf_internal(ctx, argc, argv, f); -} - -static JSValue js_std_file_flush(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - if (!f) - return JS_EXCEPTION; - fflush(f); - return JS_UNDEFINED; -} - -static JSValue js_std_file_tell(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int is_bigint) -{ - FILE *f = js_std_file_get(ctx, this_val); - int64_t pos; - if (!f) - return JS_EXCEPTION; -#if defined(__linux__) - pos = ftello(f); -#else - pos = ftell(f); -#endif - if (is_bigint) - return JS_NewBigInt64(ctx, pos); - else - return JS_NewInt64(ctx, pos); -} - -static JSValue js_std_file_seek(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - int64_t pos; - int whence, ret; - if (!f) - return JS_EXCEPTION; - if (JS_ToInt64Ext(ctx, &pos, argv[0])) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &whence, argv[1])) - return JS_EXCEPTION; -#if defined(__linux__) - ret = fseeko(f, pos, whence); -#else - ret = fseek(f, pos, whence); -#endif - if (ret < 0) - ret = -errno; - return JS_NewInt32(ctx, ret); -} - -static JSValue js_std_file_eof(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - if (!f) - return JS_EXCEPTION; - return JS_NewBool(ctx, feof(f)); -} - -static JSValue js_std_file_error(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - if (!f) - return JS_EXCEPTION; - return JS_NewBool(ctx, ferror(f)); -} - -static JSValue js_std_file_clearerr(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - if (!f) - return JS_EXCEPTION; - clearerr(f); - return JS_UNDEFINED; -} - -static JSValue js_std_file_fileno(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - if (!f) - return JS_EXCEPTION; - return JS_NewInt32(ctx, fileno(f)); -} - -static JSValue js_std_file_read_write(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - FILE *f = js_std_file_get(ctx, this_val); - uint64_t pos, len; - size_t size, ret; - uint8_t *buf; - - if (!f) - return JS_EXCEPTION; - if (JS_ToIndex(ctx, &pos, argv[1])) - return JS_EXCEPTION; - if (JS_ToIndex(ctx, &len, argv[2])) - return JS_EXCEPTION; - buf = JS_GetArrayBuffer(ctx, &size, argv[0]); - if (!buf) - return JS_EXCEPTION; - if (pos + len > size) - return JS_ThrowRangeError(ctx, "read/write array buffer overflow"); - if (magic) - ret = fwrite(buf + pos, 1, len, f); - else - ret = fread(buf + pos, 1, len, f); - return JS_NewInt64(ctx, ret); -} - -/* XXX: could use less memory and go faster */ -static JSValue js_std_file_getline(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - int c; - DynBuf dbuf; - JSValue obj; - - if (!f) - return JS_EXCEPTION; - - js_std_dbuf_init(ctx, &dbuf); - for(;;) { - c = fgetc(f); - if (c == EOF) { - if (dbuf.size == 0) { - /* EOF */ - dbuf_free(&dbuf); - return JS_NULL; - } else { - break; - } - } - if (c == '\n') - break; - if (dbuf_putc(&dbuf, c)) { - dbuf_free(&dbuf); - return JS_ThrowOutOfMemory(ctx); - } - } - obj = JS_NewStringLen(ctx, (const char *)dbuf.buf, dbuf.size); - dbuf_free(&dbuf); - return obj; -} - -/* XXX: could use less memory and go faster */ -static JSValue js_std_file_readAsString(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - int c; - DynBuf dbuf; - JSValue obj; - uint64_t max_size64; - size_t max_size; - JSValueConst max_size_val; - - if (!f) - return JS_EXCEPTION; - - if (argc >= 1) - max_size_val = argv[0]; - else - max_size_val = JS_UNDEFINED; - max_size = (size_t)-1; - if (!JS_IsUndefined(max_size_val)) { - if (JS_ToIndex(ctx, &max_size64, max_size_val)) - return JS_EXCEPTION; - if (max_size64 < max_size) - max_size = max_size64; - } - - js_std_dbuf_init(ctx, &dbuf); - while (max_size != 0) { - c = fgetc(f); - if (c == EOF) - break; - if (dbuf_putc(&dbuf, c)) { - dbuf_free(&dbuf); - return JS_EXCEPTION; - } - max_size--; - } - obj = JS_NewStringLen(ctx, (const char *)dbuf.buf, dbuf.size); - dbuf_free(&dbuf); - return obj; -} - -static JSValue js_std_file_getByte(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - if (!f) - return JS_EXCEPTION; - return JS_NewInt32(ctx, fgetc(f)); -} - -static JSValue js_std_file_putByte(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - FILE *f = js_std_file_get(ctx, this_val); - int c; - if (!f) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &c, argv[0])) - return JS_EXCEPTION; - c = fputc(c, f); - return JS_NewInt32(ctx, c); -} - -/* urlGet */ - -#define URL_GET_PROGRAM "curl -s -i" -#define URL_GET_BUF_SIZE 4096 - -static int http_get_header_line(FILE *f, char *buf, size_t buf_size, - DynBuf *dbuf) -{ - int c; - char *p; - - p = buf; - for(;;) { - c = fgetc(f); - if (c < 0) - return -1; - if ((p - buf) < buf_size - 1) - *p++ = c; - if (dbuf) - dbuf_putc(dbuf, c); - if (c == '\n') - break; - } - *p = '\0'; - return 0; -} - -static int http_get_status(const char *buf) -{ - const char *p = buf; - while (*p != ' ' && *p != '\0') - p++; - if (*p != ' ') - return 0; - while (*p == ' ') - p++; - return atoi(p); -} - -static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *url; - DynBuf cmd_buf; - DynBuf data_buf_s, *data_buf = &data_buf_s; - DynBuf header_buf_s, *header_buf = &header_buf_s; - char *buf; - size_t i, len; - int c, status; - JSValue response = JS_UNDEFINED, ret_obj; - JSValueConst options_obj; - FILE *f; - BOOL binary_flag, full_flag; - - url = JS_ToCString(ctx, argv[0]); - if (!url) - return JS_EXCEPTION; - - binary_flag = FALSE; - full_flag = FALSE; - - if (argc >= 2) { - options_obj = argv[1]; - - if (get_bool_option(ctx, &binary_flag, options_obj, "binary")) - goto fail_obj; - - if (get_bool_option(ctx, &full_flag, options_obj, "full")) { - fail_obj: - JS_FreeCString(ctx, url); - return JS_EXCEPTION; - } - } - - js_std_dbuf_init(ctx, &cmd_buf); - dbuf_printf(&cmd_buf, "%s ''", URL_GET_PROGRAM); - len = strlen(url); - for(i = 0; i < len; i++) { - c = url[i]; - if (c == '\'' || c == '\\') - dbuf_putc(&cmd_buf, '\\'); - dbuf_putc(&cmd_buf, c); - } - JS_FreeCString(ctx, url); - dbuf_putstr(&cmd_buf, "''"); - dbuf_putc(&cmd_buf, '\0'); - if (dbuf_error(&cmd_buf)) { - dbuf_free(&cmd_buf); - return JS_EXCEPTION; - } - // printf("%s\n", (char *)cmd_buf.buf); - f = popen((char *)cmd_buf.buf, "r"); - dbuf_free(&cmd_buf); - if (!f) { - return JS_ThrowTypeError(ctx, "could not start curl"); - } - - js_std_dbuf_init(ctx, data_buf); - js_std_dbuf_init(ctx, header_buf); - - buf = js_malloc(ctx, URL_GET_BUF_SIZE); - if (!buf) - goto fail; - - /* get the HTTP status */ - if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, NULL) < 0) { - status = 0; - goto bad_header; - } - status = http_get_status(buf); - if (!full_flag && !(status >= 200 && status <= 299)) { - goto bad_header; - } - - /* wait until there is an empty line */ - for(;;) { - if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, header_buf) < 0) { - bad_header: - response = JS_NULL; - goto done; - } - if (!strcmp(buf, "\r\n")) - break; - } - if (dbuf_error(header_buf)) - goto fail; - header_buf->size -= 2; /* remove the trailing CRLF */ - - /* download the data */ - for(;;) { - len = fread(buf, 1, URL_GET_BUF_SIZE, f); - if (len == 0) - break; - dbuf_put(data_buf, (uint8_t *)buf, len); - } - if (dbuf_error(data_buf)) - goto fail; - if (binary_flag) { - response = JS_NewArrayBufferCopy(ctx, - data_buf->buf, data_buf->size); - } else { - response = JS_NewStringLen(ctx, (char *)data_buf->buf, data_buf->size); - } - if (JS_IsException(response)) - goto fail; - done: - js_free(ctx, buf); - buf = NULL; - pclose(f); - f = NULL; - dbuf_free(data_buf); - data_buf = NULL; - - if (full_flag) { - ret_obj = JS_NewObject(ctx); - if (JS_IsException(ret_obj)) - goto fail; - JS_DefinePropertyValueStr(ctx, ret_obj, "response", - response, - JS_PROP_C_W_E); - if (!JS_IsNull(response)) { - JS_DefinePropertyValueStr(ctx, ret_obj, "responseHeaders", - JS_NewStringLen(ctx, (char *)header_buf->buf, - header_buf->size), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, ret_obj, "status", - JS_NewInt32(ctx, status), - JS_PROP_C_W_E); - } - } else { - ret_obj = response; - } - dbuf_free(header_buf); - return ret_obj; - fail: - if (f) - pclose(f); - js_free(ctx, buf); - if (data_buf) - dbuf_free(data_buf); - if (header_buf) - dbuf_free(header_buf); - JS_FreeValue(ctx, response); - return JS_EXCEPTION; -} - -static JSClassDef js_std_file_class = { - "FILE", - .finalizer = js_std_file_finalizer, -}; - -static const JSCFunctionListEntry js_std_error_props[] = { - /* various errno values */ -#define DEF(x) JS_PROP_INT32_DEF(#x, x, JS_PROP_CONFIGURABLE ) - DEF(EINVAL), - DEF(EIO), - DEF(EACCES), - DEF(EEXIST), - DEF(ENOSPC), - DEF(ENOSYS), - DEF(EBUSY), - DEF(ENOENT), - DEF(EPERM), - DEF(EPIPE), - DEF(EBADF), -#undef DEF -}; - -static const JSCFunctionListEntry js_std_funcs[] = { - JS_CFUNC_DEF("exit", 1, js_std_exit ), - JS_CFUNC_DEF("gc", 0, js_std_gc ), - JS_CFUNC_DEF("evalScript", 1, js_evalScript ), - JS_CFUNC_DEF("loadScript", 1, js_loadScript ), - JS_CFUNC_DEF("getenv", 1, js_std_getenv ), - JS_CFUNC_DEF("setenv", 1, js_std_setenv ), - JS_CFUNC_DEF("unsetenv", 1, js_std_unsetenv ), - JS_CFUNC_DEF("getenviron", 1, js_std_getenviron ), - JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ), - JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ), - JS_CFUNC_DEF("strerror", 1, js_std_strerror ), - JS_CFUNC_DEF("parseExtJSON", 1, js_std_parseExtJSON ), - - /* FILE I/O */ - JS_CFUNC_DEF("open", 2, js_std_open ), - JS_CFUNC_DEF("popen", 2, js_std_popen ), - JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ), - JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ), - JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ), - JS_CFUNC_DEF("printf", 1, js_std_printf ), - JS_CFUNC_DEF("sprintf", 1, js_std_sprintf ), - JS_PROP_INT32_DEF("SEEK_SET", SEEK_SET, JS_PROP_CONFIGURABLE ), - JS_PROP_INT32_DEF("SEEK_CUR", SEEK_CUR, JS_PROP_CONFIGURABLE ), - JS_PROP_INT32_DEF("SEEK_END", SEEK_END, JS_PROP_CONFIGURABLE ), - JS_OBJECT_DEF("Error", js_std_error_props, countof(js_std_error_props), JS_PROP_CONFIGURABLE), -}; - -static const JSCFunctionListEntry js_std_file_proto_funcs[] = { - JS_CFUNC_DEF("close", 0, js_std_file_close ), - JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 1 ), - JS_CFUNC_DEF("printf", 1, js_std_file_printf ), - JS_CFUNC_DEF("flush", 0, js_std_file_flush ), - JS_CFUNC_MAGIC_DEF("tell", 0, js_std_file_tell, 0 ), - JS_CFUNC_MAGIC_DEF("tello", 0, js_std_file_tell, 1 ), - JS_CFUNC_DEF("seek", 2, js_std_file_seek ), - JS_CFUNC_DEF("eof", 0, js_std_file_eof ), - JS_CFUNC_DEF("fileno", 0, js_std_file_fileno ), - JS_CFUNC_DEF("error", 0, js_std_file_error ), - JS_CFUNC_DEF("clearerr", 0, js_std_file_clearerr ), - JS_CFUNC_MAGIC_DEF("read", 3, js_std_file_read_write, 0 ), - JS_CFUNC_MAGIC_DEF("write", 3, js_std_file_read_write, 1 ), - JS_CFUNC_DEF("getline", 0, js_std_file_getline ), - JS_CFUNC_DEF("readAsString", 0, js_std_file_readAsString ), - JS_CFUNC_DEF("getByte", 0, js_std_file_getByte ), - JS_CFUNC_DEF("putByte", 1, js_std_file_putByte ), - /* setvbuf, ... */ -}; - -static int js_std_init(JSContext *ctx, JSModuleDef *m) -{ - JSValue proto; - - /* FILE class */ - /* the class ID is created once */ - JS_NewClassID(&js_std_file_class_id); - /* the class is created once per runtime */ - JS_NewClass(JS_GetRuntime(ctx), js_std_file_class_id, &js_std_file_class); - proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, proto, js_std_file_proto_funcs, - countof(js_std_file_proto_funcs)); - JS_SetClassProto(ctx, js_std_file_class_id, proto); - - JS_SetModuleExportList(ctx, m, js_std_funcs, - countof(js_std_funcs)); - JS_SetModuleExport(ctx, m, "in", js_new_std_file(ctx, stdin, FALSE, FALSE)); - JS_SetModuleExport(ctx, m, "out", js_new_std_file(ctx, stdout, FALSE, FALSE)); - JS_SetModuleExport(ctx, m, "err", js_new_std_file(ctx, stderr, FALSE, FALSE)); - return 0; -} - -JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name) -{ - JSModuleDef *m; - m = JS_NewCModule(ctx, module_name, js_std_init); - if (!m) - return NULL; - JS_AddModuleExportList(ctx, m, js_std_funcs, countof(js_std_funcs)); - JS_AddModuleExport(ctx, m, "in"); - JS_AddModuleExport(ctx, m, "out"); - JS_AddModuleExport(ctx, m, "err"); - return m; -} - -/**********************************************************/ -/* 'os' object */ - -static JSValue js_os_open(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *filename; - int flags, mode, ret; - - filename = JS_ToCString(ctx, argv[0]); - if (!filename) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &flags, argv[1])) - goto fail; - if (argc >= 3 && !JS_IsUndefined(argv[2])) { - if (JS_ToInt32(ctx, &mode, argv[2])) { - fail: - JS_FreeCString(ctx, filename); - return JS_EXCEPTION; - } - } else { - mode = 0666; - } -#if defined(_WIN32) - /* force binary mode by default */ - if (!(flags & O_TEXT)) - flags |= O_BINARY; -#endif - ret = js_get_errno(open(filename, flags, mode)); - JS_FreeCString(ctx, filename); - return JS_NewInt32(ctx, ret); -} - -static JSValue js_os_close(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int fd, ret; - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - ret = js_get_errno(close(fd)); - return JS_NewInt32(ctx, ret); -} - -static JSValue js_os_seek(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int fd, whence; - int64_t pos, ret; - BOOL is_bigint; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - is_bigint = JS_IsBigInt(ctx, argv[1]); - if (JS_ToInt64Ext(ctx, &pos, argv[1])) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &whence, argv[2])) - return JS_EXCEPTION; - ret = lseek(fd, pos, whence); - if (ret == -1) - ret = -errno; - if (is_bigint) - return JS_NewBigInt64(ctx, ret); - else - return JS_NewInt64(ctx, ret); -} - -static JSValue js_os_read_write(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - int fd; - uint64_t pos, len; - size_t size; - ssize_t ret; - uint8_t *buf; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - if (JS_ToIndex(ctx, &pos, argv[2])) - return JS_EXCEPTION; - if (JS_ToIndex(ctx, &len, argv[3])) - return JS_EXCEPTION; - buf = JS_GetArrayBuffer(ctx, &size, argv[1]); - if (!buf) - return JS_EXCEPTION; - if (pos + len > size) - return JS_ThrowRangeError(ctx, "read/write array buffer overflow"); - if (magic) - ret = js_get_errno(write(fd, buf + pos, len)); - else - ret = js_get_errno(read(fd, buf + pos, len)); - return JS_NewInt64(ctx, ret); -} - -static JSValue js_os_isatty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int fd; - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - return JS_NewBool(ctx, (isatty(fd) != 0)); -} - -#if defined(_WIN32) -static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int fd; - HANDLE handle; - CONSOLE_SCREEN_BUFFER_INFO info; - JSValue obj; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - handle = (HANDLE)_get_osfhandle(fd); - - if (!GetConsoleScreenBufferInfo(handle, &info)) - return JS_NULL; - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) - return obj; - JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewInt32(ctx, info.dwSize.X), JS_PROP_C_W_E); - JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, info.dwSize.Y), JS_PROP_C_W_E); - return obj; -} - -/* Windows 10 built-in VT100 emulation */ -#define __ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 -#define __ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 - -static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int fd; - HANDLE handle; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - handle = (HANDLE)_get_osfhandle(fd); - SetConsoleMode(handle, ENABLE_WINDOW_INPUT | __ENABLE_VIRTUAL_TERMINAL_INPUT); - _setmode(fd, _O_BINARY); - if (fd == 0) { - handle = (HANDLE)_get_osfhandle(1); /* corresponding output */ - SetConsoleMode(handle, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | __ENABLE_VIRTUAL_TERMINAL_PROCESSING); - } - return JS_UNDEFINED; -} -#else -static JSValue js_os_ttyGetWinSize(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int fd; - struct winsize ws; - JSValue obj; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - if (ioctl(fd, TIOCGWINSZ, &ws) == 0 && - ws.ws_col >= 4 && ws.ws_row >= 4) { - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) - return obj; - JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewInt32(ctx, ws.ws_col), JS_PROP_C_W_E); - JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, ws.ws_row), JS_PROP_C_W_E); - return obj; - } else { - return JS_NULL; - } -} - -static struct termios oldtty; - -static void term_exit(void) -{ - tcsetattr(0, TCSANOW, &oldtty); -} - -/* XXX: should add a way to go back to normal mode */ -static JSValue js_os_ttySetRaw(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - struct termios tty; - int fd; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - - memset(&tty, 0, sizeof(tty)); - tcgetattr(fd, &tty); - oldtty = tty; - - tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP - |INLCR|IGNCR|ICRNL|IXON); - tty.c_oflag |= OPOST; - tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); - tty.c_cflag &= ~(CSIZE|PARENB); - tty.c_cflag |= CS8; - tty.c_cc[VMIN] = 1; - tty.c_cc[VTIME] = 0; - - tcsetattr(fd, TCSANOW, &tty); - - atexit(term_exit); - return JS_UNDEFINED; -} - -#endif /* !_WIN32 */ - -static JSValue js_os_remove(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *filename; - int ret; - - filename = JS_ToCString(ctx, argv[0]); - if (!filename) - return JS_EXCEPTION; -#if defined(_WIN32) - { - struct stat st; - if (stat(filename, &st) == 0 && S_ISDIR(st.st_mode)) { - ret = rmdir(filename); - } else { - ret = unlink(filename); - } - } -#else - ret = remove(filename); -#endif - ret = js_get_errno(ret); - JS_FreeCString(ctx, filename); - return JS_NewInt32(ctx, ret); -} - -static JSValue js_os_rename(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *oldpath, *newpath; - int ret; - - oldpath = JS_ToCString(ctx, argv[0]); - if (!oldpath) - return JS_EXCEPTION; - newpath = JS_ToCString(ctx, argv[1]); - if (!newpath) { - JS_FreeCString(ctx, oldpath); - return JS_EXCEPTION; - } - ret = js_get_errno(rename(oldpath, newpath)); - JS_FreeCString(ctx, oldpath); - JS_FreeCString(ctx, newpath); - return JS_NewInt32(ctx, ret); -} - -static BOOL is_main_thread(JSRuntime *rt) -{ - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - return !ts->recv_pipe; -} - -static JSOSRWHandler *find_rh(JSThreadState *ts, int fd) -{ - JSOSRWHandler *rh; - struct list_head *el; - - list_for_each(el, &ts->os_rw_handlers) { - rh = list_entry(el, JSOSRWHandler, link); - if (rh->fd == fd) - return rh; - } - return NULL; -} - -static void free_rw_handler(JSRuntime *rt, JSOSRWHandler *rh) -{ - int i; - list_del(&rh->link); - for(i = 0; i < 2; i++) { - JS_FreeValueRT(rt, rh->rw_func[i]); - } - js_free_rt(rt, rh); -} - -static JSValue js_os_setReadHandler(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - JSOSRWHandler *rh; - int fd; - JSValueConst func; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - func = argv[1]; - if (JS_IsNull(func)) { - rh = find_rh(ts, fd); - if (rh) { - JS_FreeValue(ctx, rh->rw_func[magic]); - rh->rw_func[magic] = JS_NULL; - if (JS_IsNull(rh->rw_func[0]) && - JS_IsNull(rh->rw_func[1])) { - /* remove the entry */ - free_rw_handler(JS_GetRuntime(ctx), rh); - } - } - } else { - if (!JS_IsFunction(ctx, func)) - return JS_ThrowTypeError(ctx, "not a function"); - rh = find_rh(ts, fd); - if (!rh) { - rh = js_mallocz(ctx, sizeof(*rh)); - if (!rh) - return JS_EXCEPTION; - rh->fd = fd; - rh->rw_func[0] = JS_NULL; - rh->rw_func[1] = JS_NULL; - list_add_tail(&rh->link, &ts->os_rw_handlers); - } - JS_FreeValue(ctx, rh->rw_func[magic]); - rh->rw_func[magic] = JS_DupValue(ctx, func); - } - return JS_UNDEFINED; -} - -static JSOSSignalHandler *find_sh(JSThreadState *ts, int sig_num) -{ - JSOSSignalHandler *sh; - struct list_head *el; - list_for_each(el, &ts->os_signal_handlers) { - sh = list_entry(el, JSOSSignalHandler, link); - if (sh->sig_num == sig_num) - return sh; - } - return NULL; -} - -static void free_sh(JSRuntime *rt, JSOSSignalHandler *sh) -{ - list_del(&sh->link); - JS_FreeValueRT(rt, sh->func); - js_free_rt(rt, sh); -} - -static void os_signal_handler(int sig_num) -{ - os_pending_signals |= ((uint64_t)1 << sig_num); -} - -#if defined(_WIN32) -typedef void (*sighandler_t)(int sig_num); -#endif - -static JSValue js_os_signal(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - JSOSSignalHandler *sh; - uint32_t sig_num; - JSValueConst func; - sighandler_t handler; - - if (!is_main_thread(rt)) - return JS_ThrowTypeError(ctx, "signal handler can only be set in the main thread"); - - if (JS_ToUint32(ctx, &sig_num, argv[0])) - return JS_EXCEPTION; - if (sig_num >= 64) - return JS_ThrowRangeError(ctx, "invalid signal number"); - func = argv[1]; - /* func = null: SIG_DFL, func = undefined, SIG_IGN */ - if (JS_IsNull(func) || JS_IsUndefined(func)) { - sh = find_sh(ts, sig_num); - if (sh) { - free_sh(JS_GetRuntime(ctx), sh); - } - if (JS_IsNull(func)) - handler = SIG_DFL; - else - handler = SIG_IGN; - signal(sig_num, handler); - } else { - if (!JS_IsFunction(ctx, func)) - return JS_ThrowTypeError(ctx, "not a function"); - sh = find_sh(ts, sig_num); - if (!sh) { - sh = js_mallocz(ctx, sizeof(*sh)); - if (!sh) - return JS_EXCEPTION; - sh->sig_num = sig_num; - list_add_tail(&sh->link, &ts->os_signal_handlers); - } - JS_FreeValue(ctx, sh->func); - sh->func = JS_DupValue(ctx, func); - signal(sig_num, os_signal_handler); - } - return JS_UNDEFINED; -} - -#if defined(__linux__) || defined(__APPLE__) -static int64_t get_time_ms(void) -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (uint64_t)ts.tv_sec * 1000 + (ts.tv_nsec / 1000000); -} -#else -/* more portable, but does not work if the date is updated */ -static int64_t get_time_ms(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000); -} -#endif - -static void unlink_timer(JSRuntime *rt, JSOSTimer *th) -{ - if (th->link.prev) { - list_del(&th->link); - th->link.prev = th->link.next = NULL; - } -} - -static void free_timer(JSRuntime *rt, JSOSTimer *th) -{ - JS_FreeValueRT(rt, th->func); - js_free_rt(rt, th); -} - -static JSClassID js_os_timer_class_id; - -static void js_os_timer_finalizer(JSRuntime *rt, JSValue val) -{ - JSOSTimer *th = JS_GetOpaque(val, js_os_timer_class_id); - if (th) { - th->has_object = FALSE; - if (!th->link.prev) - free_timer(rt, th); - } -} - -static void js_os_timer_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSOSTimer *th = JS_GetOpaque(val, js_os_timer_class_id); - if (th) { - JS_MarkValue(rt, th->func, mark_func); - } -} - -static JSValue js_os_setTimeout(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - int64_t delay; - JSValueConst func; - JSOSTimer *th; - JSValue obj; - - func = argv[0]; - if (!JS_IsFunction(ctx, func)) - return JS_ThrowTypeError(ctx, "not a function"); - if (JS_ToInt64(ctx, &delay, argv[1])) - return JS_EXCEPTION; - obj = JS_NewObjectClass(ctx, js_os_timer_class_id); - if (JS_IsException(obj)) - return obj; - th = js_mallocz(ctx, sizeof(*th)); - if (!th) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - th->has_object = TRUE; - th->timeout = get_time_ms() + delay; - th->func = JS_DupValue(ctx, func); - list_add_tail(&th->link, &ts->os_timers); - JS_SetOpaque(obj, th); - return obj; -} - -static JSValue js_os_clearTimeout(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSOSTimer *th = JS_GetOpaque2(ctx, argv[0], js_os_timer_class_id); - if (!th) - return JS_EXCEPTION; - unlink_timer(JS_GetRuntime(ctx), th); - return JS_UNDEFINED; -} - -static JSClassDef js_os_timer_class = { - "OSTimer", - .finalizer = js_os_timer_finalizer, - .gc_mark = js_os_timer_mark, -}; - -static void call_handler(JSContext *ctx, JSValueConst func) -{ - JSValue ret, func1; - /* 'func' might be destroyed when calling itself (if it frees the - handler), so must take extra care */ - func1 = JS_DupValue(ctx, func); - ret = JS_Call(ctx, func1, JS_UNDEFINED, 0, NULL); - JS_FreeValue(ctx, func1); - if (JS_IsException(ret)) - js_std_dump_error(ctx); - JS_FreeValue(ctx, ret); -} - -#if defined(_WIN32) - -static int js_os_poll(JSContext *ctx) -{ - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - int min_delay, console_fd; - int64_t cur_time, delay; - JSOSRWHandler *rh; - struct list_head *el; - - /* XXX: handle signals if useful */ - - if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers)) - return -1; /* no more events */ - - /* XXX: only timers and basic console input are supported */ - if (!list_empty(&ts->os_timers)) { - cur_time = get_time_ms(); - min_delay = 10000; - list_for_each(el, &ts->os_timers) { - JSOSTimer *th = list_entry(el, JSOSTimer, link); - delay = th->timeout - cur_time; - if (delay <= 0) { - JSValue func; - /* the timer expired */ - func = th->func; - th->func = JS_UNDEFINED; - unlink_timer(rt, th); - if (!th->has_object) - free_timer(rt, th); - call_handler(ctx, func); - JS_FreeValue(ctx, func); - return 0; - } else if (delay < min_delay) { - min_delay = delay; - } - } - } else { - min_delay = -1; - } - - console_fd = -1; - list_for_each(el, &ts->os_rw_handlers) { - rh = list_entry(el, JSOSRWHandler, link); - if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) { - console_fd = rh->fd; - break; - } - } - - if (console_fd >= 0) { - DWORD ti, ret; - HANDLE handle; - if (min_delay == -1) - ti = INFINITE; - else - ti = min_delay; - handle = (HANDLE)_get_osfhandle(console_fd); - ret = WaitForSingleObject(handle, ti); - if (ret == WAIT_OBJECT_0) { - list_for_each(el, &ts->os_rw_handlers) { - rh = list_entry(el, JSOSRWHandler, link); - if (rh->fd == console_fd && !JS_IsNull(rh->rw_func[0])) { - call_handler(ctx, rh->rw_func[0]); - /* must stop because the list may have been modified */ - break; - } - } - } - } else { - Sleep(min_delay); - } - return 0; -} -#else - -#ifdef USE_WORKER - -static void js_free_message(JSWorkerMessage *msg); - -/* return 1 if a message was handled, 0 if no message */ -static int handle_posted_message(JSRuntime *rt, JSContext *ctx, - JSWorkerMessageHandler *port) -{ - JSWorkerMessagePipe *ps = port->recv_pipe; - int ret; - struct list_head *el; - JSWorkerMessage *msg; - JSValue obj, data_obj, func, retval; - - pthread_mutex_lock(&ps->mutex); - if (!list_empty(&ps->msg_queue)) { - el = ps->msg_queue.next; - msg = list_entry(el, JSWorkerMessage, link); - - /* remove the message from the queue */ - list_del(&msg->link); - - if (list_empty(&ps->msg_queue)) { - uint8_t buf[16]; - int ret; - for(;;) { - ret = read(ps->read_fd, buf, sizeof(buf)); - if (ret >= 0) - break; - if (errno != EAGAIN && errno != EINTR) - break; - } - } - - pthread_mutex_unlock(&ps->mutex); - - data_obj = JS_ReadObject(ctx, msg->data, msg->data_len, - JS_READ_OBJ_SAB | JS_READ_OBJ_REFERENCE); - - js_free_message(msg); - - if (JS_IsException(data_obj)) - goto fail; - obj = JS_NewObject(ctx); - if (JS_IsException(obj)) { - JS_FreeValue(ctx, data_obj); - goto fail; - } - JS_DefinePropertyValueStr(ctx, obj, "data", data_obj, JS_PROP_C_W_E); - - /* 'func' might be destroyed when calling itself (if it frees the - handler), so must take extra care */ - func = JS_DupValue(ctx, port->on_message_func); - retval = JS_Call(ctx, func, JS_UNDEFINED, 1, (JSValueConst *)&obj); - JS_FreeValue(ctx, obj); - JS_FreeValue(ctx, func); - if (JS_IsException(retval)) { - fail: - js_std_dump_error(ctx); - } else { - JS_FreeValue(ctx, retval); - } - ret = 1; - } else { - pthread_mutex_unlock(&ps->mutex); - ret = 0; - } - return ret; -} -#else -static int handle_posted_message(JSRuntime *rt, JSContext *ctx, - JSWorkerMessageHandler *port) -{ - return 0; -} -#endif - -static int js_os_poll(JSContext *ctx) -{ - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - int ret, fd_max, min_delay; - int64_t cur_time, delay; - fd_set rfds, wfds; - JSOSRWHandler *rh; - struct list_head *el; - struct timeval tv, *tvp; - - /* only check signals in the main thread */ - if (!ts->recv_pipe && - unlikely(os_pending_signals != 0)) { - JSOSSignalHandler *sh; - uint64_t mask; - - list_for_each(el, &ts->os_signal_handlers) { - sh = list_entry(el, JSOSSignalHandler, link); - mask = (uint64_t)1 << sh->sig_num; - if (os_pending_signals & mask) { - os_pending_signals &= ~mask; - call_handler(ctx, sh->func); - return 0; - } - } - } - - if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers) && - list_empty(&ts->port_list)) - return -1; /* no more events */ - - if (!list_empty(&ts->os_timers)) { - cur_time = get_time_ms(); - min_delay = 10000; - list_for_each(el, &ts->os_timers) { - JSOSTimer *th = list_entry(el, JSOSTimer, link); - delay = th->timeout - cur_time; - if (delay <= 0) { - JSValue func; - /* the timer expired */ - func = th->func; - th->func = JS_UNDEFINED; - unlink_timer(rt, th); - if (!th->has_object) - free_timer(rt, th); - call_handler(ctx, func); - JS_FreeValue(ctx, func); - return 0; - } else if (delay < min_delay) { - min_delay = delay; - } - } - tv.tv_sec = min_delay / 1000; - tv.tv_usec = (min_delay % 1000) * 1000; - tvp = &tv; - } else { - tvp = NULL; - } - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - fd_max = -1; - list_for_each(el, &ts->os_rw_handlers) { - rh = list_entry(el, JSOSRWHandler, link); - fd_max = max_int(fd_max, rh->fd); - if (!JS_IsNull(rh->rw_func[0])) - FD_SET(rh->fd, &rfds); - if (!JS_IsNull(rh->rw_func[1])) - FD_SET(rh->fd, &wfds); - } - - list_for_each(el, &ts->port_list) { - JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); - if (!JS_IsNull(port->on_message_func)) { - JSWorkerMessagePipe *ps = port->recv_pipe; - fd_max = max_int(fd_max, ps->read_fd); - FD_SET(ps->read_fd, &rfds); - } - } - - ret = select(fd_max + 1, &rfds, &wfds, NULL, tvp); - if (ret > 0) { - list_for_each(el, &ts->os_rw_handlers) { - rh = list_entry(el, JSOSRWHandler, link); - if (!JS_IsNull(rh->rw_func[0]) && - FD_ISSET(rh->fd, &rfds)) { - call_handler(ctx, rh->rw_func[0]); - /* must stop because the list may have been modified */ - goto done; - } - if (!JS_IsNull(rh->rw_func[1]) && - FD_ISSET(rh->fd, &wfds)) { - call_handler(ctx, rh->rw_func[1]); - /* must stop because the list may have been modified */ - goto done; - } - } - - list_for_each(el, &ts->port_list) { - JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link); - if (!JS_IsNull(port->on_message_func)) { - JSWorkerMessagePipe *ps = port->recv_pipe; - if (FD_ISSET(ps->read_fd, &rfds)) { - if (handle_posted_message(rt, ctx, port)) - goto done; - } - } - } - } - done: - return 0; -} -#endif /* !_WIN32 */ - -static JSValue make_obj_error(JSContext *ctx, - JSValue obj, - int err) -{ - JSValue arr; - if (JS_IsException(obj)) - return obj; - arr = JS_NewArray(ctx); - if (JS_IsException(arr)) - return JS_EXCEPTION; - JS_DefinePropertyValueUint32(ctx, arr, 0, obj, - JS_PROP_C_W_E); - JS_DefinePropertyValueUint32(ctx, arr, 1, JS_NewInt32(ctx, err), - JS_PROP_C_W_E); - return arr; -} - -static JSValue make_string_error(JSContext *ctx, - const char *buf, - int err) -{ - return make_obj_error(ctx, JS_NewString(ctx, buf), err); -} - -/* return [cwd, errorcode] */ -static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - char buf[PATH_MAX]; - int err; - - if (!getcwd(buf, sizeof(buf))) { - buf[0] = '\0'; - err = errno; - } else { - err = 0; - } - return make_string_error(ctx, buf, err); -} - -static JSValue js_os_chdir(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *target; - int err; - - target = JS_ToCString(ctx, argv[0]); - if (!target) - return JS_EXCEPTION; - err = js_get_errno(chdir(target)); - JS_FreeCString(ctx, target); - return JS_NewInt32(ctx, err); -} - -static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int mode, ret; - const char *path; - - if (argc >= 2) { - if (JS_ToInt32(ctx, &mode, argv[1])) - return JS_EXCEPTION; - } else { - mode = 0777; - } - path = JS_ToCString(ctx, argv[0]); - if (!path) - return JS_EXCEPTION; -#if defined(_WIN32) - (void)mode; - ret = js_get_errno(mkdir(path)); -#else - ret = js_get_errno(mkdir(path, mode)); -#endif - JS_FreeCString(ctx, path); - return JS_NewInt32(ctx, ret); -} - -/* return [array, errorcode] */ -static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *path; - DIR *f; - struct dirent *d; - JSValue obj; - int err; - uint32_t len; - - path = JS_ToCString(ctx, argv[0]); - if (!path) - return JS_EXCEPTION; - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) { - JS_FreeCString(ctx, path); - return JS_EXCEPTION; - } - f = opendir(path); - if (!f) - err = errno; - else - err = 0; - JS_FreeCString(ctx, path); - if (!f) - goto done; - len = 0; - for(;;) { - errno = 0; - d = readdir(f); - if (!d) { - err = errno; - break; - } - JS_DefinePropertyValueUint32(ctx, obj, len++, - JS_NewString(ctx, d->d_name), - JS_PROP_C_W_E); - } - closedir(f); - done: - return make_obj_error(ctx, obj, err); -} - -#if !defined(_WIN32) -static int64_t timespec_to_ms(const struct timespec *tv) -{ - return (int64_t)tv->tv_sec * 1000 + (tv->tv_nsec / 1000000); -} -#endif - -/* return [obj, errcode] */ -static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int is_lstat) -{ - const char *path; - int err, res; - struct stat st; - JSValue obj; - - path = JS_ToCString(ctx, argv[0]); - if (!path) - return JS_EXCEPTION; -#if defined(_WIN32) - res = stat(path, &st); -#else - if (is_lstat) - res = lstat(path, &st); - else - res = stat(path, &st); -#endif - JS_FreeCString(ctx, path); - if (res < 0) { - err = errno; - obj = JS_NULL; - } else { - err = 0; - obj = JS_NewObject(ctx); - if (JS_IsException(obj)) - return JS_EXCEPTION; - JS_DefinePropertyValueStr(ctx, obj, "dev", - JS_NewInt64(ctx, st.st_dev), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "ino", - JS_NewInt64(ctx, st.st_ino), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "mode", - JS_NewInt32(ctx, st.st_mode), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "nlink", - JS_NewInt64(ctx, st.st_nlink), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "uid", - JS_NewInt64(ctx, st.st_uid), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "gid", - JS_NewInt64(ctx, st.st_gid), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "rdev", - JS_NewInt64(ctx, st.st_rdev), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "size", - JS_NewInt64(ctx, st.st_size), - JS_PROP_C_W_E); -#if !defined(_WIN32) - JS_DefinePropertyValueStr(ctx, obj, "blocks", - JS_NewInt64(ctx, st.st_blocks), - JS_PROP_C_W_E); -#endif -#if defined(_WIN32) - JS_DefinePropertyValueStr(ctx, obj, "atime", - JS_NewInt64(ctx, (int64_t)st.st_atime * 1000), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "mtime", - JS_NewInt64(ctx, (int64_t)st.st_mtime * 1000), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "ctime", - JS_NewInt64(ctx, (int64_t)st.st_ctime * 1000), - JS_PROP_C_W_E); -#elif defined(__APPLE__) - JS_DefinePropertyValueStr(ctx, obj, "atime", - JS_NewInt64(ctx, timespec_to_ms(&st.st_atimespec)), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "mtime", - JS_NewInt64(ctx, timespec_to_ms(&st.st_mtimespec)), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "ctime", - JS_NewInt64(ctx, timespec_to_ms(&st.st_ctimespec)), - JS_PROP_C_W_E); -#else - JS_DefinePropertyValueStr(ctx, obj, "atime", - JS_NewInt64(ctx, timespec_to_ms(&st.st_atim)), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "mtime", - JS_NewInt64(ctx, timespec_to_ms(&st.st_mtim)), - JS_PROP_C_W_E); - JS_DefinePropertyValueStr(ctx, obj, "ctime", - JS_NewInt64(ctx, timespec_to_ms(&st.st_ctim)), - JS_PROP_C_W_E); -#endif - } - return make_obj_error(ctx, obj, err); -} - -#if !defined(_WIN32) -static void ms_to_timeval(struct timeval *tv, uint64_t v) -{ - tv->tv_sec = v / 1000; - tv->tv_usec = (v % 1000) * 1000; -} -#endif - -static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *path; - int64_t atime, mtime; - int ret; - - if (JS_ToInt64(ctx, &atime, argv[1])) - return JS_EXCEPTION; - if (JS_ToInt64(ctx, &mtime, argv[2])) - return JS_EXCEPTION; - path = JS_ToCString(ctx, argv[0]); - if (!path) - return JS_EXCEPTION; -#if defined(_WIN32) - { - struct _utimbuf times; - times.actime = atime / 1000; - times.modtime = mtime / 1000; - ret = js_get_errno(_utime(path, ×)); - } -#else - { - struct timeval times[2]; - ms_to_timeval(×[0], atime); - ms_to_timeval(×[1], mtime); - ret = js_get_errno(utimes(path, times)); - } -#endif - JS_FreeCString(ctx, path); - return JS_NewInt32(ctx, ret); -} - -/* sleep(delay_ms) */ -static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int64_t delay; - int ret; - - if (JS_ToInt64(ctx, &delay, argv[0])) - return JS_EXCEPTION; - if (delay < 0) - delay = 0; -#if defined(_WIN32) - { - if (delay > INT32_MAX) - delay = INT32_MAX; - Sleep(delay); - ret = 0; - } -#else - { - struct timespec ts; - - ts.tv_sec = delay / 1000; - ts.tv_nsec = (delay % 1000) * 1000000; - ret = js_get_errno(nanosleep(&ts, NULL)); - } -#endif - return JS_NewInt32(ctx, ret); -} - -#if defined(_WIN32) -static char *realpath(const char *path, char *buf) -{ - if (!_fullpath(buf, path, PATH_MAX)) { - errno = ENOENT; - return NULL; - } else { - return buf; - } -} -#endif - -/* return [path, errorcode] */ -static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *path; - char buf[PATH_MAX], *res; - int err; - - path = JS_ToCString(ctx, argv[0]); - if (!path) - return JS_EXCEPTION; - res = realpath(path, buf); - JS_FreeCString(ctx, path); - if (!res) { - buf[0] = '\0'; - err = errno; - } else { - err = 0; - } - return make_string_error(ctx, buf, err); -} - -#if !defined(_WIN32) -static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *target, *linkpath; - int err; - - target = JS_ToCString(ctx, argv[0]); - if (!target) - return JS_EXCEPTION; - linkpath = JS_ToCString(ctx, argv[1]); - if (!linkpath) { - JS_FreeCString(ctx, target); - return JS_EXCEPTION; - } - err = js_get_errno(symlink(target, linkpath)); - JS_FreeCString(ctx, target); - JS_FreeCString(ctx, linkpath); - return JS_NewInt32(ctx, err); -} - -/* return [path, errorcode] */ -static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - const char *path; - char buf[PATH_MAX]; - int err; - ssize_t res; - - path = JS_ToCString(ctx, argv[0]); - if (!path) - return JS_EXCEPTION; - res = readlink(path, buf, sizeof(buf) - 1); - if (res < 0) { - buf[0] = '\0'; - err = errno; - } else { - buf[res] = '\0'; - err = 0; - } - JS_FreeCString(ctx, path); - return make_string_error(ctx, buf, err); -} - -static char **build_envp(JSContext *ctx, JSValueConst obj) -{ - uint32_t len, i; - JSPropertyEnum *tab; - char **envp, *pair; - const char *key, *str; - JSValue val; - size_t key_len, str_len; - - if (JS_GetOwnPropertyNames(ctx, &tab, &len, obj, - JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0) - return NULL; - envp = js_mallocz(ctx, sizeof(envp[0]) * ((size_t)len + 1)); - if (!envp) - goto fail; - for(i = 0; i < len; i++) { - val = JS_GetProperty(ctx, obj, tab[i].atom); - if (JS_IsException(val)) - goto fail; - str = JS_ToCString(ctx, val); - JS_FreeValue(ctx, val); - if (!str) - goto fail; - key = JS_AtomToCString(ctx, tab[i].atom); - if (!key) { - JS_FreeCString(ctx, str); - goto fail; - } - key_len = strlen(key); - str_len = strlen(str); - pair = js_malloc(ctx, key_len + str_len + 2); - if (!pair) { - JS_FreeCString(ctx, key); - JS_FreeCString(ctx, str); - goto fail; - } - memcpy(pair, key, key_len); - pair[key_len] = '='; - memcpy(pair + key_len + 1, str, str_len); - pair[key_len + 1 + str_len] = '\0'; - envp[i] = pair; - JS_FreeCString(ctx, key); - JS_FreeCString(ctx, str); - } - done: - for(i = 0; i < len; i++) - JS_FreeAtom(ctx, tab[i].atom); - js_free(ctx, tab); - return envp; - fail: - if (envp) { - for(i = 0; i < len; i++) - js_free(ctx, envp[i]); - js_free(ctx, envp); - envp = NULL; - } - goto done; -} - -/* execvpe is not available on non GNU systems */ -static int my_execvpe(const char *filename, char **argv, char **envp) -{ - char *path, *p, *p_next, *p1; - char buf[PATH_MAX]; - size_t filename_len, path_len; - BOOL eacces_error; - - filename_len = strlen(filename); - if (filename_len == 0) { - errno = ENOENT; - return -1; - } - if (strchr(filename, '/')) - return execve(filename, argv, envp); - - path = getenv("PATH"); - if (!path) - path = (char *)"/bin:/usr/bin"; - eacces_error = FALSE; - p = path; - for(p = path; p != NULL; p = p_next) { - p1 = strchr(p, ':'); - if (!p1) { - p_next = NULL; - path_len = strlen(p); - } else { - p_next = p1 + 1; - path_len = p1 - p; - } - /* path too long */ - if ((path_len + 1 + filename_len + 1) > PATH_MAX) - continue; - memcpy(buf, p, path_len); - buf[path_len] = '/'; - memcpy(buf + path_len + 1, filename, filename_len); - buf[path_len + 1 + filename_len] = '\0'; - - execve(buf, argv, envp); - - switch(errno) { - case EACCES: - eacces_error = TRUE; - break; - case ENOENT: - case ENOTDIR: - break; - default: - return -1; - } - } - if (eacces_error) - errno = EACCES; - return -1; -} - -/* exec(args[, options]) -> exitcode */ -static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst options, args = argv[0]; - JSValue val, ret_val; - const char **exec_argv, *file = NULL, *str, *cwd = NULL; - char **envp = environ; - uint32_t exec_argc, i; - int ret, pid, status; - BOOL block_flag = TRUE, use_path = TRUE; - static const char *std_name[3] = { "stdin", "stdout", "stderr" }; - int std_fds[3]; - uint32_t uid = -1, gid = -1; - - val = JS_GetPropertyStr(ctx, args, "length"); - if (JS_IsException(val)) - return JS_EXCEPTION; - ret = JS_ToUint32(ctx, &exec_argc, val); - JS_FreeValue(ctx, val); - if (ret) - return JS_EXCEPTION; - /* arbitrary limit to avoid overflow */ - if (exec_argc < 1 || exec_argc > 65535) { - return JS_ThrowTypeError(ctx, "invalid number of arguments"); - } - exec_argv = js_mallocz(ctx, sizeof(exec_argv[0]) * (exec_argc + 1)); - if (!exec_argv) - return JS_EXCEPTION; - for(i = 0; i < exec_argc; i++) { - val = JS_GetPropertyUint32(ctx, args, i); - if (JS_IsException(val)) - goto exception; - str = JS_ToCString(ctx, val); - JS_FreeValue(ctx, val); - if (!str) - goto exception; - exec_argv[i] = str; - } - exec_argv[exec_argc] = NULL; - - for(i = 0; i < 3; i++) - std_fds[i] = i; - - /* get the options, if any */ - if (argc >= 2) { - options = argv[1]; - - if (get_bool_option(ctx, &block_flag, options, "block")) - goto exception; - if (get_bool_option(ctx, &use_path, options, "usePath")) - goto exception; - - val = JS_GetPropertyStr(ctx, options, "file"); - if (JS_IsException(val)) - goto exception; - if (!JS_IsUndefined(val)) { - file = JS_ToCString(ctx, val); - JS_FreeValue(ctx, val); - if (!file) - goto exception; - } - - val = JS_GetPropertyStr(ctx, options, "cwd"); - if (JS_IsException(val)) - goto exception; - if (!JS_IsUndefined(val)) { - cwd = JS_ToCString(ctx, val); - JS_FreeValue(ctx, val); - if (!cwd) - goto exception; - } - - /* stdin/stdout/stderr handles */ - for(i = 0; i < 3; i++) { - val = JS_GetPropertyStr(ctx, options, std_name[i]); - if (JS_IsException(val)) - goto exception; - if (!JS_IsUndefined(val)) { - int fd; - ret = JS_ToInt32(ctx, &fd, val); - JS_FreeValue(ctx, val); - if (ret) - goto exception; - std_fds[i] = fd; - } - } - - val = JS_GetPropertyStr(ctx, options, "env"); - if (JS_IsException(val)) - goto exception; - if (!JS_IsUndefined(val)) { - envp = build_envp(ctx, val); - JS_FreeValue(ctx, val); - if (!envp) - goto exception; - } - - val = JS_GetPropertyStr(ctx, options, "uid"); - if (JS_IsException(val)) - goto exception; - if (!JS_IsUndefined(val)) { - ret = JS_ToUint32(ctx, &uid, val); - JS_FreeValue(ctx, val); - if (ret) - goto exception; - } - - val = JS_GetPropertyStr(ctx, options, "gid"); - if (JS_IsException(val)) - goto exception; - if (!JS_IsUndefined(val)) { - ret = JS_ToUint32(ctx, &gid, val); - JS_FreeValue(ctx, val); - if (ret) - goto exception; - } - } - - pid = fork(); - if (pid < 0) { - JS_ThrowTypeError(ctx, "fork error"); - goto exception; - } - if (pid == 0) { - /* child */ - int fd_max = sysconf(_SC_OPEN_MAX); - - /* remap the stdin/stdout/stderr handles if necessary */ - for(i = 0; i < 3; i++) { - if (std_fds[i] != i) { - if (dup2(std_fds[i], i) < 0) - _exit(127); - } - } - - for(i = 3; i < fd_max; i++) - close(i); - if (cwd) { - if (chdir(cwd) < 0) - _exit(127); - } - if (uid != -1) { - if (setuid(uid) < 0) - _exit(127); - } - if (gid != -1) { - if (setgid(gid) < 0) - _exit(127); - } - - if (!file) - file = exec_argv[0]; - if (use_path) - ret = my_execvpe(file, (char **)exec_argv, envp); - else - ret = execve(file, (char **)exec_argv, envp); - _exit(127); - } - /* parent */ - if (block_flag) { - for(;;) { - ret = waitpid(pid, &status, 0); - if (ret == pid) { - if (WIFEXITED(status)) { - ret = WEXITSTATUS(status); - break; - } else if (WIFSIGNALED(status)) { - ret = -WTERMSIG(status); - break; - } - } - } - } else { - ret = pid; - } - ret_val = JS_NewInt32(ctx, ret); - done: - JS_FreeCString(ctx, file); - JS_FreeCString(ctx, cwd); - for(i = 0; i < exec_argc; i++) - JS_FreeCString(ctx, exec_argv[i]); - js_free(ctx, exec_argv); - if (envp != environ) { - char **p; - p = envp; - while (*p != NULL) { - js_free(ctx, *p); - p++; - } - js_free(ctx, envp); - } - return ret_val; - exception: - ret_val = JS_EXCEPTION; - goto done; -} - -/* waitpid(pid, block) -> [pid, status] */ -static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int pid, status, options, ret; - JSValue obj; - - if (JS_ToInt32(ctx, &pid, argv[0])) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &options, argv[1])) - return JS_EXCEPTION; - - ret = waitpid(pid, &status, options); - if (ret < 0) { - ret = -errno; - status = 0; - } - - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) - return obj; - JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewInt32(ctx, ret), - JS_PROP_C_W_E); - JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, status), - JS_PROP_C_W_E); - return obj; -} - -/* pipe() -> [read_fd, write_fd] or null if error */ -static JSValue js_os_pipe(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int pipe_fds[2], ret; - JSValue obj; - - ret = pipe(pipe_fds); - if (ret < 0) - return JS_NULL; - obj = JS_NewArray(ctx); - if (JS_IsException(obj)) - return obj; - JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewInt32(ctx, pipe_fds[0]), - JS_PROP_C_W_E); - JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, pipe_fds[1]), - JS_PROP_C_W_E); - return obj; -} - -/* kill(pid, sig) */ -static JSValue js_os_kill(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int pid, sig, ret; - - if (JS_ToInt32(ctx, &pid, argv[0])) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &sig, argv[1])) - return JS_EXCEPTION; - ret = js_get_errno(kill(pid, sig)); - return JS_NewInt32(ctx, ret); -} - -/* dup(fd) */ -static JSValue js_os_dup(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int fd, ret; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - ret = js_get_errno(dup(fd)); - return JS_NewInt32(ctx, ret); -} - -/* dup2(fd) */ -static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int fd, fd2, ret; - - if (JS_ToInt32(ctx, &fd, argv[0])) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &fd2, argv[1])) - return JS_EXCEPTION; - ret = js_get_errno(dup2(fd, fd2)); - return JS_NewInt32(ctx, ret); -} - -#endif /* !_WIN32 */ - -#ifdef USE_WORKER - -/* Worker */ - -typedef struct { - JSWorkerMessagePipe *recv_pipe; - JSWorkerMessagePipe *send_pipe; - JSWorkerMessageHandler *msg_handler; -} JSWorkerData; - -typedef struct { - char *filename; /* module filename */ - char *basename; /* module base name */ - JSWorkerMessagePipe *recv_pipe, *send_pipe; -} WorkerFuncArgs; - -typedef struct { - int ref_count; - uint64_t buf[0]; -} JSSABHeader; - -static JSClassID js_worker_class_id; -static JSContext *(*js_worker_new_context_func)(JSRuntime *rt); - -static int atomic_add_int(int *ptr, int v) -{ - return atomic_fetch_add((_Atomic(uint32_t) *)ptr, v) + v; -} - -/* shared array buffer allocator */ -static void *js_sab_alloc(void *opaque, size_t size) -{ - JSSABHeader *sab; - sab = malloc(sizeof(JSSABHeader) + size); - if (!sab) - return NULL; - sab->ref_count = 1; - return sab->buf; -} - -static void js_sab_free(void *opaque, void *ptr) -{ - JSSABHeader *sab; - int ref_count; - sab = (JSSABHeader *)((uint8_t *)ptr - sizeof(JSSABHeader)); - ref_count = atomic_add_int(&sab->ref_count, -1); - assert(ref_count >= 0); - if (ref_count == 0) { - free(sab); - } -} - -static void js_sab_dup(void *opaque, void *ptr) -{ - JSSABHeader *sab; - sab = (JSSABHeader *)((uint8_t *)ptr - sizeof(JSSABHeader)); - atomic_add_int(&sab->ref_count, 1); -} - -static JSWorkerMessagePipe *js_new_message_pipe(void) -{ - JSWorkerMessagePipe *ps; - int pipe_fds[2]; - - if (pipe(pipe_fds) < 0) - return NULL; - - ps = malloc(sizeof(*ps)); - if (!ps) { - close(pipe_fds[0]); - close(pipe_fds[1]); - return NULL; - } - ps->ref_count = 1; - init_list_head(&ps->msg_queue); - pthread_mutex_init(&ps->mutex, NULL); - ps->read_fd = pipe_fds[0]; - ps->write_fd = pipe_fds[1]; - return ps; -} - -static JSWorkerMessagePipe *js_dup_message_pipe(JSWorkerMessagePipe *ps) -{ - atomic_add_int(&ps->ref_count, 1); - return ps; -} - -static void js_free_message(JSWorkerMessage *msg) -{ - size_t i; - /* free the SAB */ - for(i = 0; i < msg->sab_tab_len; i++) { - js_sab_free(NULL, msg->sab_tab[i]); - } - free(msg->sab_tab); - free(msg->data); - free(msg); -} - -static void js_free_message_pipe(JSWorkerMessagePipe *ps) -{ - struct list_head *el, *el1; - JSWorkerMessage *msg; - int ref_count; - - if (!ps) - return; - - ref_count = atomic_add_int(&ps->ref_count, -1); - assert(ref_count >= 0); - if (ref_count == 0) { - list_for_each_safe(el, el1, &ps->msg_queue) { - msg = list_entry(el, JSWorkerMessage, link); - js_free_message(msg); - } - pthread_mutex_destroy(&ps->mutex); - close(ps->read_fd); - close(ps->write_fd); - free(ps); - } -} - -static void js_free_port(JSRuntime *rt, JSWorkerMessageHandler *port) -{ - if (port) { - js_free_message_pipe(port->recv_pipe); - JS_FreeValueRT(rt, port->on_message_func); - list_del(&port->link); - js_free_rt(rt, port); - } -} - -static void js_worker_finalizer(JSRuntime *rt, JSValue val) -{ - JSWorkerData *worker = JS_GetOpaque(val, js_worker_class_id); - if (worker) { - js_free_message_pipe(worker->recv_pipe); - js_free_message_pipe(worker->send_pipe); - js_free_port(rt, worker->msg_handler); - js_free_rt(rt, worker); - } -} - -static JSClassDef js_worker_class = { - "Worker", - .finalizer = js_worker_finalizer, -}; - -static void *worker_func(void *opaque) -{ - WorkerFuncArgs *args = opaque; - JSRuntime *rt; - JSThreadState *ts; - JSContext *ctx; - - rt = JS_NewRuntime(); - if (rt == NULL) { - fprintf(stderr, "JS_NewRuntime failure"); - exit(1); - } - js_std_init_handlers(rt); - - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); - - /* set the pipe to communicate with the parent */ - ts = JS_GetRuntimeOpaque(rt); - ts->recv_pipe = args->recv_pipe; - ts->send_pipe = args->send_pipe; - - /* function pointer to avoid linking the whole JS_NewContext() if - not needed */ - ctx = js_worker_new_context_func(rt); - if (ctx == NULL) { - fprintf(stderr, "JS_NewContext failure"); - } - - JS_SetCanBlock(rt, TRUE); - - js_std_add_helpers(ctx, -1, NULL); - - if (!JS_RunModule(ctx, args->basename, args->filename)) - js_std_dump_error(ctx); - free(args->filename); - free(args->basename); - free(args); - - js_std_loop(ctx); - - JS_FreeContext(ctx); - js_std_free_handlers(rt); - JS_FreeRuntime(rt); - return NULL; -} - -static JSValue js_worker_ctor_internal(JSContext *ctx, JSValueConst new_target, - JSWorkerMessagePipe *recv_pipe, - JSWorkerMessagePipe *send_pipe) -{ - JSValue obj = JS_UNDEFINED, proto; - JSWorkerData *s; - - /* create the object */ - if (JS_IsUndefined(new_target)) { - proto = JS_GetClassProto(ctx, js_worker_class_id); - } else { - proto = JS_GetPropertyStr(ctx, new_target, "prototype"); - if (JS_IsException(proto)) - goto fail; - } - obj = JS_NewObjectProtoClass(ctx, proto, js_worker_class_id); - JS_FreeValue(ctx, proto); - if (JS_IsException(obj)) - goto fail; - s = js_mallocz(ctx, sizeof(*s)); - if (!s) - goto fail; - s->recv_pipe = js_dup_message_pipe(recv_pipe); - s->send_pipe = js_dup_message_pipe(send_pipe); - - JS_SetOpaque(obj, s); - return obj; - fail: - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - -static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target, - int argc, JSValueConst *argv) -{ - JSRuntime *rt = JS_GetRuntime(ctx); - WorkerFuncArgs *args = NULL; - pthread_t tid; - pthread_attr_t attr; - JSValue obj = JS_UNDEFINED; - int ret; - const char *filename = NULL, *basename; - JSAtom basename_atom; - - /* XXX: in order to avoid problems with resource liberation, we - don't support creating workers inside workers */ - if (!is_main_thread(rt)) - return JS_ThrowTypeError(ctx, "cannot create a worker inside a worker"); - - /* base name, assuming the calling function is a normal JS - function */ - basename_atom = JS_GetScriptOrModuleName(ctx, 1); - if (basename_atom == JS_ATOM_NULL) { - return JS_ThrowTypeError(ctx, "could not determine calling script or module name"); - } - basename = JS_AtomToCString(ctx, basename_atom); - JS_FreeAtom(ctx, basename_atom); - if (!basename) - goto fail; - - /* module name */ - filename = JS_ToCString(ctx, argv[0]); - if (!filename) - goto fail; - - args = malloc(sizeof(*args)); - if (!args) - goto oom_fail; - memset(args, 0, sizeof(*args)); - args->filename = strdup(filename); - args->basename = strdup(basename); - - /* ports */ - args->recv_pipe = js_new_message_pipe(); - if (!args->recv_pipe) - goto oom_fail; - args->send_pipe = js_new_message_pipe(); - if (!args->send_pipe) - goto oom_fail; - - obj = js_worker_ctor_internal(ctx, new_target, - args->send_pipe, args->recv_pipe); - if (JS_IsException(obj)) - goto fail; - - pthread_attr_init(&attr); - /* no join at the end */ - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - ret = pthread_create(&tid, &attr, worker_func, args); - pthread_attr_destroy(&attr); - if (ret != 0) { - JS_ThrowTypeError(ctx, "could not create worker"); - goto fail; - } - JS_FreeCString(ctx, basename); - JS_FreeCString(ctx, filename); - return obj; - oom_fail: - JS_ThrowOutOfMemory(ctx); - fail: - JS_FreeCString(ctx, basename); - JS_FreeCString(ctx, filename); - if (args) { - free(args->filename); - free(args->basename); - js_free_message_pipe(args->recv_pipe); - js_free_message_pipe(args->send_pipe); - free(args); - } - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - -static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); - JSWorkerMessagePipe *ps; - size_t data_len, sab_tab_len, i; - uint8_t *data; - JSWorkerMessage *msg; - uint8_t **sab_tab; - - if (!worker) - return JS_EXCEPTION; - - data = JS_WriteObject2(ctx, &data_len, argv[0], - JS_WRITE_OBJ_SAB | JS_WRITE_OBJ_REFERENCE, - &sab_tab, &sab_tab_len); - if (!data) - return JS_EXCEPTION; - - msg = malloc(sizeof(*msg)); - if (!msg) - goto fail; - msg->data = NULL; - msg->sab_tab = NULL; - - /* must reallocate because the allocator may be different */ - msg->data = malloc(data_len); - if (!msg->data) - goto fail; - memcpy(msg->data, data, data_len); - msg->data_len = data_len; - - msg->sab_tab = malloc(sizeof(msg->sab_tab[0]) * sab_tab_len); - if (!msg->sab_tab) - goto fail; - memcpy(msg->sab_tab, sab_tab, sizeof(msg->sab_tab[0]) * sab_tab_len); - msg->sab_tab_len = sab_tab_len; - - js_free(ctx, data); - js_free(ctx, sab_tab); - - /* increment the SAB reference counts */ - for(i = 0; i < msg->sab_tab_len; i++) { - js_sab_dup(NULL, msg->sab_tab[i]); - } - - ps = worker->send_pipe; - pthread_mutex_lock(&ps->mutex); - /* indicate that data is present */ - if (list_empty(&ps->msg_queue)) { - uint8_t ch = '\0'; - int ret; - for(;;) { - ret = write(ps->write_fd, &ch, 1); - if (ret == 1) - break; - if (ret < 0 && (errno != EAGAIN || errno != EINTR)) - break; - } - } - list_add_tail(&msg->link, &ps->msg_queue); - pthread_mutex_unlock(&ps->mutex); - return JS_UNDEFINED; - fail: - if (msg) { - free(msg->data); - free(msg->sab_tab); - free(msg); - } - js_free(ctx, data); - js_free(ctx, sab_tab); - return JS_EXCEPTION; - -} - -static JSValue js_worker_set_onmessage(JSContext *ctx, JSValueConst this_val, - JSValueConst func) -{ - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); - JSWorkerMessageHandler *port; - - if (!worker) - return JS_EXCEPTION; - - port = worker->msg_handler; - if (JS_IsNull(func)) { - if (port) { - js_free_port(rt, port); - worker->msg_handler = NULL; - } - } else { - if (!JS_IsFunction(ctx, func)) - return JS_ThrowTypeError(ctx, "not a function"); - if (!port) { - port = js_mallocz(ctx, sizeof(*port)); - if (!port) - return JS_EXCEPTION; - port->recv_pipe = js_dup_message_pipe(worker->recv_pipe); - port->on_message_func = JS_NULL; - list_add_tail(&port->link, &ts->port_list); - worker->msg_handler = port; - } - JS_FreeValue(ctx, port->on_message_func); - port->on_message_func = JS_DupValue(ctx, func); - } - return JS_UNDEFINED; -} - -static JSValue js_worker_get_onmessage(JSContext *ctx, JSValueConst this_val) -{ - JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, js_worker_class_id); - JSWorkerMessageHandler *port; - if (!worker) - return JS_EXCEPTION; - port = worker->msg_handler; - if (port) { - return JS_DupValue(ctx, port->on_message_func); - } else { - return JS_NULL; - } -} - -static const JSCFunctionListEntry js_worker_proto_funcs[] = { - JS_CFUNC_DEF("postMessage", 1, js_worker_postMessage ), - JS_CGETSET_DEF("onmessage", js_worker_get_onmessage, js_worker_set_onmessage ), -}; - -#endif /* USE_WORKER */ - -void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)) -{ -#ifdef USE_WORKER - js_worker_new_context_func = func; -#endif -} - -#if defined(_WIN32) -#define OS_PLATFORM "win32" -#elif defined(__APPLE__) -#define OS_PLATFORM "darwin" -#elif defined(EMSCRIPTEN) -#define OS_PLATFORM "js" -#else -#define OS_PLATFORM "linux" -#endif - -#define OS_FLAG(x) JS_PROP_INT32_DEF(#x, x, JS_PROP_CONFIGURABLE ) - -static const JSCFunctionListEntry js_os_funcs[] = { - JS_CFUNC_DEF("open", 2, js_os_open ), - OS_FLAG(O_RDONLY), - OS_FLAG(O_WRONLY), - OS_FLAG(O_RDWR), - OS_FLAG(O_APPEND), - OS_FLAG(O_CREAT), - OS_FLAG(O_EXCL), - OS_FLAG(O_TRUNC), -#if defined(_WIN32) - OS_FLAG(O_BINARY), - OS_FLAG(O_TEXT), -#endif - JS_CFUNC_DEF("close", 1, js_os_close ), - JS_CFUNC_DEF("seek", 3, js_os_seek ), - JS_CFUNC_MAGIC_DEF("read", 4, js_os_read_write, 0 ), - JS_CFUNC_MAGIC_DEF("write", 4, js_os_read_write, 1 ), - JS_CFUNC_DEF("isatty", 1, js_os_isatty ), - JS_CFUNC_DEF("ttyGetWinSize", 1, js_os_ttyGetWinSize ), - JS_CFUNC_DEF("ttySetRaw", 1, js_os_ttySetRaw ), - JS_CFUNC_DEF("remove", 1, js_os_remove ), - JS_CFUNC_DEF("rename", 2, js_os_rename ), - JS_CFUNC_MAGIC_DEF("setReadHandler", 2, js_os_setReadHandler, 0 ), - JS_CFUNC_MAGIC_DEF("setWriteHandler", 2, js_os_setReadHandler, 1 ), - JS_CFUNC_DEF("signal", 2, js_os_signal ), - OS_FLAG(SIGINT), - OS_FLAG(SIGABRT), - OS_FLAG(SIGFPE), - OS_FLAG(SIGILL), - OS_FLAG(SIGSEGV), - OS_FLAG(SIGTERM), -#if !defined(_WIN32) - OS_FLAG(SIGQUIT), - OS_FLAG(SIGPIPE), - OS_FLAG(SIGALRM), - OS_FLAG(SIGUSR1), - OS_FLAG(SIGUSR2), - OS_FLAG(SIGCHLD), - OS_FLAG(SIGCONT), - OS_FLAG(SIGSTOP), - OS_FLAG(SIGTSTP), - OS_FLAG(SIGTTIN), - OS_FLAG(SIGTTOU), -#endif - JS_CFUNC_DEF("setTimeout", 2, js_os_setTimeout ), - JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ), - JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ), - JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ), - JS_CFUNC_DEF("chdir", 0, js_os_chdir ), - JS_CFUNC_DEF("mkdir", 1, js_os_mkdir ), - JS_CFUNC_DEF("readdir", 1, js_os_readdir ), - /* st_mode constants */ - OS_FLAG(S_IFMT), - OS_FLAG(S_IFIFO), - OS_FLAG(S_IFCHR), - OS_FLAG(S_IFDIR), - OS_FLAG(S_IFBLK), - OS_FLAG(S_IFREG), -#if !defined(_WIN32) - OS_FLAG(S_IFSOCK), - OS_FLAG(S_IFLNK), - OS_FLAG(S_ISGID), - OS_FLAG(S_ISUID), -#endif - JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ), - JS_CFUNC_DEF("utimes", 3, js_os_utimes ), - JS_CFUNC_DEF("sleep", 1, js_os_sleep ), - JS_CFUNC_DEF("realpath", 1, js_os_realpath ), -#if !defined(_WIN32) - JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ), - JS_CFUNC_DEF("symlink", 2, js_os_symlink ), - JS_CFUNC_DEF("readlink", 1, js_os_readlink ), - JS_CFUNC_DEF("exec", 1, js_os_exec ), - JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ), - OS_FLAG(WNOHANG), - JS_CFUNC_DEF("pipe", 0, js_os_pipe ), - JS_CFUNC_DEF("kill", 2, js_os_kill ), - JS_CFUNC_DEF("dup", 1, js_os_dup ), - JS_CFUNC_DEF("dup2", 2, js_os_dup2 ), -#endif -}; - -static int js_os_init(JSContext *ctx, JSModuleDef *m) -{ - os_poll_func = js_os_poll; - - /* OSTimer class */ - JS_NewClassID(&js_os_timer_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_os_timer_class_id, &js_os_timer_class); - -#ifdef USE_WORKER - { - JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - JSValue proto, obj; - /* Worker class */ - JS_NewClassID(&js_worker_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_worker_class_id, &js_worker_class); - proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, proto, js_worker_proto_funcs, countof(js_worker_proto_funcs)); - - obj = JS_NewCFunction2(ctx, js_worker_ctor, "Worker", 1, - JS_CFUNC_constructor, 0); - JS_SetConstructor(ctx, obj, proto); - - JS_SetClassProto(ctx, js_worker_class_id, proto); - - /* set 'Worker.parent' if necessary */ - if (ts->recv_pipe && ts->send_pipe) { - JS_DefinePropertyValueStr(ctx, obj, "parent", - js_worker_ctor_internal(ctx, JS_UNDEFINED, ts->recv_pipe, ts->send_pipe), - JS_PROP_C_W_E); - } - - JS_SetModuleExport(ctx, m, "Worker", obj); - } -#endif /* USE_WORKER */ - - return JS_SetModuleExportList(ctx, m, js_os_funcs, - countof(js_os_funcs)); -} - -JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name) -{ - JSModuleDef *m; - m = JS_NewCModule(ctx, module_name, js_os_init); - if (!m) - return NULL; - JS_AddModuleExportList(ctx, m, js_os_funcs, countof(js_os_funcs)); -#ifdef USE_WORKER - JS_AddModuleExport(ctx, m, "Worker"); -#endif - return m; -} - -/**********************************************************/ - -static JSValue js_print(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int i; - const char *str; - size_t len; - - for(i = 0; i < argc; i++) { - if (i != 0) - putchar(' '); - str = JS_ToCStringLen(ctx, &len, argv[i]); - if (!str) - return JS_EXCEPTION; - fwrite(str, 1, len, stdout); - JS_FreeCString(ctx, str); - } - putchar('\n'); - return JS_UNDEFINED; -} - -void js_std_add_helpers(JSContext *ctx, int argc, char **argv) -{ - JSValue global_obj, console, args; - int i; - - /* XXX: should these global definitions be enumerable? */ - global_obj = JS_GetGlobalObject(ctx); - - console = JS_NewObject(ctx); - JS_SetPropertyStr(ctx, console, "log", - JS_NewCFunction(ctx, js_print, "log", 1)); - JS_SetPropertyStr(ctx, global_obj, "console", console); - - /* same methods as the mozilla JS shell */ - if (argc >= 0) { - args = JS_NewArray(ctx); - for(i = 0; i < argc; i++) { - JS_SetPropertyUint32(ctx, args, i, JS_NewString(ctx, argv[i])); - } - JS_SetPropertyStr(ctx, global_obj, "scriptArgs", args); - } - - JS_SetPropertyStr(ctx, global_obj, "print", - JS_NewCFunction(ctx, js_print, "print", 1)); - JS_SetPropertyStr(ctx, global_obj, "__loadScript", - JS_NewCFunction(ctx, js_loadScript, "__loadScript", 1)); - - JS_FreeValue(ctx, global_obj); -} - -void js_std_init_handlers(JSRuntime *rt) -{ - JSThreadState *ts; - - ts = malloc(sizeof(*ts)); - if (!ts) { - fprintf(stderr, "Could not allocate memory for the worker"); - exit(1); - } - memset(ts, 0, sizeof(*ts)); - init_list_head(&ts->os_rw_handlers); - init_list_head(&ts->os_signal_handlers); - init_list_head(&ts->os_timers); - init_list_head(&ts->port_list); - - JS_SetRuntimeOpaque(rt, ts); - -#ifdef USE_WORKER - /* set the SharedArrayBuffer memory handlers */ - { - JSSharedArrayBufferFunctions sf; - memset(&sf, 0, sizeof(sf)); - sf.sab_alloc = js_sab_alloc; - sf.sab_free = js_sab_free; - sf.sab_dup = js_sab_dup; - JS_SetSharedArrayBufferFunctions(rt, &sf); - } -#endif -} - -void js_std_free_handlers(JSRuntime *rt) -{ - JSThreadState *ts = JS_GetRuntimeOpaque(rt); - struct list_head *el, *el1; - - list_for_each_safe(el, el1, &ts->os_rw_handlers) { - JSOSRWHandler *rh = list_entry(el, JSOSRWHandler, link); - free_rw_handler(rt, rh); - } - - list_for_each_safe(el, el1, &ts->os_signal_handlers) { - JSOSSignalHandler *sh = list_entry(el, JSOSSignalHandler, link); - free_sh(rt, sh); - } - - list_for_each_safe(el, el1, &ts->os_timers) { - JSOSTimer *th = list_entry(el, JSOSTimer, link); - unlink_timer(rt, th); - if (!th->has_object) - free_timer(rt, th); - } - -#ifdef USE_WORKER - /* XXX: free port_list ? */ - js_free_message_pipe(ts->recv_pipe); - js_free_message_pipe(ts->send_pipe); -#endif - - free(ts); - JS_SetRuntimeOpaque(rt, NULL); /* fail safe */ -} - -static void js_dump_obj(JSContext *ctx, FILE *f, JSValueConst val) -{ - const char *str; - - str = JS_ToCString(ctx, val); - if (str) { - fprintf(f, "%s\n", str); - JS_FreeCString(ctx, str); - } else { - fprintf(f, "[exception]\n"); - } -} - -static void js_std_dump_error1(JSContext *ctx, JSValueConst exception_val) -{ - JSValue val; - BOOL is_error; - - is_error = JS_IsError(ctx, exception_val); - js_dump_obj(ctx, stderr, exception_val); - if (is_error) { - val = JS_GetPropertyStr(ctx, exception_val, "stack"); - if (!JS_IsUndefined(val)) { - js_dump_obj(ctx, stderr, val); - } - JS_FreeValue(ctx, val); - } -} - -void js_std_dump_error(JSContext *ctx) -{ - JSValue exception_val; - - exception_val = JS_GetException(ctx); - js_std_dump_error1(ctx, exception_val); - JS_FreeValue(ctx, exception_val); -} - -void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, - JSValueConst reason, - BOOL is_handled, void *opaque) -{ - if (!is_handled) { - fprintf(stderr, "Possibly unhandled promise rejection: "); - js_std_dump_error1(ctx, reason); - } -} - -/* main loop which calls the user JS callbacks */ -void js_std_loop(JSContext *ctx) -{ - JSContext *ctx1; - int err; - - for(;;) { - /* execute the pending jobs */ - for(;;) { - err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); - if (err <= 0) { - if (err < 0) { - js_std_dump_error(ctx1); - } - break; - } - } - - if (!os_poll_func || os_poll_func(ctx)) - break; - } -} - -void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, - int load_only) -{ - JSValue obj, val; - obj = JS_ReadObject(ctx, buf, buf_len, JS_READ_OBJ_BYTECODE); - if (JS_IsException(obj)) - goto exception; - if (load_only) { - if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { - js_module_set_import_meta(ctx, obj, FALSE, FALSE); - } - } else { - if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { - if (JS_ResolveModule(ctx, obj) < 0) { - JS_FreeValue(ctx, obj); - goto exception; - } - js_module_set_import_meta(ctx, obj, FALSE, TRUE); - } - val = JS_EvalFunction(ctx, obj); - if (JS_IsException(val)) { - exception: - js_std_dump_error(ctx); - exit(1); - } - JS_FreeValue(ctx, val); - } -} diff --git a/quickjs/quickjs-libc.h.removed b/quickjs/quickjs-libc.h.removed deleted file mode 100644 index fbbe5b0..0000000 --- a/quickjs/quickjs-libc.h.removed +++ /dev/null @@ -1,59 +0,0 @@ -/* - * QuickJS C library - * - * 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 QUICKJS_LIBC_H -#define QUICKJS_LIBC_H - -#include -#include - -#include "quickjs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); -JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); -void js_std_add_helpers(JSContext *ctx, int argc, char **argv); -void js_std_loop(JSContext *ctx); -void js_std_init_handlers(JSRuntime *rt); -void js_std_free_handlers(JSRuntime *rt); -void js_std_dump_error(JSContext *ctx); -uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); -int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, - JS_BOOL use_realpath, JS_BOOL is_main); -JSModuleDef *js_module_loader(JSContext *ctx, - const char *module_name, void *opaque); -void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, - int flags); -void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, - JSValueConst reason, - JS_BOOL is_handled, void *opaque); -void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); - -#ifdef __cplusplus -} /* extern "C" { */ -#endif - -#endif /* QUICKJS_LIBC_H */ diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c index 7f3b1ea..2ba40ce 100644 --- a/quickjs/quickjs.c +++ b/quickjs/quickjs.c @@ -1,6 +1,6 @@ /* * QuickJS Javascript Engine - * + * * Copyright (c) 2017-2021 Fabrice Bellard * Copyright (c) 2017-2021 Charlie Gordon * @@ -23,21 +23,18 @@ * THE SOFTWARE. */ #include -#include "my_stdlib.h" #include -#include "my_stdio.h" #include #include -#include "my_inttypes.h" +#include #include -// #include -// #include -// #include -// #include -#include "my_math.h" +#include +#include +#include +#include +#include #include -#include "my_string.h" #include "cutils.h" #include "list.h" @@ -47,14 +44,6 @@ #include "libbf.h" #endif -#include "mocked.h" - -int isnan(double x) { return __builtin_isnan(x); } - -int isfinite(double x) { return __builtin_isfinite(x); } - -double trunc(double x) { return __builtin_truncl(x); } - #define OPTIMIZE 1 #define SHORT_OPCODES 1 #if defined(EMSCRIPTEN) @@ -203,7 +192,7 @@ typedef enum JSErrorEnum { JS_URI_ERROR, JS_INTERNAL_ERROR, JS_AGGREGATE_ERROR, - + JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */ } JSErrorEnum; @@ -266,7 +255,7 @@ struct JSRuntime { by the garbage collector) */ struct list_head gc_obj_list; /* list of JSGCObjectHeader.link. Used during JS_FreeValueRT() */ - struct list_head gc_zero_ref_count_list; + struct list_head gc_zero_ref_count_list; struct list_head tmp_obj_list; /* used during GC */ JSGCPhaseEnum gc_phase : 8; size_t malloc_gc_threshold; @@ -277,7 +266,7 @@ struct JSRuntime { uintptr_t stack_size; /* in bytes, 0 if no limit */ uintptr_t stack_top; uintptr_t stack_limit; /* lower stack limit */ - + JSValue current_exception; /* true if inside an out of memory error, to avoid recursing */ BOOL in_out_of_memory : 8; @@ -289,7 +278,7 @@ struct JSRuntime { JSHostPromiseRejectionTracker *host_promise_rejection_tracker; void *host_promise_rejection_tracker_opaque; - + struct list_head job_list; /* list of JSJobEntry.link */ JSModuleNormalizeFunc *module_normalize_func; @@ -299,7 +288,7 @@ struct JSRuntime { BOOL can_block : 8; /* TRUE if Atomics.wait can block */ /* used to allocate, free and clone SharedArrayBuffers */ JSSharedArrayBufferFunctions sab_funcs; - + /* Shape hash table */ int shape_hash_bits; int shape_hash_size; @@ -340,7 +329,7 @@ typedef struct JSStackFrame { int arg_count; int js_mode; /* 0 or JS_MODE_MATH for C functions */ /* only used in generators. Current stack pointer value. NULL if - the function is running. */ + the function is running. */ JSValue *cur_sp; } JSStackFrame; @@ -374,9 +363,9 @@ typedef struct JSVarRef { /* 0 : the JSVarRef is on the stack. header.link is an element of JSStackFrame.var_ref_list. - 1 : the JSVarRef is detached. header.link has the normal meanning + 1 : the JSVarRef is detached. header.link has the normal meanning */ - uint8_t is_detached : 1; + uint8_t is_detached : 1; uint8_t is_arg : 1; uint16_t var_idx; /* index of the corresponding function variable on the stack */ @@ -553,7 +542,7 @@ typedef struct JSVarDef { JSAtom var_name; /* index into fd->scopes of this variable lexical scope */ int scope_level; - /* during compilation: + /* during compilation: - if scope_level = 0: scope in which the variable is defined - if scope_level != 0: index into fd->vars of the next variable in the same or enclosing lexical scope @@ -561,7 +550,7 @@ typedef struct JSVarDef { index into fd->vars of the next variable in the same or enclosing lexical scope */ - int scope_next; + int scope_next; uint8_t is_const : 1; uint8_t is_lexical : 1; uint8_t is_captured : 1; @@ -808,7 +797,7 @@ struct JSModuleDef { BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */ /* true if evaluation yielded an exception. It is saved in eval_exception */ - BOOL eval_has_exception : 8; + BOOL eval_has_exception : 8; JSValue eval_exception; JSValue meta_obj; /* for import.meta */ }; @@ -876,7 +865,7 @@ struct JSObject { struct { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ - + uint8_t extensible : 1; uint8_t free_mark : 1; /* only used when freeing objects with cycles */ uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */ @@ -936,7 +925,7 @@ struct JSObject { struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ } u1; union { - JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ + JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ void *ptr; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ int8_t *int8_ptr; /* JS_CLASS_INT8_ARRAY */ uint8_t *uint8_ptr; /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */ @@ -1645,7 +1634,7 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) init_list_head(&rt->gc_obj_list); init_list_head(&rt->gc_zero_ref_count_list); rt->gc_phase = JS_GC_PHASE_NONE; - + #ifdef DUMP_LEAKS init_list_head(&rt->string_list); #endif @@ -2284,7 +2273,7 @@ void JS_FreeContext(JSContext *ctx) if (--ctx->header.ref_count > 0) return; assert(ctx->header.ref_count == 0); - + #ifdef DUMP_ATOMS JS_DumpAtoms(ctx->rt); #endif @@ -3336,7 +3325,7 @@ static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1) const char *cstr; char *cstr2; size_t len, len1; - + str = JS_AtomToString(ctx, name); if (JS_IsException(str)) return JS_ATOM_NULL; @@ -3874,7 +3863,7 @@ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) uint32_t c; StringBuffer b_s, *b = &b_s; size_t len1; - + p_start = (const uint8_t *)buf; p_end = p_start + buf_len; p = p_start; @@ -4366,7 +4355,7 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, sh->prop_size = prop_size; sh->prop_count = 0; sh->deleted_prop_count = 0; - + /* insert in the hash table */ sh->hash = shape_initial_hash(proto); sh->is_hashed = TRUE; @@ -4526,7 +4515,7 @@ static int compact_properties(JSContext *ctx, JSObject *p) uint32_t new_hash_size, i, j, new_hash_mask, new_size; JSShapeProperty *old_pr, *pr; JSProperty *prop, *new_prop; - + sh = p->shape; assert(!sh->is_hashed); @@ -4548,7 +4537,7 @@ static int compact_properties(JSContext *ctx, JSObject *p) list_del(&old_sh->header.link); memcpy(sh, old_sh, sizeof(JSShape)); list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); - + memset(prop_hash_end(sh) - new_hash_size, 0, sizeof(prop_hash_end(sh)[0]) * new_hash_size); @@ -4577,7 +4566,7 @@ static int compact_properties(JSContext *ctx, JSObject *p) p->shape = sh; js_free(ctx, get_alloc_from_shape(old_sh)); - + /* reduce the size of the object properties */ new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size); if (new_prop) @@ -4704,7 +4693,7 @@ static __maybe_unused void JS_DumpShapes(JSRuntime *rt) struct list_head *el; JSObject *p; JSGCObjectHeader *gp; - + printf("JSShapes: {\n"); printf("%5s %4s %14s %5s %5s %s\n", "SLOT", "REFS", "PROTO", "SIZE", "COUNT", "PROPS"); for(i = 0; i < rt->shape_hash_size; i++) { @@ -5032,7 +5021,7 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, JSValue func_obj; JSObject *p; JSAtom name_atom; - + func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); if (JS_IsException(func_obj)) return func_obj; @@ -5463,7 +5452,7 @@ static void free_zero_refcount(JSRuntime *rt) { struct list_head *el; JSGCObjectHeader *p; - + rt->gc_phase = JS_GC_PHASE_DECREF; for(;;) { el = rt->gc_zero_ref_count_list.next; @@ -5695,7 +5684,7 @@ static void gc_decref(JSRuntime *rt) { struct list_head *el, *el1; JSGCObjectHeader *p; - + init_list_head(&rt->tmp_obj_list); /* decrement the refcount of all the children of all the GC @@ -5742,7 +5731,7 @@ static void gc_scan(JSRuntime *rt) p->mark = 0; /* reset the mark for the next GC call */ mark_children(rt, p, gc_scan_incref_child); } - + /* restore the refcount of the objects to be deleted. */ list_for_each(el, &rt->tmp_obj_list) { p = list_entry(el, JSGCObjectHeader, link); @@ -5788,7 +5777,7 @@ static void gc_free_cycles(JSRuntime *rt) } } rt->gc_phase = JS_GC_PHASE_NONE; - + list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) { p = list_entry(el, JSGCObjectHeader, link); assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT || @@ -6455,7 +6444,7 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func) JSProperty *pr; JSShapeProperty *prs; JSValueConst val; - + if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT) return NULL; prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name); @@ -6486,7 +6475,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, const char *str1; JSObject *p; BOOL backtrace_barrier; - + js_dbuf_init(ctx, &dbuf); if (filename) { dbuf_printf(&dbuf, " at %s", filename); @@ -7326,7 +7315,7 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) JSProperty *pr; JSValue brand; JSAtom brand_atom; - + if (unlikely(JS_VALUE_GET_TAG(home_obj) != JS_TAG_OBJECT)) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; @@ -7348,7 +7337,7 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) brand = JS_DupValue(ctx, pr->u.value); } brand_atom = js_symbol_to_atom(ctx, brand); - + if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) { JS_ThrowTypeErrorNotAnObject(ctx); JS_FreeAtom(ctx, brand_atom); @@ -7369,7 +7358,7 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func) JSShapeProperty *prs; JSProperty *pr; JSValueConst brand; - + /* get the home object of 'func' */ if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) { not_obj: @@ -7391,7 +7380,7 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func) /* safety check */ if (unlikely(JS_VALUE_GET_TAG(brand) != JS_TAG_SYMBOL)) goto not_obj; - + /* get the brand array of 'obj' */ if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) goto not_obj; @@ -7466,7 +7455,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, BOOL is_enumerable, num_sorted; uint32_t num_key; JSAtomKindEnum kind; - + /* clear pointer for consistency in case of failure */ *ptab = NULL; *plen = 0; @@ -8326,7 +8315,7 @@ static int JS_SetPropertyGeneric(JSContext *ctx, JSPropertyDescriptor desc; JSValue obj1; JSObject *p; - + obj1 = JS_DupValue(ctx, obj); for(;;) { p = JS_VALUE_GET_OBJ(obj1); @@ -8380,7 +8369,7 @@ static int JS_SetPropertyGeneric(JSContext *ctx, JS_FreeValue(ctx, val); return JS_ThrowTypeErrorOrFalse(ctx, flags, "receiver is not an object"); } - + p = JS_VALUE_GET_OBJ(this_obj); /* modify the property in this_obj if it already exists */ @@ -9402,7 +9391,7 @@ static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj) JSShapeProperty *prs; JSValueConst val; JSString *p; - + prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name); if (!prs) return FALSE; @@ -9662,7 +9651,7 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, return 0; } flags = JS_PROP_THROW_STRICT; - if (is_strict_mode(ctx)) + if (is_strict_mode(ctx)) flags |= JS_PROP_NO_ADD; return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags); } @@ -9675,7 +9664,7 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) JSValue obj1; JSObject *p; int res; - + obj1 = JS_ToObject(ctx, obj); if (JS_IsException(obj1)) return -1; @@ -9922,7 +9911,7 @@ static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj) p = JS_VALUE_GET_OBJ(obj); return p->is_HTMLDDA; } - + static int JS_ToBoolFree(JSContext *ctx, JSValue val) { uint32_t tag = JS_VALUE_GET_TAG(val); @@ -10024,11 +10013,11 @@ static double js_strtod(const char *p, int radix, BOOL is_float) { double d; int c; - + if (!is_float || radix != 10) { uint64_t n_max, n; int int_exp, is_neg; - + is_neg = 0; if (*p == '-') { is_neg = 1; @@ -10076,7 +10065,7 @@ static double js_strtod(const char *p, int radix, BOOL is_float) /* accept _ between digits as a digit separator */ #define ATOD_ACCEPT_UNDERSCORES (1 << 5) /* allow a suffix to override the type */ -#define ATOD_ACCEPT_SUFFIX (1 << 6) +#define ATOD_ACCEPT_SUFFIX (1 << 6) /* default type */ #define ATOD_TYPE_MASK (3 << 7) #define ATOD_TYPE_FLOAT64 (0 << 7) @@ -10085,7 +10074,7 @@ static double js_strtod(const char *p, int radix, BOOL is_float) #define ATOD_TYPE_BIG_DECIMAL (3 << 7) /* assume bigint mode: floats are parsed as integers if no decimal point nor exponent */ -#define ATOD_MODE_BIGINT (1 << 9) +#define ATOD_MODE_BIGINT (1 << 9) /* accept -0x1 */ #define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10) @@ -10115,7 +10104,7 @@ static JSValue js_string_to_bigfloat(JSContext *ctx, const char *buf, bf_t *a; int ret; JSValue val; - + val = JS_NewBigFloat(ctx); if (JS_IsException(val)) return val; @@ -10141,7 +10130,7 @@ static JSValue js_string_to_bigdecimal(JSContext *ctx, const char *buf, bfdec_t *a; int ret; JSValue val; - + val = JS_NewBigDecimal(ctx); if (JS_IsException(val)) return val; @@ -10175,11 +10164,11 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, int i, j, len; BOOL buf_allocated = FALSE; JSValue val; - + /* optional separator between digits */ sep = (flags & ATOD_ACCEPT_UNDERSCORES) ? '_' : 256; has_legacy_octal = FALSE; - + p = str; p_start = p; is_neg = 0; @@ -10384,7 +10373,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp, val = JS_NewFloat64(ctx, d); } #endif - + done: if (buf_allocated) js_free_rt(ctx->rt, buf); @@ -10466,7 +10455,7 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val, const char *str; const char *p; size_t len; - + str = JS_ToCStringLen(ctx, &len, val); JS_FreeValue(ctx, val); if (!str) @@ -11799,7 +11788,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) } printf(" }"); } - + if (js_class_has_bytecode(p->class_id)) { JSFunctionBytecode *b = p->u.func.function_bytecode; JSVarRef **var_refs; @@ -12091,7 +12080,7 @@ static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val) uint32_t tag; JSBigDecimal *p; bfdec_t *r; - + tag = JS_VALUE_GET_NORM_TAG(val); switch(tag) { case JS_TAG_BIG_DECIMAL: @@ -12112,7 +12101,7 @@ static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val) const char *str, *p; size_t len; int flags; - + str = JS_ToCStringLen(ctx, &len, val); JS_FreeValue(ctx, val); if (!str) @@ -12228,7 +12217,7 @@ static __maybe_unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val) } else { bf_t a_s, *a, *r; int ret; - JSValue res; + JSValue res; res = JS_NewBigInt(ctx); if (JS_IsException(res)) @@ -12330,7 +12319,7 @@ static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val, { int64_t v; bf_t *a; - + if (JS_VALUE_GET_TAG(val) != JS_TAG_BIG_INT) return val; /* fail safe */ a = JS_GetBigInt(val); @@ -12458,10 +12447,10 @@ static __exception int js_call_binary_op_fallback(JSContext *ctx, JSOverloadableOperatorEnum ovop; JSObject *p; JSValueConst args[2]; - + if (!ctx->allow_operator_overloading) return 0; - + opset2_obj = JS_UNDEFINED; opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet); if (JS_IsException(opset1_obj)) @@ -12490,7 +12479,7 @@ static __exception int js_call_binary_op_fallback(JSContext *ctx, } ovop = get_ovop_from_opcode(op); - + if (opset1->operator_counter == opset2->operator_counter) { p = opset1->self_ops[ovop]; } else if (opset1->operator_counter > opset2->operator_counter) { @@ -12515,7 +12504,7 @@ static __exception int js_call_binary_op_fallback(JSContext *ctx, } else { new_op1 = JS_DupValue(ctx, op1); } - + if (opset2->is_primitive) { if (is_numeric) { new_op2 = JS_ToNumeric(ctx, op2); @@ -12532,7 +12521,7 @@ static __exception int js_call_binary_op_fallback(JSContext *ctx, /* XXX: could apply JS_ToPrimitive() if primitive type so that the operator function does not get a value object */ - + method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); if (ovop == JS_OVOP_LESS && (op == OP_lte || op == OP_gt)) { args[0] = new_op2; @@ -12643,7 +12632,7 @@ static __exception int js_call_unary_op_fallback(JSContext *ctx, if (!ctx->allow_operator_overloading) return 0; - + opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet); if (JS_IsException(opset1_obj)) goto exception; @@ -12699,7 +12688,7 @@ static int js_unary_arith_bigint(JSContext *ctx, bf_t a_s, *r, *a; int ret, v; JSValue res; - + if (op == OP_plus && !is_math_mode(ctx)) { JS_ThrowTypeError(ctx, "bigint argument with unary +"); JS_FreeValue(ctx, op1); @@ -12751,7 +12740,7 @@ static int js_unary_arith_bigfloat(JSContext *ctx, bf_t a_s, *r, *a; int ret, v; JSValue res; - + if (op == OP_plus && !is_math_mode(ctx)) { JS_ThrowTypeError(ctx, "bigfloat argument with unary +"); JS_FreeValue(ctx, op1); @@ -12800,7 +12789,7 @@ static int js_unary_arith_bigdecimal(JSContext *ctx, bfdec_t *r, *a; int ret, v; JSValue res; - + if (op == OP_plus && !is_math_mode(ctx)) { JS_ThrowTypeError(ctx, "bigdecimal argument with unary +"); JS_FreeValue(ctx, op1); @@ -12960,7 +12949,7 @@ static no_inline int js_not_slow(JSContext *ctx, JSValue *sp) { JSValue op1, val; int ret; - + op1 = sp[-1]; if (JS_IsObject(op1)) { ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not); @@ -12997,7 +12986,7 @@ static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op, bf_t a_s, b_s, *r, *a, *b; int ret; JSValue res; - + res = JS_NewBigFloat(ctx); if (JS_IsException(res)) { JS_FreeValue(ctx, op1); @@ -13058,7 +13047,7 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op, bf_t a_s, b_s, *r, *a, *b; int ret; JSValue res; - + res = JS_NewBigInt(ctx); if (JS_IsException(res)) goto fail; @@ -13245,7 +13234,7 @@ static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op, if (JS_IsException(res)) goto fail; r = JS_GetBigDecimal(res); - + a = JS_ToBigDecimal(ctx, op1); if (!a) goto fail; @@ -13672,7 +13661,7 @@ static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op, { bf_t a_s, b_s, *a, *b; int res; - + a = JS_ToBigFloat(ctx, &a_s, op1); if (!a) { JS_FreeValue(ctx, op2); @@ -13734,7 +13723,7 @@ static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op, } a = JS_ToBigDecimal(ctx, op1); b = JS_ToBigDecimal(ctx, op2); - + switch(op) { case OP_lt: res = bfdec_cmp_lt(a, b); /* if NaN return false */ @@ -14123,7 +14112,7 @@ static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a, bf_t r_s, *r = &r_s; double d; int ret; - + /* always convert to Float64 */ bf_init(ctx->bf_ctx, r); ret = bf_mul_pow_radix(r, a, 10, exponent, @@ -14845,7 +14834,7 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1) { JSObject *p; p = JS_VALUE_GET_OBJ(op1); - if (unlikely(p->is_HTMLDDA)) + if (unlikely(p->is_HTMLDDA)) atom = JS_ATOM_undefined; else if (JS_IsFunction(ctx, op1)) atom = JS_ATOM_function; @@ -15566,7 +15555,7 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp) int is_array_iterator; JSValue *arrp; uint32_t i, count32, pos; - + if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) { JS_ThrowInternalError(ctx, "invalid index for append"); return -1; @@ -15654,7 +15643,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, int ret, gpn_flags; JSPropertyDescriptor desc; BOOL is_enumerable; - + if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT) return 0; @@ -15675,7 +15664,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p, gpn_flags)) return -1; - + for (i = 0; i < tab_atom_count; i++) { if (pexcl) { ret = JS_GetOwnPropertyInternal(ctx, NULL, pexcl, tab_atom[i].atom); @@ -16038,7 +16027,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, sf->prev_frame = prev_sf; rt->current_stack_frame = sf; ctx = p->u.cfunc.realm; /* change the current realm */ - + #ifdef CONFIG_BIGNUM /* we only propagate the bignum mode as some runtime functions test it */ @@ -16226,7 +16215,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, #define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id, #if SHORT_OPCODES #define def(id, size, n_pop, n_push, f) -#else +#else #define def(id, size, n_pop, n_push, f) && case_default, #endif #include "quickjs-opcode.h" @@ -16320,7 +16309,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sf->prev_frame = rt->current_stack_frame; rt->current_stack_frame = sf; ctx = b->realm; /* set the current realm */ - + restart: for(;;) { int call_argc; @@ -16770,7 +16759,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_FreeValue(ctx, sp[-1]); sp -= 2; BREAK; - + CASE(OP_throw): JS_Throw(ctx, *--sp); goto exception; @@ -17585,7 +17574,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSAtom atom; JSValue val; - + atom = get_u32(pc); pc += 4; val = JS_NewSymbolFromAtom(ctx, atom, JS_ATOM_TYPE_PRIVATE); @@ -17594,7 +17583,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, *sp++ = val; } BREAK; - + CASE(OP_get_private_field): { JSValue val; @@ -17747,7 +17736,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { int class_flags; JSAtom atom; - + atom = get_u32(pc); class_flags = pc[4]; pc += 5; @@ -18737,7 +18726,7 @@ static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj) { JSObject *p; JSContext *realm; - + if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) return ctx; p = JS_VALUE_GET_OBJ(func_obj); @@ -18786,7 +18775,7 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, { JSValue proto, obj; JSContext *realm; - + if (JS_IsUndefined(ctor)) { proto = JS_DupValue(ctx, ctx->class_proto[class_id]); } else { @@ -18953,7 +18942,7 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) /* close the closure variables. */ close_var_refs(rt, sf); - + if (sf->arg_buf) { /* cannot free the function if it is running */ assert(sf->cur_sp != NULL); @@ -19999,7 +19988,7 @@ typedef struct JSFunctionDef { int var_object_idx; /* -1 if none */ int arg_var_object_idx; /* -1 if none (var object for the argument scope) */ int arguments_var_idx; /* -1 if none */ - int arguments_arg_idx; /* argument variable definition in argument scope, + int arguments_arg_idx; /* argument variable definition in argument scope, -1 if none */ int func_var_idx; /* variable containing the current function (-1 if none, only used if is_func_expr is true) */ @@ -20009,7 +19998,7 @@ typedef struct JSFunctionDef { int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */ int home_object_var_idx; BOOL need_home_object; - + int scope_level; /* index into fd->scopes if the current lexical scope */ int scope_first; /* index into vd->vars of first lexically scoped variable */ int scope_size; /* allocated size of fd->scopes array */ @@ -20026,7 +20015,7 @@ typedef struct JSFunctionDef { int last_opcode_pos; /* -1 if no last opcode */ int last_opcode_line_num; BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */ - + LabelSlot *label_slots; int label_size; /* allocated size for label_slots[] */ int label_count; @@ -20241,7 +20230,7 @@ int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const JSContext *ctx = s->ctx; va_list ap; int backtrace_flags; - + va_start(ap, fmt); JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE); va_end(ap); @@ -20591,7 +20580,7 @@ static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize, { char *buf, *new_buf; size_t size, new_size; - + buf = *pbuf; size = *psize; if (size >= (SIZE_MAX / 3) * 2) @@ -20621,7 +20610,7 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, char ident_buf[128], *buf; size_t ident_size, ident_pos; JSAtom atom; - + p = *pp; buf = ident_buf; ident_size = sizeof(ident_buf); @@ -20630,7 +20619,7 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp, buf[ident_pos++] = '#'; for(;;) { p1 = p; - + if (c < 128) { buf[ident_pos++] = c; } else { @@ -20668,11 +20657,11 @@ static __exception int next_token(JSParseState *s) int c; BOOL ident_has_escape; JSAtom atom; - + if (js_check_stack_overflow(s->ctx->rt, 0)) { return js_parse_error(s, "stack overflow"); } - + free_token(s, &s->token); p = s->last_ptr = s->buf_ptr; @@ -20799,14 +20788,14 @@ static __exception int next_token(JSParseState *s) case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': - case 'y': case 'z': + case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': + case 'Y': case 'Z': case '_': case '$': /* identifier */ @@ -20890,7 +20879,7 @@ static __exception int next_token(JSParseState *s) goto parse_number; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': - case '9': + case '9': /* number */ parse_number: { @@ -21148,7 +21137,7 @@ static __exception int next_token(JSParseState *s) case CP_LS: /* XXX: should avoid incrementing line_number, but needed to handle HTML comments */ - goto line_terminator; + goto line_terminator; default: if (lre_is_space(c)) { goto redo; @@ -21183,7 +21172,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) char ident_buf[128], *buf; size_t ident_size, ident_pos; JSAtom atom; - + p = *pp; buf = ident_buf; ident_size = sizeof(ident_buf); @@ -21215,11 +21204,11 @@ static __exception int json_next_token(JSParseState *s) const uint8_t *p; int c; JSAtom atom; - + if (js_check_stack_overflow(s->ctx->rt, 0)) { return js_parse_error(s, "stack overflow"); } - + free_token(s, &s->token); p = s->last_ptr = s->buf_ptr; @@ -21329,14 +21318,14 @@ static __exception int json_next_token(JSParseState *s) case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': - case 'y': case 'z': + case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': + case 'Y': case 'Z': case '_': case '$': /* identifier : only pure ascii characters are accepted */ @@ -21363,7 +21352,7 @@ static __exception int json_next_token(JSParseState *s) goto parse_number; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': - case '9': + case '9': /* number */ parse_number: { @@ -21411,7 +21400,7 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) { const uint8_t *p; uint32_t c; - + /* skip spaces and comments */ p = *pp; for (;;) { @@ -21642,7 +21631,7 @@ static int emit_goto(JSParseState *s, int opcode, int label) static int cpool_add(JSParseState *s, JSValue val) { JSFunctionDef *fd = s->cur_func; - + if (js_resize_array(s->ctx, (void *)&fd->cpool, sizeof(fd->cpool[0]), &fd->cpool_size, fd->cpool_count + 1)) return -1; @@ -22028,7 +22017,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, if (find_var_in_child_scope(ctx, fd, name, fd->scope_level) >= 0) { return js_parse_error(s, "invalid redefinition of a variable"); } - + if (fd->is_global_var) { JSGlobalVar *hf; hf = find_global_var(fd, name); @@ -22037,7 +22026,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, return js_parse_error(s, "invalid redefinition of global identifier"); } } - + if (fd->is_eval && (fd->eval_type == JS_EVAL_TYPE_GLOBAL || fd->eval_type == JS_EVAL_TYPE_MODULE) && @@ -22308,7 +22297,7 @@ static int __exception js_parse_property_name(JSParseState *s, BOOL is_non_reserved_ident; JSAtom name; int prop_type; - + prop_type = PROP_TYPE_IDENT; if (allow_method) { if (token_is_pseudo_keyword(s, JS_ATOM_get) @@ -22534,7 +22523,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ if (level >= sizeof(state)) goto done; state[level++] = '`'; - } + } break; case TOK_EOF: goto done; @@ -22551,7 +22540,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ case '=': bits |= SKIP_HAS_ASSIGNMENT; break; - + case TOK_DIV_ASSIGN: tok_len = 2; goto parse_regexp; @@ -22761,15 +22750,15 @@ static __exception int js_parse_object_literal(JSParseState *s) } /* allow the 'in' binary operator */ -#define PF_IN_ACCEPTED (1 << 0) +#define PF_IN_ACCEPTED (1 << 0) /* allow function calls parsing in js_parse_postfix_expr() */ -#define PF_POSTFIX_CALL (1 << 1) +#define PF_POSTFIX_CALL (1 << 1) /* allow arrow functions parsing in js_parse_postfix_expr() */ -#define PF_ARROW_FUNC (1 << 2) +#define PF_ARROW_FUNC (1 << 2) /* allow the exponentiation operator in js_parse_unary() */ -#define PF_POW_ALLOWED (1 << 3) +#define PF_POW_ALLOWED (1 << 3) /* forbid the exponentiation operator in js_parse_unary() */ -#define PF_POW_FORBIDDEN (1 << 4) +#define PF_POW_FORBIDDEN (1 << 4) static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags); @@ -22788,7 +22777,7 @@ static __exception int js_parse_class_default_ctor(JSParseState *s, int ret, line_num; JSParseFunctionEnum func_type; const uint8_t *saved_buf_end; - + js_parse_get_pos(s, &pos); if (has_super) { /* spec change: no argument evaluation */ @@ -22835,7 +22824,7 @@ static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd, static void emit_class_field_init(JSParseState *s) { int label_next; - + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_class_fields_init); emit_u16(s, s->cur_func->scope_level); @@ -22843,13 +22832,13 @@ static void emit_class_field_init(JSParseState *s) /* no need to call the class field initializer if not defined */ emit_op(s, OP_dup); label_next = emit_goto(s, OP_if_false, -1); - + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); - + emit_op(s, OP_swap); - + emit_op(s, OP_call_method); emit_u16(s, 0); @@ -22874,29 +22863,29 @@ static __exception int emit_class_init_start(JSParseState *s, ClassFieldsDef *cf) { int label_add_brand; - + cf->fields_init_fd = js_parse_function_class_fields_init(s); if (!cf->fields_init_fd) return -1; s->cur_func = cf->fields_init_fd; - + /* XXX: would be better to add the code only if needed, maybe in a later pass */ emit_op(s, OP_push_false); /* will be patched later */ cf->brand_push_pos = cf->fields_init_fd->last_opcode_pos; label_add_brand = emit_goto(s, OP_if_false, -1); - + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); - + emit_op(s, OP_scope_get_var); emit_atom(s, JS_ATOM_home_object); emit_u16(s, 0); - + emit_op(s, OP_add_brand); - + emit_label(s, label_add_brand); s->cur_func = s->cur_func->parent; @@ -22913,7 +22902,7 @@ static __exception int add_brand(JSParseState *s, ClassFieldsDef *cf) } /* patch the start of the function to enable the OP_add_brand code */ cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true; - + cf->has_brand = TRUE; } return 0; @@ -22922,11 +22911,11 @@ static __exception int add_brand(JSParseState *s, ClassFieldsDef *cf) static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf) { int cpool_idx; - + s->cur_func = cf->fields_init_fd; emit_op(s, OP_return_undef); s->cur_func = s->cur_func->parent; - + cpool_idx = cpool_add(s, JS_NULL); cf->fields_init_fd->parent_cpool_idx = cpool_idx; emit_op(s, OP_fclosure); @@ -22949,7 +22938,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, const uint8_t *class_start_ptr = s->token.ptr; const uint8_t *start_ptr; ClassFieldsDef class_fields[2]; - + /* classes are parsed and executed in strict mode */ saved_js_mode = fd->js_mode; fd->js_mode |= JS_MODE_STRICT; @@ -23012,7 +23001,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, } else { class_name1 = class_name; } - + emit_op(s, OP_define_class); emit_atom(s, class_name1); emit_u8(s, class_flags); @@ -23024,7 +23013,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, cf->computed_fields_count = 0; cf->has_brand = FALSE; } - + ctor_fd = NULL; while (s->token.val != '}') { if (s->token.val == ';') { @@ -23054,7 +23043,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, } is_private = prop_type & PROP_TYPE_PRIVATE; prop_type &= ~PROP_TYPE_PRIVATE; - + if ((name == JS_ATOM_constructor && !is_static && prop_type != PROP_TYPE_IDENT) || (name == JS_ATOM_prototype && is_static) || @@ -23100,7 +23089,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, if (is_set) { JSAtom setter_name; int ret; - + setter_name = get_private_setter_name(ctx, name); if (setter_name == JS_ATOM_NULL) goto fail; @@ -23126,7 +23115,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, } else if (prop_type == PROP_TYPE_IDENT && s->token.val != '(') { ClassFieldsDef *cf = &class_fields[is_static]; JSAtom field_var_name = JS_ATOM_NULL; - + /* class field */ /* XXX: spec: not consistent with method name checks */ @@ -23134,7 +23123,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, js_parse_error(s, "invalid field name"); goto fail; } - + if (is_private) { if (find_private_class_field(ctx, fd, name, fd->scope_level) >= 0) { @@ -23184,7 +23173,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, emit_atom(s, name); emit_u16(s, s->cur_func->scope_level); } - + if (s->token.val == '=') { if (next_token(s)) goto fail; @@ -23211,7 +23200,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, } else { JSParseFunctionEnum func_type; JSFunctionKindEnum func_kind; - + func_type = JS_PARSE_FUNC_METHOD; func_kind = JS_FUNC_NORMAL; if (prop_type == PROP_TYPE_STAR) { @@ -23303,7 +23292,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, { ClassFieldsDef *cf = &class_fields[0]; int var_idx; - + var_idx = define_var(s, fd, JS_ATOM_class_fields_init, JS_VAR_DEF_CONST); if (var_idx < 0) @@ -23330,7 +23319,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, emit_u16(s, 0); emit_op(s, OP_drop); } - + if (class_name != JS_ATOM_NULL) { /* store the class name in the scoped class name variable (it is independent from the class statement variable @@ -23734,7 +23723,7 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, default: break; } - + switch(opcode) { case OP_scope_get_var: /* val -- */ assert(special == PUT_LVALUE_NOKEEP || @@ -23788,7 +23777,7 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok) { JSFunctionDef *fd = s->cur_func; JSVarDefEnum var_def_type; - + if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) { return js_parse_error(s, "yield is a reserved identifier"); } @@ -23899,7 +23888,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg, JSAtom prop_name, var_name; int opcode, scope, tok1, skip_bits; BOOL has_initializer; - + if (has_ellipsis < 0) { /* pre-parse destructuration target for spread detection */ js_parse_skip_parens_token(s, &skip_bits, FALSE); @@ -24338,7 +24327,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) FuncCallType call_type; int optional_chaining_label; BOOL accept_lparen = (parse_flags & PF_POSTFIX_CALL) != 0; - + call_type = FUNC_CALL_NORMAL; switch(s->token.val) { case TOK_NUMBER: @@ -24394,7 +24383,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) if (next_token(s)) return -1; break; - + case TOK_DIV_ASSIGN: s->buf_ptr -= 2; goto parse_regexp; @@ -24636,7 +24625,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) for(;;) { JSFunctionDef *fd = s->cur_func; BOOL has_optional_chain = FALSE; - + if (s->token.val == TOK_QUESTION_MARK_DOT) { /* optional chaining */ if (next_token(s)) @@ -25133,7 +25122,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags) put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND, FALSE); if (next_token(s)) - return -1; + return -1; } break; } @@ -25370,7 +25359,7 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op, static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags) { int label1; - + if (js_parse_logical_and_or(s, TOK_LOR, parse_flags)) return -1; if (s->token.val == TOK_DOUBLE_QUESTION_MARK) { @@ -25378,12 +25367,12 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags) for(;;) { if (next_token(s)) return -1; - + emit_op(s, OP_dup); emit_op(s, OP_is_undefined_or_null); emit_goto(s, OP_if_false, label1); emit_op(s, OP_drop); - + if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC)) return -1; if (s->token.val != TOK_DOUBLE_QUESTION_MARK) @@ -25434,7 +25423,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) if (s->token.val == TOK_YIELD) { BOOL is_star = FALSE, is_async; - + if (!(s->cur_func->func_kind & JS_FUNC_GENERATOR)) return js_parse_error(s, "unexpected 'yield' keyword"); if (!s->cur_func->in_function_body) @@ -25472,9 +25461,9 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) undefined) */ emit_op(s, OP_drop); emit_op(s, OP_undefined); - + emit_op(s, OP_undefined); /* initial value */ - + emit_label(s, label_loop); emit_op(s, OP_iterator_next); if (is_async) @@ -25498,13 +25487,13 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) label_return = emit_goto(s, OP_if_true, -1); emit_op(s, OP_drop); emit_goto(s, OP_goto, label_loop); - + emit_label(s, label_return); emit_op(s, OP_push_i32); emit_u32(s, 2); emit_op(s, OP_strict_eq); label_throw = emit_goto(s, OP_if_true, -1); - + /* return handling */ if (is_async) emit_op(s, OP_await); @@ -25520,13 +25509,13 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_get_field); emit_atom(s, JS_ATOM_value); - + emit_label(s, label_return1); emit_op(s, OP_nip); emit_op(s, OP_nip); emit_op(s, OP_nip); emit_return(s, TRUE); - + /* throw handling */ emit_label(s, label_throw); emit_op(s, OP_iterator_call); @@ -25551,7 +25540,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_throw_error); emit_atom(s, JS_ATOM_NULL); emit_u8(s, JS_THROW_ERROR_ITERATOR_THROW); - + emit_label(s, label_next); emit_op(s, OP_get_field); emit_atom(s, JS_ATOM_value); @@ -25561,7 +25550,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) emit_op(s, OP_nip); } else { int label_next; - + if (is_async) emit_op(s, OP_await); emit_op(s, OP_yield); @@ -25616,7 +25605,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE); } else if (op >= TOK_LAND_ASSIGN && op <= TOK_DOUBLE_QUESTION_MARK_ASSIGN) { int label, label1, depth_lvalue, label2; - + if (next_token(s)) return -1; if (get_lvalue(s, &opcode, &scope, &name, &label, @@ -25629,7 +25618,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) label1 = emit_goto(s, op == TOK_LOR_ASSIGN ? OP_if_true : OP_if_false, -1); emit_op(s, OP_drop); - + if (js_parse_assign_expr2(s, parse_flags)) { JS_FreeAtom(s->ctx, name); return -1; @@ -25638,7 +25627,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) if (opcode == OP_get_ref_value && name == name0) { set_object_name(s, name); } - + switch(depth_lvalue) { case 1: emit_op(s, OP_insert2); @@ -25658,7 +25647,7 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags) put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_NOKEEP_DEPTH, FALSE); label2 = emit_goto(s, OP_goto, -1); - + emit_label(s, label1); /* remove the lvalue stack entries */ @@ -26876,7 +26865,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, emit_label(s, label_finally); if (s->token.val == TOK_FINALLY) { int saved_eval_ret_idx = 0; /* avoid warning */ - + if (next_token(s)) goto fail; /* on the stack: ret_value gosub_ret_value */ @@ -26896,7 +26885,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, emit_u16(s, saved_eval_ret_idx); set_eval_ret_undefined(s); } - + if (js_parse_block(s)) goto fail; @@ -27001,7 +26990,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (js_parse_expect_semi(s)) goto fail; break; - + case TOK_ENUM: case TOK_EXPORT: case TOK_EXTENDS: @@ -27318,7 +27307,7 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) { struct list_head *el; JSModuleDef *m; - + /* first look at the loaded modules */ list_for_each(el, &ctx->loaded_modules) { m = list_entry(el, JSModuleDef, link); @@ -27383,7 +27372,7 @@ static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx, { const char *base_cname, *cname; JSModuleDef *m; - + base_cname = JS_AtomToCString(ctx, base_module_name); if (!base_cname) return NULL; @@ -27921,7 +27910,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) BOOL is_c_module; int i; JSVarRef *var_ref; - + if (m->func_created) return 0; @@ -27945,7 +27934,7 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) m->func_created = TRUE; /* do it on the dependencies */ - + for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; if (js_create_module_function(ctx, rme->module) < 0) @@ -27953,9 +27942,9 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) } return 0; -} +} + - /* Prepare a module to be executed by resolving all the imported variables. */ static int js_link_module(JSContext *ctx, JSModuleDef *m) @@ -27967,7 +27956,7 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m) JSObject *p; BOOL is_c_module; JSValue ret_val; - + if (m->instantiated) return 0; m->instantiated = TRUE; @@ -28168,7 +28157,7 @@ static JSValue js_import_meta(JSContext *ctx) { JSAtom filename; JSModuleDef *m; - + filename = JS_GetScriptOrModuleName(ctx, 0); if (filename == JS_ATOM_NULL) goto fail; @@ -28191,11 +28180,11 @@ JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename, { JSModuleDef *m; JSValue ret, func_obj; - + m = js_host_resolve_imported_module(ctx, basename, filename); if (!m) return NULL; - + if (js_resolve_module(ctx, m) < 0) { js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED); return NULL; @@ -28231,7 +28220,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx, filename = JS_ToCString(ctx, specifier); if (!filename) goto exception; - + m = JS_RunModule(ctx, basename, filename); JS_FreeCString(ctx, filename); if (!m) @@ -28273,7 +28262,7 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) JS_FreeAtom(ctx, basename); if (JS_IsException(basename_val)) return basename_val; - + promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) { JS_FreeValue(ctx, basename_val); @@ -28284,7 +28273,7 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) args[1] = resolving_funcs[1]; args[2] = basename_val; args[3] = specifier; - + JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args); JS_FreeValue(ctx, basename_val); @@ -28694,7 +28683,7 @@ static __exception int js_parse_source_element(JSParseState *s) { JSFunctionDef *fd = s->cur_func; int tok; - + if (s->token.val == TOK_FUNCTION || (token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, TRUE) == TOK_FUNCTION)) { @@ -28786,7 +28775,7 @@ static void free_bytecode_atoms(JSRuntime *rt, int pos, len, op; JSAtom atom; const JSOpCode *oi; - + pos = 0; while (pos < bc_len) { op = bc_buf[pos]; @@ -28794,7 +28783,7 @@ static void free_bytecode_atoms(JSRuntime *rt, oi = &short_opcode_info(op); else oi = &opcode_info[op]; - + len = oi->size; switch(oi->fmt) { case OP_FMT_atom: @@ -29577,7 +29566,7 @@ static void var_object_test(JSContext *ctx, JSFunctionDef *s, update_label(s, *plabel_done, 1); s->jump_size++; } - + /* return the position of the next opcode */ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, JSAtom var_name, int scope_level, int op, @@ -29783,7 +29772,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, is_arg_scope = (idx == ARG_SCOPE_END); if (var_idx >= 0) break; - + if (!is_arg_scope) { var_idx = find_var(ctx, fd, var_name); if (var_idx >= 0) @@ -29827,7 +29816,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, dbuf_put_u16(bc, idx); var_object_test(ctx, s, var_name, op, bc, &label_done, 0); } - + if (fd->is_eval) break; /* it it necessarily the top level function */ } @@ -30030,7 +30019,7 @@ static void get_loc_or_ref(DynBuf *bc, BOOL is_ref, int idx) { /* if the field is not initialized, the error is catched when accessing it */ - if (is_ref) + if (is_ref) dbuf_putc(bc, OP_get_var_ref); else dbuf_putc(bc, OP_get_loc); @@ -30045,7 +30034,7 @@ static int resolve_scope_private_field1(JSContext *ctx, int idx, var_kind; JSFunctionDef *fd; BOOL is_ref; - + fd = s; is_ref = FALSE; for(;;) { @@ -30371,7 +30360,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, int i, count; JSVarDef *vd; BOOL is_arg_scope; - + count = b->arg_count + b->var_count + b->closure_var_count; s->closure_var = NULL; s->closure_var_count = 0; @@ -30605,7 +30594,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy visible if there are cyclic module references */ if (s->module) { label_next = new_label_fd(s, -1); - + /* if 'this' is true, initialize the global variables and return */ dbuf_putc(bc, OP_push_this); dbuf_putc(bc, OP_if_false); @@ -30613,7 +30602,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy update_label(s, label_next, 1); s->jump_size++; } - + /* add the global variables (only happens if s->is_global_var is true) */ for(i = 0; i < s->global_var_count; i++) { @@ -30642,7 +30631,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy } if (!has_closure) { int flags; - + flags = 0; if (s->eval_type != JS_EVAL_TYPE_GLOBAL) flags |= JS_PROP_CONFIGURABLE; @@ -30650,11 +30639,11 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy /* global function definitions need a specific handling */ dbuf_putc(bc, OP_fclosure); dbuf_put_u32(bc, hf->cpool_idx); - + dbuf_putc(bc, OP_define_func); dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name)); dbuf_putc(bc, flags); - + goto done_global_var; } else { if (hf->is_lexical) { @@ -30698,7 +30687,7 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy if (s->module) { dbuf_putc(bc, OP_return_undef); - + dbuf_putc(bc, OP_label); dbuf_put_u32(bc, label_next); s->label_slots[label_next].pos2 = bc->size; @@ -30803,7 +30792,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) for(i = 0; i < s->global_var_count; i++) { JSGlobalVar *hf = &s->global_vars[i]; int flags; - + /* check if global variable (XXX: simplify) */ for(idx = 0; idx < s->closure_var_count; idx++) { JSClosureVar *cv = &s->closure_var[idx]; @@ -30825,7 +30814,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) cv->var_name == JS_ATOM__arg_var_) goto next; } - + dbuf_putc(&bc_out, OP_check_define_var); dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name)); flags = 0; @@ -31104,7 +31093,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) case OP_set_class_name: /* only used during parsing */ break; - + default: no_change: dbuf_put(&bc_out, bc_buf + pos, len); @@ -32665,7 +32654,7 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->realm = JS_DupContext(ctx); add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); - + #if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1) if (!(fd->js_mode & JS_MODE_STRIP)) { js_dump_function_bytecode(ctx, b); @@ -32877,7 +32866,7 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s) { JSFunctionDef *fd; - + fd = js_new_function_def(s->ctx, s->cur_func, FALSE, FALSE, s->filename, 0); if (!fd) @@ -32885,7 +32874,7 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s) fd->func_name = JS_ATOM_NULL; fd->has_prototype = FALSE; fd->has_home_object = TRUE; - + fd->has_arguments_binding = FALSE; fd->has_this_binding = TRUE; fd->is_derived_class_constructor = FALSE; @@ -32893,7 +32882,7 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s) fd->super_call_allowed = FALSE; fd->super_allowed = fd->has_home_object; fd->arguments_allowed = FALSE; - + fd->func_kind = JS_FUNC_NORMAL; fd->func_type = JS_PARSE_FUNC_METHOD; return fd; @@ -33069,7 +33058,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) { emit_class_field_init(s); } - + /* parse arguments */ fd->has_simple_parameter_list = TRUE; fd->has_parameter_expressions = FALSE; @@ -33104,7 +33093,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, if (push_scope(s) < 0) return -1; } - + while (s->token.val != ')') { JSAtom name; BOOL rest = FALSE; @@ -33169,7 +33158,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, has_opt_arg = TRUE; } else if (s->token.val == '=') { int label; - + fd->has_simple_parameter_list = FALSE; has_opt_arg = TRUE; @@ -33252,7 +33241,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, } idx = vd->scope_next; } - + /* the argument scope has no parent, hence we don't use pop_scope(s) */ emit_op(s, OP_leave_scope); emit_u16(s, fd->scope_level); @@ -33261,7 +33250,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, fd->scope_level = 0; fd->scope_first = fd->scopes[fd->scope_level].first; } - + if (next_token(s)) goto fail; @@ -33375,7 +33364,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, /* it is considered as defined at the top level (needed for annex B.3.3.4 and B.3.3.5 checks) */ - hf->scope_level = 0; + hf->scope_level = 0; hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0); /* store directly into global var, bypass lexical scope */ emit_op(s, OP_dup); @@ -33656,7 +33645,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, push_scope(s); /* body scope */ fd->body_scope = fd->scope_level; - + err = js_parse_program(s); if (err) { fail: @@ -33791,13 +33780,13 @@ static int js_object_list_resize_hash(JSContext *ctx, JSObjectList *s, js_free(ctx, s->hash_table); s->hash_table = new_hash_table; s->hash_size = new_hash_size; - + for(i = 0; i < s->hash_size; i++) { s->hash_table[i] = -1; } for(i = 0; i < s->object_count; i++) { e = &s->object_tab[i]; - h = js_object_list_get_hash(e->obj, s->hash_size); + h = js_object_list_get_hash(e->obj, s->hash_size); e->hash_next = s->hash_table[h]; s->hash_table[h] = i; } @@ -33810,7 +33799,7 @@ static int js_object_list_add(JSContext *ctx, JSObjectList *s, JSObject *obj) { JSObjectListEntry *e; uint32_t h, new_hash_size; - + if (js_resize_array(ctx, (void *)&s->object_tab, sizeof(s->object_tab[0]), &s->object_size, s->object_count + 1)) @@ -33823,7 +33812,7 @@ static int js_object_list_add(JSContext *ctx, JSObjectList *s, JSObject *obj) return -1; } e = &s->object_tab[s->object_count++]; - h = js_object_list_get_hash(obj, s->hash_size); + h = js_object_list_get_hash(obj, s->hash_size); e->obj = obj; e->hash_next = s->hash_table[h]; s->hash_table[h] = s->object_count - 1; @@ -33839,7 +33828,7 @@ static int js_object_list_find(JSContext *ctx, JSObjectList *s, JSObject *obj) /* must test empty size because there is no hash table */ if (s->object_count == 0) return -1; - h = js_object_list_get_hash(obj, s->hash_size); + h = js_object_list_get_hash(obj, s->hash_size); p = s->hash_table[h]; while (p != -1) { e = &s->object_tab[p]; @@ -34231,7 +34220,7 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) int bpos, d; uint8_t v8; size_t i0; - + /* little endian BCD */ i = 0; while (i < a->len && a->tab[i] == 0) @@ -34251,7 +34240,7 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) return -1; } bc_put_leb128(s, len); - + bpos = 0; v8 = 0; i0 = i; @@ -34289,7 +34278,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj); uint32_t flags; int idx, i; - + bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE); flags = idx = 0; bc_set_flags(&flags, &idx, b->has_prototype, 1); @@ -34307,7 +34296,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) bc_put_u16(s, flags); bc_put_u8(s, b->js_mode); bc_put_atom(s, b->func_name); - + bc_put_leb128(s, b->arg_count); bc_put_leb128(s, b->var_count); bc_put_leb128(s, b->defined_arg_count); @@ -34334,7 +34323,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) } else { bc_put_leb128(s, 0); } - + for(i = 0; i < b->closure_var_count; i++) { JSClosureVar *cv = &b->closure_var[i]; bc_put_atom(s, cv->var_name); @@ -34348,17 +34337,17 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) assert(idx <= 8); bc_put_u8(s, flags); } - + if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len)) goto fail; - + if (b->has_debug) { bc_put_atom(s, b->debug.filename); bc_put_leb128(s, b->debug.line_num); bc_put_leb128(s, b->debug.pc2line_len); dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len); } - + for(i = 0; i < b->cpool_count; i++) { if (JS_WriteObjectRec(s, b->cpool[i])) goto fail; @@ -34372,16 +34361,16 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj) { JSModuleDef *m = JS_VALUE_GET_PTR(obj); int i; - + bc_put_u8(s, BC_TAG_MODULE); bc_put_atom(s, m->module_name); - + bc_put_leb128(s, m->req_module_entries_count); for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; bc_put_atom(s, rme->module_name); } - + bc_put_leb128(s, m->export_entries_count); for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; @@ -34394,13 +34383,13 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj) } bc_put_atom(s, me->export_name); } - + bc_put_leb128(s, m->star_export_entries_count); for(i = 0; i < m->star_export_entries_count; i++) { JSStarExportEntry *se = &m->star_export_entries[i]; bc_put_leb128(s, se->req_module_idx); } - + bc_put_leb128(s, m->import_entries_count); for(i = 0; i < m->import_entries_count; i++) { JSImportEntry *mi = &m->import_entries[i]; @@ -34408,7 +34397,7 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj) bc_put_atom(s, mi->import_name); bc_put_leb128(s, mi->req_module_idx); } - + if (JS_WriteObjectRec(s, m->func_obj)) goto fail; return 0; @@ -34423,7 +34412,7 @@ static int JS_WriteArray(BCWriterState *s, JSValueConst obj) JSValue val; int ret; BOOL is_template; - + if (s->allow_bytecode && !p->extensible) { /* not extensible array: we consider it is a template when we are saving bytecode */ @@ -34597,7 +34586,7 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) { JSObject *p = JS_VALUE_GET_OBJ(obj); int ret, idx; - + if (s->allow_reference) { idx = js_object_list_find(s->ctx, &s->object_list, p); if (idx >= 0) { @@ -34738,7 +34727,7 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, s->first_atom = 1; js_dbuf_init(ctx, &s->dbuf); js_object_list_init(&s->object_list); - + if (JS_WriteObjectRec(s, obj)) goto fail; if (JS_WriteObjectAtoms(s)) @@ -34786,7 +34775,7 @@ typedef struct BCReaderState { JSObject **objects; int objects_count; int objects_size; - + #ifdef DUMP_READ_OBJECT const uint8_t *ptr_last; int level; @@ -35071,7 +35060,7 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) limb_t v; bf_t *a; int bpos, d; - + p = js_new_bf(s->ctx); if (!p) goto fail; @@ -35283,7 +35272,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) b = js_mallocz(ctx, function_size); if (!b) return JS_EXCEPTION; - + memcpy(b, &bc, offsetof(JSFunctionBytecode, debug)); b->header.ref_count = 1; if (local_count != 0) { @@ -35295,9 +35284,9 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) if (b->cpool_count != 0) { b->cpool = (void *)((uint8_t*)b + cpool_offset); } - + add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); - + obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b); #ifdef DUMP_READ_OBJECT @@ -35410,7 +35399,7 @@ static JSValue JS_ReadModule(BCReaderState *s) JSAtom module_name; int i; uint8_t v8; - + if (bc_get_atom(s, &module_name)) goto fail; #ifdef DUMP_READ_OBJECT @@ -35511,7 +35500,7 @@ static JSValue JS_ReadObjectTag(BCReaderState *s) JSAtom atom; JSValue val; int ret; - + obj = JS_NewObject(ctx); if (BC_add_object_ref(s, obj)) goto fail; @@ -35591,7 +35580,7 @@ static JSValue JS_ReadTypedArray(BCReaderState *s) uint8_t array_tag; JSValueConst args[3]; uint32_t offset, len, idx; - + if (bc_get_u8(s, &array_tag)) return JS_EXCEPTION; if (array_tag >= JS_TYPED_ARRAY_COUNT) @@ -35636,7 +35625,7 @@ static JSValue JS_ReadArrayBuffer(BCReaderState *s) JSContext *ctx = s->ctx; uint32_t byte_length; JSValue obj; - + if (bc_get_leb128(s, &byte_length)) return JS_EXCEPTION; if (unlikely(s->buf_end - s->ptr < byte_length)) { @@ -35662,7 +35651,7 @@ static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s) uint8_t *data_ptr; JSValue obj; uint64_t u64; - + if (bc_get_leb128(s, &byte_length)) return JS_EXCEPTION; if (bc_get_u64(s, &u64)) @@ -36172,7 +36161,7 @@ static void JS_SetConstructor2(JSContext *ctx, set_cycle_flag(ctx, proto); } -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, +void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, JSValueConst proto) { JS_SetConstructor2(ctx, func_obj, proto, @@ -37015,7 +37004,7 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, if (!res) { return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false"); } - + p = JS_VALUE_GET_OBJ(obj); flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK; if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags)) @@ -37056,7 +37045,7 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, JSPropertyEnum *props; uint32_t len, i; int flags, res; - + if (!JS_IsObject(obj)) return JS_TRUE; @@ -37085,7 +37074,7 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, if (res < 0) return JS_EXCEPTION; res ^= 1; -done: +done: js_free_prop_enum(ctx, props, len); return JS_NewBool(ctx, res); @@ -37108,14 +37097,14 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, obj = JS_NewObject(ctx); if (JS_IsException(obj)) return obj; - + iter = JS_GetIterator(ctx, iterable, FALSE); if (JS_IsException(iter)) goto fail; next_method = JS_GetProperty(ctx, iter, JS_ATOM_next); if (JS_IsException(next_method)) goto fail; - + for(;;) { JSValue key, value, item; item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done); @@ -37125,7 +37114,7 @@ static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, item); break; } - + key = JS_UNDEFINED; value = JS_UNDEFINED; if (!JS_IsObject(item)) { @@ -37510,7 +37499,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, string_buffer_init(ctx, b, 0); string_buffer_putc8(b, '('); - + if (func_kind == JS_FUNC_ASYNC || func_kind == JS_FUNC_ASYNC_GENERATOR) { string_buffer_puts8(b, "async "); } @@ -37843,7 +37832,7 @@ static JSValue iterator_to_array(JSContext *ctx, JSValueConst items) JSValue v, r = JS_UNDEFINED; int64_t k; BOOL done; - + iter = JS_GetIterator(ctx, items, FALSE); if (JS_IsException(iter)) goto exception; @@ -37889,7 +37878,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, if (!JS_IsObject(proto)) { JSContext *realm; JSValueConst proto1; - + JS_FreeValue(ctx, proto); realm = JS_GetFunctionRealm(ctx, new_target); if (!realm) @@ -37977,7 +37966,7 @@ static JSValue js_aggregate_error_constructor(JSContext *ctx, JSValueConst errors) { JSValue obj; - + obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[JS_AGGREGATE_ERROR], JS_CLASS_ERROR); @@ -38043,7 +38032,7 @@ static int JS_CopySubArray(JSContext *ctx, fromPresent = JS_TryGetPropertyInt64(ctx, obj, from, &val); if (fromPresent < 0) goto exception; - + if (fromPresent) { if (JS_SetPropertyInt64(ctx, obj, to, val) < 0) goto exception; @@ -38251,7 +38240,7 @@ static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj, JSValue ctor, ret, species; int res; JSContext *realm; - + res = JS_IsArray(ctx, obj); if (res < 0) return JS_EXCEPTION; @@ -38416,7 +38405,7 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, this_arg = JS_UNDEFINED; if (argc > 1) this_arg = argv[1]; - + if (check_function(ctx, func)) goto exception; @@ -40115,7 +40104,7 @@ static int js_string_define_own_property(JSContext *ctx, uint32_t idx; JSObject *p; JSString *p1, *p2; - + if (__JS_AtomIsTaggedInt(prop)) { idx = __JS_AtomToUInt32(prop); p = JS_VALUE_GET_OBJ(this_obj); @@ -40281,7 +40270,7 @@ static JSValue js_string_raw(JSContext *ctx, JSValueConst this_val, goto exception; if (js_get_length64(ctx, &n, raw) < 0) goto exception; - + for (i = 0; i < n; i++) { val = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, raw, i)); if (JS_IsException(val)) @@ -40634,7 +40623,7 @@ static int check_regexp_g_flag(JSContext *ctx, JSValueConst regexp) { int ret; JSValue flags; - + ret = js_is_regexp(ctx, regexp); if (ret < 0) return -1; @@ -40908,7 +40897,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, } if (JS_IsException(repl_str)) goto exception; - + string_buffer_concat(b, sp, endOfLastMatch, pos); string_buffer_concat_value_free(b, repl_str); endOfLastMatch = pos + searchp->len; @@ -41586,7 +41575,7 @@ static JSValue js_string_CreateHTML(JSContext *ctx, JSValueConst this_val, static struct { const char *tag, *attr; } const defs[] = { { "a", "name" }, { "big", NULL }, { "blink", NULL }, { "b", NULL }, { "tt", NULL }, { "font", "color" }, { "font", "size" }, { "i", NULL }, - { "a", "href" }, { "small", NULL }, { "strike", NULL }, + { "a", "href" }, { "small", NULL }, { "strike", NULL }, { "sub", NULL }, { "sup", NULL }, }; @@ -42386,7 +42375,7 @@ static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val) if (p->len == 0) { empty_regex: return JS_NewString(ctx, "(?:)"); - } + } string_buffer_init2(ctx, b, p->len, p->is_wide_char); /* Escape '/' and newline sequences as needed */ @@ -42445,7 +42434,7 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas else return JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP); } - + flags = lre_get_flags(re->bytecode->u.str8); return JS_NewBool(ctx, (flags & mask) != 0); } @@ -42972,7 +42961,7 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, JSString *strp; int64_t lastIndex; JSRegExpStringIteratorData *it; - + if (!JS_IsObject(R)) return JS_ThrowTypeErrorNotAnObject(ctx); @@ -42980,7 +42969,7 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, flags = JS_UNDEFINED; matcher = JS_UNDEFINED; iter = JS_UNDEFINED; - + S = JS_ToString(ctx, argv[0]); if (JS_IsException(S)) goto exception; @@ -43001,7 +42990,7 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex, JS_NewInt64(ctx, lastIndex)) < 0) goto exception; - + iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR); if (JS_IsException(iter)) goto exception; @@ -43139,7 +43128,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, str = JS_ToString(ctx, argv[0]); if (JS_IsException(str)) goto exception; - + sp = JS_VALUE_GET_STRING(str); rp = NULL; functionalReplace = JS_IsFunction(ctx, rep); @@ -43418,7 +43407,7 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, while (q < size) { if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, JS_NewInt32(ctx, q)) < 0) goto exception; - JS_FreeValue(ctx, z); + JS_FreeValue(ctx, z); z = JS_RegExpExec(ctx, splitter, str); if (JS_IsException(z)) goto exception; @@ -43473,7 +43462,7 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, ctor); JS_FreeValue(ctx, splitter); JS_FreeValue(ctx, flags); - JS_FreeValue(ctx, z); + JS_FreeValue(ctx, z); return A; } @@ -43558,7 +43547,7 @@ static JSValue json_parse_value(JSParseState *s) { JSValue prop_val; JSAtom prop_name; - + if (json_next_token(s)) goto fail; val = JS_NewObject(ctx); @@ -43701,7 +43690,7 @@ JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char *filename) { - return JS_ParseJSON2(ctx, buf, buf_len, filename, 0); + return JS_ParseJSON2(ctx, buf, buf_len, filename, 0); } static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, @@ -43894,7 +43883,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, int64_t i, len; int cl, ret; BOOL has_content; - + indent1 = JS_UNDEFINED; sep = JS_UNDEFINED; sep1 = JS_UNDEFINED; @@ -44069,7 +44058,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, JS_FreeValue(ctx, val); return 0; } - + exception: JS_FreeValue(ctx, val); JS_FreeValue(ctx, tab); @@ -44187,7 +44176,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, JS_DupValue(ctx, obj), JS_PROP_C_W_E) < 0) goto exception; val = JS_DupValue(ctx, obj); - + val = js_json_check(ctx, jsc, wrapper, val, jsc->empty); if (JS_IsException(val)) goto exception; @@ -44443,7 +44432,7 @@ static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod, JS_ThrowStackOverflow(ctx); return NULL; } - + /* 's' should never be NULL */ if (s->is_revoked) { JS_ThrowTypeErrorRevokedProxy(ctx); @@ -44842,7 +44831,7 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc JS_FreeValue(ctx, trap_result_obj); if (res < 0) return -1; - + if (target_desc_ret) { /* convert result_desc.flags to defineProperty flags */ flags1 = result_desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE; @@ -45207,7 +45196,7 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, if (flags & JS_CALL_FLAG_CONSTRUCTOR) return js_proxy_call_constructor(ctx, func_obj, this_obj, argc, argv); - + s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_apply); if (!s) return JS_EXCEPTION; @@ -45792,7 +45781,7 @@ static void reset_weak_ref(JSRuntime *rt, JSObject *p) { JSMapRecord *mr, *mr_next; JSMapState *s; - + /* first pass to remove the records from the WeakMap/WeakSet lists */ for(mr = p->first_weak_ref; mr != NULL; mr = mr->next_weak_ref) { @@ -45802,7 +45791,7 @@ static void reset_weak_ref(JSRuntime *rt, JSObject *p) list_del(&mr->hash_link); list_del(&mr->link); } - + /* second pass to free the values to avoid modifying the weak reference list while traversing it. */ for(mr = p->first_weak_ref; mr != NULL; mr = mr_next) { @@ -46801,7 +46790,7 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, JSValueConst resolve_element_env = func_data[4]; JSValue ret, obj; int is_zero, index; - + if (JS_ToInt32(ctx, &index, func_data[1])) return JS_EXCEPTION; if (alreadyCalled) @@ -46810,7 +46799,7 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, if (resolve_type == PROMISE_MAGIC_allSettled) { JSValue str; - + obj = JS_NewObject(ctx); if (JS_IsException(obj)) return JS_EXCEPTION; @@ -46835,7 +46824,7 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, if (JS_DefinePropertyValueUint32(ctx, values, index, obj, JS_PROP_C_W_E) < 0) return JS_EXCEPTION; - + is_zero = remainingElementsCount_add(ctx, resolve_element_env, -1); if (is_zero < 0) return JS_EXCEPTION; @@ -46868,7 +46857,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, JSValueConst then_args[2], resolve_element_data[5]; BOOL done; int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any); - + if (!JS_IsObject(this_val)) return JS_ThrowTypeErrorNotAnObject(ctx); result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); @@ -46904,7 +46893,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, JS_NewInt32(ctx, 1), JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) goto fail_reject; - + index = 0; for(;;) { /* XXX: conformance: should close the iterator if error on 'done' @@ -46914,7 +46903,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, goto fail_reject; if (done) break; - next_promise = JS_Call(ctx, promise_resolve, + next_promise = JS_Call(ctx, promise_resolve, this_val, 1, (JSValueConst *)&item); JS_FreeValue(ctx, item); if (JS_IsException(next_promise)) { @@ -46934,7 +46923,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, next_promise); goto fail_reject1; } - + if (magic == PROMISE_MAGIC_allSettled) { reject_element = JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1, @@ -48014,7 +48003,7 @@ static double set_date_fields(double fields[], int is_local) { int64_t y; double days, d, h, m1; int i, m, md; - + m1 = fields[1]; m = fmod(m1, 12); if (m < 0) @@ -48029,7 +48018,7 @@ static double set_date_fields(double fields[], int is_local) { days += md; } days += fields[2] - 1; - h = fields[3] * 3600000 + fields[4] * 60000 + + h = fields[3] * 3600000 + fields[4] * 60000 + fields[5] * 1000 + fields[6]; d = days * 86400000 + h; if (is_local) @@ -48328,7 +48317,7 @@ static void string_skip_non_spaces(JSString *sp, int *pp) { static int string_get_digits(JSString *sp, int *pp, int64_t *pval) { int64_t v = 0; int c, p = *pp, p_start; - + if (p >= sp->len) return -1; p_start = p; @@ -48350,14 +48339,14 @@ static int string_get_digits(JSString *sp, int *pp, int64_t *pval) { static int string_get_signed_digits(JSString *sp, int *pp, int64_t *pval) { int res, sgn, p = *pp; - + if (p >= sp->len) return -1; sgn = string_get(sp, p); if (sgn == '-' || sgn == '+') p++; - + res = string_get_digits(sp, &p, pval); if (res == 0 && sgn == '-') *pval = -*pval; @@ -48451,13 +48440,13 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, int p, i, c, sgn, l; JSString *sp; BOOL is_local; - + rv = JS_NAN; s = JS_ToString(ctx, argv[0]); if (JS_IsException(s)) return JS_EXCEPTION; - + sp = JS_VALUE_GET_STRING(s); p = 0; if (p < sp->len && (((c = string_get(sp, p)) >= '0' && c <= '9') || c == '+' || c == '-')) { @@ -48821,7 +48810,7 @@ static void js_operator_set_finalizer(JSRuntime *rt, JSValue val) JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET); int i, j; JSBinaryOperatorDefEntry *ent; - + if (opset) { for(i = 0; i < JS_OVOP_COUNT; i++) { if (opset->self_ops[i]) @@ -48853,7 +48842,7 @@ static void js_operator_set_mark(JSRuntime *rt, JSValueConst val, JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET); int i, j; JSBinaryOperatorDefEntry *ent; - + if (opset) { for(i = 0; i < JS_OVOP_COUNT; i++) { if (opset->self_ops[i]) @@ -48953,7 +48942,7 @@ static JSValue js_operators_create_internal(JSContext *ctx, } op_count = opset1->operator_counter; JS_FreeValue(ctx, prop); - + /* we assume there are few entries */ new_tab = js_realloc(ctx, def->tab, (def->count + 1) * sizeof(def->tab[0])); @@ -48964,7 +48953,7 @@ static JSValue js_operators_create_internal(JSContext *ctx, ent = def->tab + def->count - 1; memset(ent, 0, sizeof(def->tab[0])); ent->operator_index = op_count; - + for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) { prop = JS_GetPropertyStr(ctx, arg, js_overloadable_operator_names[i]); @@ -49001,7 +48990,7 @@ static JSValue js_operators_updateBigIntOperators(JSContext *ctx, JSValueConst t const JSOverloadableOperatorEnum ops[2] = { JS_OVOP_DIV, JS_OVOP_POW }; JSOverloadableOperatorEnum op; int i; - + opset_obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_BIG_INT], JS_ATOM_Symbol_operatorSet); if (JS_IsException(opset_obj)) @@ -49131,7 +49120,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val) case JS_TAG_BIG_FLOAT: { bf_t *a, a_s; - + a = JS_ToBigFloat(ctx, &a_s, val); if (!bf_is_finite(a)) { JS_FreeValue(ctx, val); @@ -49246,7 +49235,7 @@ static JSValue js_bigint_div(JSContext *ctx, bf_t a_s, b_s, *a, *b, *r, *q; int status; JSValue q_val, r_val; - + q_val = JS_NewBigInt(ctx); if (JS_IsException(q_val)) return JS_EXCEPTION; @@ -49297,7 +49286,7 @@ static JSValue js_bigint_sqrt(JSContext *ctx, bf_t a_s, *a, *r, *rem; int status; JSValue r_val, rem_val; - + r_val = JS_NewBigInt(ctx); if (JS_IsException(r_val)) return JS_EXCEPTION; @@ -49375,7 +49364,7 @@ static JSValue js_bigint_asUintN(JSContext *ctx, uint64_t bits; bf_t a_s, *a = &a_s, *r, mask_s, *mask = &mask_s; JSValue res; - + if (JS_ToIndex(ctx, &bits, argv[0])) return JS_EXCEPTION; res = JS_NewBigInt(ctx); @@ -49442,7 +49431,7 @@ void JS_AddIntrinsicBigInt(JSContext *ctx) rt->bigint_ops.unary_arith = js_unary_arith_bigint; rt->bigint_ops.binary_arith = js_binary_arith_bigint; rt->bigint_ops.compare = js_compare_bigfloat; - + ctx->class_proto[JS_CLASS_BIG_INT] = JS_NewObject(ctx); JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT], js_bigint_proto_funcs, @@ -49867,7 +49856,7 @@ static JSValue js_bigfloat_isFinite(JSContext *ctx, JSValueConst this_val, { JSValueConst val = argv[0]; JSBigFloat *p; - + if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT) return JS_FALSE; p = JS_VALUE_GET_PTR(val); @@ -49879,7 +49868,7 @@ static JSValue js_bigfloat_isNaN(JSContext *ctx, JSValueConst this_val, { JSValueConst val = argv[0]; JSBigFloat *p; - + if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT) return JS_FALSE; p = JS_VALUE_GET_PTR(val); @@ -50333,7 +50322,7 @@ void JS_AddIntrinsicBigFloat(JSContext *ctx) { JSRuntime *rt = ctx->rt; JSValueConst obj1; - + rt->bigfloat_ops.to_string = js_bigfloat_to_string; rt->bigfloat_ops.from_string = js_string_to_bigfloat; rt->bigfloat_ops.unary_arith = js_unary_arith_bigfloat; @@ -50341,7 +50330,7 @@ void JS_AddIntrinsicBigFloat(JSContext *ctx) rt->bigfloat_ops.compare = js_compare_bigfloat; rt->bigfloat_ops.mul_pow10_to_float64 = js_mul_pow10_to_float64; rt->bigfloat_ops.mul_pow10 = js_mul_pow10; - + ctx->class_proto[JS_CLASS_BIG_FLOAT] = JS_NewObject(ctx); JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT], js_bigfloat_proto_funcs, @@ -50517,7 +50506,7 @@ static int js_bigdecimal_get_rnd_mode(JSContext *ctx, JSValueConst obj) const char *str; size_t size; int rnd_mode; - + str = JS_ToCStringLen(ctx, &size, obj); if (!str) return -1; @@ -50557,7 +50546,7 @@ static int js_bigdecimal_get_env(JSContext *ctx, BigDecimalEnv *fe, int64_t val; BOOL has_prec; int rnd_mode; - + if (!JS_IsObject(obj)) { JS_ThrowTypeErrorNotAnObject(ctx); return -1; @@ -50570,7 +50559,7 @@ static int js_bigdecimal_get_env(JSContext *ctx, BigDecimalEnv *fe, if (rnd_mode < 0) return -1; fe->flags = rnd_mode; - + prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumSignificantDigits); if (JS_IsException(prop)) return -1; @@ -50625,7 +50614,7 @@ static JSValue js_bigdecimal_fop(JSContext *ctx, JSValueConst this_val, op_count = 1; else op_count = 2; - + op1 = JS_ToNumeric(ctx, argv[0]); if (JS_IsException(op1)) return op1; @@ -51582,7 +51571,7 @@ JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, } return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); } - + static JSValue js_typed_array_get_toStringTag(JSContext *ctx, JSValueConst this_val) { @@ -52002,7 +51991,7 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, if (typed_array_is_detached(ctx, p)) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - + shift = typed_array_size_log2(p->class_id); switch(shift) { case 0: @@ -52143,7 +52132,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, res = 0; goto done; } - + is_bigint = 0; is_int = 0; /* avoid warning */ v64 = 0; /* avoid warning */ @@ -52161,7 +52150,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, #ifdef CONFIG_BIGNUM if (tag == JS_TAG_BIG_INT) { JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]); - + if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) { if (bf_get_int64(&v64, &p1->num, 0) != 0) goto done; @@ -52794,7 +52783,7 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, uint32_t *array_idx; void *array_tmp; size_t i, j; - + /* XXX: a stable sort would use less memory */ array_idx = js_malloc(ctx, len * sizeof(array_idx[0])); if (!array_idx) @@ -53608,7 +53597,7 @@ static JSValue js_atomics_op(JSContext *ctx, } switch(op | (size_log2 << 3)) { - + #ifdef CONFIG_BIGNUM #define OP(op_name, func_name) \ case ATOMICS_OP_ ## op_name | (0 << 3): \ @@ -53657,7 +53646,7 @@ static JSValue js_atomics_op(JSContext *ctx, a = atomic_load((_Atomic(uint64_t) *)ptr); break; #endif - + case ATOMICS_OP_COMPARE_EXCHANGE | (0 << 3): { uint8_t v1 = v; @@ -53832,7 +53821,7 @@ static JSValue js_atomics_wait(JSContext *ctx, return JS_EXCEPTION; } else #endif - { + { if (JS_ToInt32(ctx, &v32, argv[2])) return JS_EXCEPTION; v = v32; diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h index d0e3692..71990c2 100644 --- a/quickjs/quickjs.h +++ b/quickjs/quickjs.h @@ -28,7 +28,6 @@ #include #include #include -#include "my_stdint.h" #ifdef __cplusplus extern "C" { @@ -140,7 +139,7 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) { return 0; } - + #elif defined(JS_NAN_BOXING) typedef uint64_t JSValue; @@ -205,7 +204,7 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) tag = JS_VALUE_GET_TAG(v); return tag == (JS_NAN >> 32); } - + #else /* !JS_NAN_BOXING */ typedef union JSValueUnion { @@ -970,7 +969,7 @@ static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *fun { return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic); } -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, +void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, JSValueConst proto); /* C property definition */ diff --git a/quickjs/std_module.c b/quickjs/std_module.c index 6f85455..72ff934 100644 --- a/quickjs/std_module.c +++ b/quickjs/std_module.c @@ -1,5 +1,4 @@ #include -#include "my_stdlib.h" #include #include #include @@ -9,7 +8,6 @@ #include "cutils.h" #include "std_module.h" #include "ckb_syscall_apis.h" -#include "my_string.h" #include "ckb_cell_fs.h" /* console.log */ diff --git a/tests/basic/test_builtin.js b/tests/basic/test_builtin.js index f506538..5f6d51c 100644 --- a/tests/basic/test_builtin.js +++ b/tests/basic/test_builtin.js @@ -57,7 +57,7 @@ function test_function() } var r, g; - + r = my_func.call(null, 1, 2); assert(r, 3, "call"); @@ -70,10 +70,10 @@ function test_function() assert_throws(TypeError, (function() { Reflect.apply((function () { return 1; }), null, undefined); })); - + r = new Function("a", "b", "return a + b;"); assert(r(2,3), 5, "function"); - + g = f.bind(1, 2); assert(g.length, 1); assert(g.name, "bound f"); @@ -103,7 +103,7 @@ function test() assert(a.z, 4, "get"); a.z = 5; assert(a.z_val, 5, "set"); - + a = { get z() { return 4; }, set z(val) { this.z_val = val; } }; assert(a.z, 4, "get"); a.z = 5; @@ -207,7 +207,7 @@ function test_string() assert(a.charAt(1), "b"); assert(a.charAt(-1), ""); assert(a.charAt(3), ""); - + a = "abcd"; assert(a.substring(1, 3), "bc", "substring"); a = String.fromCharCode(0x20ac); @@ -216,7 +216,7 @@ function test_string() assert(a, "\u20ac", "unicode"); assert(a, "\u{20ac}", "unicode"); assert("a", "\x61", "unicode"); - + a = "\u{10ffff}"; assert(a.length, 2, "unicode"); assert(a, "\u{dbff}\u{dfff}", "unicode"); @@ -380,7 +380,7 @@ function test_eval() assert(eval("if (0) 2; else 3;"), 3); assert(f.call(1, "this"), 1); - + a = 2; assert(eval("a"), 2); @@ -425,7 +425,7 @@ function test_typed_array() a[2] = 0.5; a[3] = 1233.5; assert(a.toString(), "0,2,0,255"); - + buffer = new ArrayBuffer(16); assert(buffer.byteLength, 16); a = new Uint32Array(buffer, 12, 1); @@ -437,7 +437,7 @@ function test_typed_array() a = new Float32Array(buffer, 8, 1); a[0] = 1; - + a = new Uint8Array(buffer); str = a.toString(); @@ -526,7 +526,7 @@ function test_regexp() a = /(\.(?!com|org)|\/)/.exec("ah.com"); assert(a, null); - + a = /(?=(a+))/.exec("baaabac"); assert(a.index === 1 && a[0] === "" && a[1] === "aaa"); @@ -593,7 +593,7 @@ function test_map() } i = 0; - a.forEach(function (v, o) { + a.forEach(function (v, o) { assert(o, tab[i++][0]); assert(a.has(o)); assert(a.delete(o)); @@ -616,7 +616,7 @@ function test_weak_map() a.set(o, v); } o = null; - + n2 = n >> 1; for(i = 0; i < n2; i++) { a.delete(tab[i][0]); diff --git a/tests/basic/test_float.js b/tests/basic/test_float.js index f777422..e6adc23 100644 --- a/tests/basic/test_float.js +++ b/tests/basic/test_float.js @@ -20,7 +20,7 @@ function assert(actual, expected, message) { function test_to_string() { assert(1.1.toString(), "1.1") assert((-1.1).toString(), "-1.1") - assert(3.14159265354.toString(), "3.1415926540000000") + assert(3.14159265354.toString(), "3.14159265354") } test_to_string() diff --git a/tests/benchmark/Makefile b/tests/benchmark/Makefile index 909cb3a..dfcaf80 100644 --- a/tests/benchmark/Makefile +++ b/tests/benchmark/Makefile @@ -1,4 +1,3 @@ - CKB-DEBUGGER := ckb-debugger ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) BIN_PATH := $(ROOT_DIR)/../../build/ckb-js-vm @@ -15,7 +14,7 @@ define debug endef define compile-run - $(CKB-DEBUGGER) --read-file $(ROOT_DIR)/$(1) --bin $(BIN_PATH) -- -c | awk '/Run result: 0/{exit} {print}' | xxd -r -p > $(ROOT_DIR)/../../build/$(1).bc + $(CKB-DEBUGGER) --read-file $(ROOT_DIR)/$(1) --bin $(BIN_PATH) -- -c | awk -f $(ROOT_DIR)/../../tools/compile.awk | xxd -r -p > $(ROOT_DIR)/../../build/$(1).bc $(CKB-DEBUGGER) --read-file $(ROOT_DIR)/../../build/$(1).bc --bin $(BIN_PATH) -- -r | tee $(ROOT_DIR)/benchmark.txt endef diff --git a/tests/benchmark/benchmark.txt b/tests/benchmark/benchmark.txt index f58ae1e..76c89b7 100644 --- a/tests/benchmark/benchmark.txt +++ b/tests/benchmark/benchmark.txt @@ -1,43 +1,42 @@ -Run from file, local access enabled. For Testing only. -Benchmark started. Every test may iterate 1 internally ... -empty_loop: 3 K cycles -prop_read: 11 K cycles -prop_write: 10 K cycles -prop_create: 10 K cycles -prop_delete: 7 K cycles -array_read: 17 K cycles -array_write: 16 K cycles -array_prop_create: 937 K cycles -array_length_decr: 1278 K cycles -array_hole_length_decr: 3142 K cycles -array_push: 1181 K cycles -array_pop: 1366 K cycles -typed_array_read: 20 K cycles -typed_array_write: 20 K cycles -global_read: 3 K cycles -global_write: 4 K cycles -global_write_strict: 3 K cycles -local_destruct: 93 K cycles -global_destruct: 37 K cycles -global_destruct_strict: 64 K cycles -func_call: 12 K cycles -int_arith: 994 K cycles -set_collection_add: 893 K cycles -array_for: 133 K cycles -array_for_in: 351 K cycles -array_for_of: 174 K cycles -math_min: 1222 K cycles -string_build1: 188 K cycles -string_build2: 191 K cycles -string_build3: 189 K cycles -string_build4: 194 K cycles -int_to_string: 10 K cycles -float_to_string: 21 K cycles -string_to_int: 5 K cycles -string_to_float: 8 K cycles -sort_bench(5000 numbers): 23806 K cycles -json_parse_bench: 123 K cycles -json_stringify_bench: 198 K cycles +Script log: Run from file, local access enabled. For Testing only. +Script log: Benchmark started. Every test may iterate 1 internally ... +Script log: empty_loop: 3 K cycles +Script log: prop_read: 11 K cycles +Script log: prop_write: 10 K cycles +Script log: prop_create: 10 K cycles +Script log: prop_delete: 7 K cycles +Script log: array_read: 17 K cycles +Script log: array_write: 16 K cycles +Script log: array_prop_create: 924 K cycles +Script log: array_length_decr: 1275 K cycles +Script log: array_hole_length_decr: 3189 K cycles +Script log: array_push: 1183 K cycles +Script log: array_pop: 1232 K cycles +Script log: typed_array_read: 20 K cycles +Script log: typed_array_write: 20 K cycles +Script log: global_read: 3 K cycles +Script log: global_write: 4 K cycles +Script log: global_write_strict: 3 K cycles +Script log: local_destruct: 91 K cycles +Script log: global_destruct: 37 K cycles +Script log: global_destruct_strict: 63 K cycles +Script log: func_call: 12 K cycles +Script log: int_arith: 1018 K cycles +Script log: set_collection_add: 885 K cycles +Script log: array_for: 132 K cycles +Script log: array_for_in: 349 K cycles +Script log: array_for_of: 175 K cycles +Script log: math_min: 1214 K cycles +Script log: string_build1: 182 K cycles +Script log: string_build2: 185 K cycles +Script log: string_build3: 183 K cycles +Script log: string_build4: 189 K cycles +Script log: int_to_string: 10 K cycles +Script log: float_to_string: 21 K cycles +Script log: string_to_int: 5 K cycles +Script log: string_to_float: 8 K cycles +Script log: sort_bench(5000 numbers): 23628 K cycles +Script log: json_parse_bench: 121 K cycles +Script log: json_stringify_bench: 194 K cycles Run result: 0 -Total cycles consumed: 53546530(51.1M) -Transfer cycles: 123824(120.9K), running cycles: 53422706(50.9M) +Total cycles consumed: 53532515(51.1M) diff --git a/tests/ckb_js_tests/Makefile b/tests/ckb_js_tests/Makefile index 3a498d8..1d5f4f9 100644 --- a/tests/ckb_js_tests/Makefile +++ b/tests/ckb_js_tests/Makefile @@ -15,7 +15,7 @@ cargo_test: cargo test spawn_caller: - clang-16 --target=riscv64 -march=rv64imc_zba_zbb_zbc_zbs \ + clang-18 --target=riscv64 -march=rv64imc_zba_zbb_zbc_zbs \ -I ../../deps/ckb-c-stdlib/libc -I ../../deps/ckb-c-stdlib \ -nostdinc -nostdlib -o ../../build/spawn_caller test_data/spawn_caller.c @@ -27,8 +27,8 @@ build/testdata_fs_modules.bin: test_data/fs_module/main.js test_data/fs_module/f fs_bytecode: mkdir -p ../../build/bytecode - $(CKB_DEBUGGER) --read-file test_data/fs_module/main.js --bin $(BIN_PATH) -- -c | awk '/Run result: 0/{exit} {print}' | xxd -r -p > ../../build/bytecode/main.bc - $(CKB_DEBUGGER) --read-file test_data/fs_module/fib_module.js --bin $(BIN_PATH) -- -c | awk '/Run result: 0/{exit} {print}' | xxd -r -p > ../../build/bytecode/fib_module.bc + $(CKB_DEBUGGER) --read-file test_data/fs_module/main.js --bin $(BIN_PATH) -- -c | awk -f $(ROOT_DIR)/../../tools/compile.awk | xxd -r -p > ../../build/bytecode/main.bc + $(CKB_DEBUGGER) --read-file test_data/fs_module/fib_module.js --bin $(BIN_PATH) -- -c | awk -f $(ROOT_DIR)/../../tools/compile.awk | xxd -r -p > ../../build/bytecode/fib_module.bc cd ../../build/bytecode && lua ../../tools/fs.lua pack ../../build/testdata_fs_modules_bc.bin main.bc fib_module.bc $(CKB_DEBUGGER) --max-cycles $(MAX_CYCLES) --read-file ../../build/testdata_fs_modules_bc.bin --bin $(BIN_PATH) -- -f -r 2>&1 | fgrep 'Run result: 0' diff --git a/tests/ckb_js_tests/test_data/syscall.js b/tests/ckb_js_tests/test_data/syscall.js index a805047..85343f8 100644 --- a/tests/ckb_js_tests/test_data/syscall.js +++ b/tests/ckb_js_tests/test_data/syscall.js @@ -109,28 +109,6 @@ function test_misc() { console.log('test_misc done'); } -function test_spawn() { - console.log('test_spawn ...'); - const js_code = ` - let c = new Uint8Array([0,1,2,3,4,5,6,7]); - ckb.set_content(c); - ckb.exit(0); - `; - let code_hash = new Uint8Array([ - 0xdf, 0x97, 0x77, 0x78, 0x08, 0x9b, 0xf3, 0x3f, 0xc5, 0x1f, 0x22, 0x45, 0xfa, 0x6d, 0xb7, 0xfa, - 0x18, 0x19, 0xd5, 0x03, 0x11, 0x31, 0xa8, 0x3d, 0x4e, 0xcb, 0xcb, 0x6c, 0xba, 0x07, 0xce, 0x91 - ]); - let spawn_args = {content_length: 8}; - let ret = ckb.spawn_cell(code_hash, ckb.SCRIPT_HASH_TYPE_TYPE, spawn_args, '-e', js_code); - console.assert(ret.exit_code == 0, 'exit_code != 0'); - console.assert(ret.content.byteLength == 8, 'content.byteLength != 8'); - let content = new Uint8Array(ret.content); - for (let i = 0; i < 8; i++) { - console.assert(content[i] == i, `content is incorrect at index ${i}`); - } - console.log('test_spawn done'); -} - test_misc(); test_partial_loading(ckb.load_witness); test_partial_loading(ckb.load_cell_data); @@ -141,6 +119,5 @@ test_partial_loading_without_comparing(ckb.load_script); test_partial_loading_without_comparing(ckb.load_cell); test_partial_loading_field_without_comparing(ckb.load_cell_by_field, ckb.CELL_FIELD_CAPACITY); test_partial_loading_field_without_comparing(ckb.load_input_by_field, ckb.INPUT_FIELD_OUT_POINT); -test_spawn(); ckb.exit(0); diff --git a/tests/examples/Makefile b/tests/examples/Makefile index 806f777..3a9e34b 100644 --- a/tests/examples/Makefile +++ b/tests/examples/Makefile @@ -1,4 +1,3 @@ - CKB-DEBUGGER := ckb-debugger ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) BIN_PATH := $(ROOT_DIR)/../../build/ckb-js-vm @@ -15,7 +14,7 @@ define debug endef define compile-run - $(CKB-DEBUGGER) --read-file $(ROOT_DIR)/$(1) --bin $(BIN_PATH) -- -c | awk '/Run result: 0/{exit} {print}' | xxd -r -p > $(ROOT_DIR)/../../build/$(1).bc + $(CKB-DEBUGGER) --read-file $(ROOT_DIR)/$(1) --bin $(BIN_PATH) -- -c | awk -f $(ROOT_DIR)/../../tools/compile.awk | xxd -r -p > $(ROOT_DIR)/../../build/$(1).bc $(CKB-DEBUGGER) --read-file $(ROOT_DIR)/../../build/$(1).bc --bin $(BIN_PATH) -- -r | fgrep 'Run result: 0' endef @@ -24,4 +23,4 @@ all: $(call run,fib.js) $(call debug,pi_bigint.js) $(call compile-run,fib.js) - $(call compile-run,pi_bigint.js) \ No newline at end of file + $(call compile-run,pi_bigint.js) diff --git a/tools/compile.awk b/tools/compile.awk new file mode 100644 index 0000000..bacc338 --- /dev/null +++ b/tools/compile.awk @@ -0,0 +1,14 @@ +#!/usr/bin/awk -f + +{ + # Check if the line starts with "Script log: " + if ($0 ~ /^Script log: /) { + # Remove "Script log: " from the line + line_data = gensub(/^Script log: /, "", "g") + + # If the remaining line is not empty, print it + if (line_data != "") { + print line_data + } + } +}