@port-labs/jq-node-bindings 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +3 -3
- package/configure +8 -6
- package/deps/jq/.travis.yml +184 -35
- package/deps/jq/AUTHORS +31 -30
- package/deps/jq/COPYING +2 -2
- package/deps/jq/KEYS +8 -0
- package/deps/jq/Makefile.am +85 -70
- package/deps/jq/NEWS +5 -4
- package/deps/jq/README.md +18 -9
- package/deps/jq/appveyor.yml +53 -0
- package/deps/jq/compile-ios.sh +5 -5
- package/deps/jq/config/m4/check-math-func.m4 +7 -2
- package/deps/jq/configure.ac +130 -68
- package/deps/jq/docs/Rakefile +14 -135
- package/deps/jq/docs/Rakefile.manual +49 -0
- package/deps/jq/docs/Rakefile.website +76 -0
- package/deps/jq/docs/content/2.download/default.yml +115 -39
- package/deps/jq/docs/content/3.manual/manual.yml +641 -231
- package/deps/jq/docs/content/3.manual/v1.3/manual.yml +130 -130
- package/deps/jq/docs/content/3.manual/v1.4/manual.yml +160 -160
- package/deps/jq/docs/content/3.manual/v1.5/manual.yml +2878 -0
- package/deps/jq/docs/content/3.manual/v1.6/manual.yml +3287 -0
- package/deps/jq/docs/content/index/index.yml +28 -6
- package/deps/jq/docs/public/.htaccess +2 -2
- package/deps/jq/docs/public/css/base.scss +141 -59
- package/deps/jq/docs/public/js/manual-search.js +52 -0
- package/deps/jq/docs/site.yml +1 -10
- package/deps/jq/docs/templates/default.liquid +10 -10
- package/deps/jq/docs/templates/index.liquid +45 -32
- package/deps/jq/docs/templates/manual.liquid +67 -90
- package/deps/jq/docs/templates/shared/_footer.liquid +10 -5
- package/deps/jq/docs/templates/shared/_head.liquid +17 -12
- package/deps/jq/docs/templates/shared/_navbar.liquid +27 -0
- package/deps/jq/jq.1.prebuilt +523 -139
- package/deps/jq/modules/oniguruma/AUTHORS +1 -0
- package/deps/jq/modules/oniguruma/CMakeLists.txt +86 -0
- package/deps/jq/modules/oniguruma/COPYING +28 -0
- package/deps/jq/modules/oniguruma/ChangeLog +0 -0
- package/deps/jq/modules/oniguruma/HISTORY +2138 -0
- package/deps/jq/modules/oniguruma/Makefile.am +33 -0
- package/deps/jq/modules/oniguruma/NEWS +0 -0
- package/deps/jq/modules/oniguruma/README +189 -0
- package/deps/jq/modules/oniguruma/README.ja +195 -0
- package/deps/jq/modules/oniguruma/README.md +203 -0
- package/deps/jq/modules/oniguruma/cmake/dist.cmake +321 -0
- package/deps/jq/modules/oniguruma/compile +348 -0
- package/deps/jq/modules/oniguruma/config.guess +1754 -0
- package/deps/jq/modules/oniguruma/config.sub +1890 -0
- package/deps/jq/modules/oniguruma/configure.ac +87 -0
- package/deps/jq/modules/oniguruma/contributed/libfuzzer-onig.cpp +31 -0
- package/deps/jq/modules/oniguruma/depcomp +791 -0
- package/deps/jq/modules/oniguruma/dist.info +10 -0
- package/deps/jq/modules/oniguruma/doc/API +660 -0
- package/deps/jq/modules/oniguruma/doc/API.ja +667 -0
- package/deps/jq/modules/oniguruma/doc/FAQ +12 -0
- package/deps/jq/modules/oniguruma/doc/FAQ.ja +22 -0
- package/deps/jq/modules/oniguruma/doc/RE +436 -0
- package/deps/jq/modules/oniguruma/doc/RE.ja +448 -0
- package/deps/jq/modules/oniguruma/doc/UNICODE_PROPERTIES +698 -0
- package/deps/jq/modules/oniguruma/index.html +181 -0
- package/deps/jq/modules/oniguruma/index_ja.html +184 -0
- package/deps/jq/modules/oniguruma/install-sh +541 -0
- package/deps/jq/modules/oniguruma/m4/.whatever +0 -0
- package/deps/jq/modules/oniguruma/make_win32.bat +3 -0
- package/deps/jq/modules/oniguruma/make_win64.bat +3 -0
- package/deps/jq/modules/oniguruma/missing +215 -0
- package/deps/jq/modules/oniguruma/onig-config.in +78 -0
- package/deps/jq/modules/oniguruma/oniguruma.pc.cmake.in +13 -0
- package/deps/jq/modules/oniguruma/oniguruma.pc.in +14 -0
- package/deps/jq/modules/oniguruma/sample/CMakeLists.txt +28 -0
- package/deps/jq/modules/oniguruma/sample/Makefile.am +34 -0
- package/deps/jq/modules/oniguruma/sample/bug_fix.c +131 -0
- package/deps/jq/modules/oniguruma/sample/crnl.c +127 -0
- package/deps/jq/modules/oniguruma/sample/encode.c +308 -0
- package/deps/jq/modules/oniguruma/sample/listcap.c +110 -0
- package/deps/jq/modules/oniguruma/sample/names.c +75 -0
- package/deps/jq/modules/oniguruma/sample/posix.c +96 -0
- package/deps/jq/modules/oniguruma/sample/scan.c +88 -0
- package/deps/jq/modules/oniguruma/sample/simple.c +59 -0
- package/deps/jq/modules/oniguruma/sample/sql.c +76 -0
- package/deps/jq/modules/oniguruma/sample/syntax.c +76 -0
- package/deps/jq/modules/oniguruma/sample/user_property.c +87 -0
- package/deps/jq/modules/oniguruma/src/Makefile.am +58 -0
- package/deps/jq/modules/oniguruma/src/Makefile.windows +183 -0
- package/deps/jq/modules/oniguruma/src/ascii.c +61 -0
- package/deps/jq/modules/oniguruma/src/big5.c +190 -0
- package/deps/jq/modules/oniguruma/src/config.h.cmake.in +71 -0
- package/deps/jq/modules/oniguruma/src/config.h.win32 +84 -0
- package/deps/jq/modules/oniguruma/src/config.h.win64 +84 -0
- package/deps/jq/modules/oniguruma/src/cp1251.c +203 -0
- package/deps/jq/modules/oniguruma/src/euc_jp.c +310 -0
- package/deps/jq/modules/oniguruma/src/euc_jp_prop.c +158 -0
- package/deps/jq/modules/oniguruma/src/euc_jp_prop.gperf +27 -0
- package/deps/jq/modules/oniguruma/src/euc_kr.c +188 -0
- package/deps/jq/modules/oniguruma/src/euc_tw.c +171 -0
- package/deps/jq/modules/oniguruma/src/gb18030.c +538 -0
- package/deps/jq/modules/oniguruma/src/gperf_fold_key_conv.py +67 -0
- package/deps/jq/modules/oniguruma/src/gperf_unfold_key_conv.py +55 -0
- package/deps/jq/modules/oniguruma/src/iso8859_1.c +275 -0
- package/deps/jq/modules/oniguruma/src/iso8859_10.c +242 -0
- package/deps/jq/modules/oniguruma/src/iso8859_11.c +99 -0
- package/deps/jq/modules/oniguruma/src/iso8859_13.c +231 -0
- package/deps/jq/modules/oniguruma/src/iso8859_14.c +244 -0
- package/deps/jq/modules/oniguruma/src/iso8859_15.c +238 -0
- package/deps/jq/modules/oniguruma/src/iso8859_16.c +240 -0
- package/deps/jq/modules/oniguruma/src/iso8859_2.c +238 -0
- package/deps/jq/modules/oniguruma/src/iso8859_3.c +238 -0
- package/deps/jq/modules/oniguruma/src/iso8859_4.c +240 -0
- package/deps/jq/modules/oniguruma/src/iso8859_5.c +229 -0
- package/deps/jq/modules/oniguruma/src/iso8859_6.c +99 -0
- package/deps/jq/modules/oniguruma/src/iso8859_7.c +225 -0
- package/deps/jq/modules/oniguruma/src/iso8859_8.c +99 -0
- package/deps/jq/modules/oniguruma/src/iso8859_9.c +231 -0
- package/deps/jq/modules/oniguruma/src/koi8.c +253 -0
- package/deps/jq/modules/oniguruma/src/koi8_r.c +215 -0
- package/deps/jq/modules/oniguruma/src/make_unicode_fold.sh +22 -0
- package/deps/jq/modules/oniguruma/src/make_unicode_fold_data.py +306 -0
- package/deps/jq/modules/oniguruma/src/make_unicode_property.sh +18 -0
- package/deps/jq/modules/oniguruma/src/make_unicode_property_data.py +545 -0
- package/deps/jq/modules/oniguruma/src/mktable.c +1184 -0
- package/deps/jq/modules/oniguruma/src/onig_init.c +45 -0
- package/deps/jq/modules/oniguruma/src/oniggnu.h +85 -0
- package/deps/jq/modules/oniguruma/src/onigposix.h +169 -0
- package/deps/jq/modules/oniguruma/src/oniguruma.h +841 -0
- package/deps/jq/modules/oniguruma/src/regcomp.c +6300 -0
- package/deps/jq/modules/oniguruma/src/regenc.c +917 -0
- package/deps/jq/modules/oniguruma/src/regenc.h +243 -0
- package/deps/jq/modules/oniguruma/src/regerror.c +393 -0
- package/deps/jq/modules/oniguruma/src/regexec.c +3856 -0
- package/deps/jq/modules/oniguruma/src/regext.c +202 -0
- package/deps/jq/modules/oniguruma/src/reggnu.c +147 -0
- package/deps/jq/modules/oniguruma/src/regint.h +779 -0
- package/deps/jq/modules/oniguruma/src/regparse.c +5403 -0
- package/deps/jq/modules/oniguruma/src/regparse.h +351 -0
- package/deps/jq/modules/oniguruma/src/regposerr.c +105 -0
- package/deps/jq/modules/oniguruma/src/regposix.c +306 -0
- package/deps/jq/modules/oniguruma/src/regsyntax.c +315 -0
- package/deps/jq/modules/oniguruma/src/regtrav.c +76 -0
- package/deps/jq/modules/oniguruma/src/regversion.c +57 -0
- package/deps/jq/modules/oniguruma/src/sjis.c +341 -0
- package/deps/jq/modules/oniguruma/src/sjis_prop.c +158 -0
- package/deps/jq/modules/oniguruma/src/sjis_prop.gperf +27 -0
- package/deps/jq/modules/oniguruma/src/st.c +589 -0
- package/deps/jq/modules/oniguruma/src/st.h +68 -0
- package/deps/jq/modules/oniguruma/src/unicode-7.0/unicode_fold1_key.c +2250 -0
- package/deps/jq/modules/oniguruma/src/unicode-7.0/unicode_fold2_key.c +203 -0
- package/deps/jq/modules/oniguruma/src/unicode-7.0/unicode_fold3_key.c +113 -0
- package/deps/jq/modules/oniguruma/src/unicode-7.0/unicode_fold_data.c +1225 -0
- package/deps/jq/modules/oniguruma/src/unicode-7.0/unicode_property_data.c +24742 -0
- package/deps/jq/modules/oniguruma/src/unicode-7.0/unicode_property_data_posix.c +4846 -0
- package/deps/jq/modules/oniguruma/src/unicode-7.0/unicode_unfold_key.c +2571 -0
- package/deps/jq/modules/oniguruma/src/unicode.c +664 -0
- package/deps/jq/modules/oniguruma/src/unicode_fold1_key.c +2548 -0
- package/deps/jq/modules/oniguruma/src/unicode_fold2_key.c +203 -0
- package/deps/jq/modules/oniguruma/src/unicode_fold3_key.c +113 -0
- package/deps/jq/modules/oniguruma/src/unicode_fold_data.c +1366 -0
- package/deps/jq/modules/oniguruma/src/unicode_property_data.c +25306 -0
- package/deps/jq/modules/oniguruma/src/unicode_property_data_posix.c +4940 -0
- package/deps/jq/modules/oniguruma/src/unicode_unfold_key.c +2854 -0
- package/deps/jq/modules/oniguruma/src/utf16_be.c +235 -0
- package/deps/jq/modules/oniguruma/src/utf16_le.c +245 -0
- package/deps/jq/modules/oniguruma/src/utf32_be.c +194 -0
- package/deps/jq/modules/oniguruma/src/utf32_le.c +194 -0
- package/deps/jq/modules/oniguruma/src/utf8.c +335 -0
- package/deps/jq/modules/oniguruma/test/Makefile.am +28 -0
- package/deps/jq/modules/oniguruma/test/testc.c +874 -0
- package/deps/jq/modules/oniguruma/test/testu.c +916 -0
- package/deps/jq/modules/oniguruma/test-driver +153 -0
- package/deps/jq/modules/oniguruma/windows/testc.c +869 -0
- package/deps/jq/scripts/crosscompile +2 -1
- package/deps/jq/scripts/gen_utf8_tables.py +2 -3
- package/deps/jq/scripts/update-website +29 -0
- package/deps/jq/scripts/version +7 -2
- package/deps/jq/sig/jq-release.key +41 -0
- package/deps/jq/sig/v1.3/jq-linux-x86.asc +17 -0
- package/deps/jq/sig/v1.3/jq-linux-x86_64.asc +17 -0
- package/deps/jq/sig/v1.3/jq-osx-x86.asc +17 -0
- package/deps/jq/sig/v1.3/jq-osx-x86_64.asc +17 -0
- package/deps/jq/sig/v1.3/jq-win32.exe.asc +17 -0
- package/deps/jq/sig/v1.3/jq-win64.exe.asc +17 -0
- package/deps/jq/sig/v1.3/sha256sum.txt +6 -0
- package/deps/jq/sig/v1.4/jq-linux-x86.asc +17 -0
- package/deps/jq/sig/v1.4/jq-linux-x86_64.asc +17 -0
- package/deps/jq/sig/v1.4/jq-osx-x86.asc +17 -0
- package/deps/jq/sig/v1.4/jq-osx-x86_64.asc +17 -0
- package/deps/jq/sig/v1.4/jq-solaris11-32.asc +17 -0
- package/deps/jq/sig/v1.4/jq-solaris11-64.asc +17 -0
- package/deps/jq/sig/v1.4/jq-win32.exe.asc +17 -0
- package/deps/jq/sig/v1.4/jq-win64.exe.asc +17 -0
- package/deps/jq/sig/v1.4/sha256sum.txt +8 -0
- package/deps/jq/sig/v1.5/jq-linux32-no-oniguruma.asc +17 -0
- package/deps/jq/sig/v1.5/jq-linux32.asc +17 -0
- package/deps/jq/sig/v1.5/jq-linux64.asc +17 -0
- package/deps/jq/sig/v1.5/jq-osx-amd64.asc +17 -0
- package/deps/jq/sig/v1.5/jq-win32.exe.asc +17 -0
- package/deps/jq/sig/v1.5/jq-win64.exe.asc +17 -0
- package/deps/jq/sig/v1.5/sha256sum.txt +5 -0
- package/deps/jq/sig/v1.5rc1/jq-linux-x86_64-static.asc +17 -0
- package/deps/jq/sig/v1.5rc1/jq-win32.exe.asc +17 -0
- package/deps/jq/sig/v1.5rc1/jq-win64.exe.asc +17 -0
- package/deps/jq/sig/v1.5rc1/sha256sum.txt +3 -0
- package/deps/jq/sig/v1.5rc2/jq-linux-x86.asc +17 -0
- package/deps/jq/sig/v1.5rc2/jq-linux-x86_64.asc +17 -0
- package/deps/jq/sig/v1.5rc2/jq-osx-x86_64.asc +17 -0
- package/deps/jq/sig/v1.5rc2/jq-win32.exe.asc +17 -0
- package/deps/jq/sig/v1.5rc2/jq-win64.exe.asc +17 -0
- package/deps/jq/sig/v1.5rc2/sha256sum.txt +5 -0
- package/deps/jq/sig/v1.6/jq-linux32.asc +16 -0
- package/deps/jq/sig/v1.6/jq-linux64.asc +16 -0
- package/deps/jq/sig/v1.6/jq-osx-amd64.asc +16 -0
- package/deps/jq/sig/v1.6/jq-win32.exe.asc +16 -0
- package/deps/jq/sig/v1.6/jq-win64.exe.asc +16 -0
- package/deps/jq/sig/v1.6/sha256sum.txt +5 -0
- package/deps/jq/{builtin.c → src/builtin.c} +449 -344
- package/deps/jq/{builtin.h → src/builtin.h} +0 -0
- package/deps/jq/src/builtin.jq +311 -0
- package/deps/jq/{bytecode.c → src/bytecode.c} +0 -0
- package/deps/jq/{bytecode.h → src/bytecode.h} +0 -0
- package/deps/jq/{compile.c → src/compile.c} +213 -37
- package/deps/jq/{compile.h → src/compile.h} +7 -2
- package/deps/jq/{exec_stack.h → src/exec_stack.h} +0 -0
- package/deps/jq/{execute.c → src/execute.c} +127 -24
- package/deps/jq/{inject_errors.c → src/inject_errors.c} +0 -0
- package/deps/jq/{jq.h → src/jq.h} +13 -2
- package/deps/jq/{jq_parser.h → src/jq_parser.h} +0 -0
- package/deps/jq/{jq_test.c → src/jq_test.c} +1 -1
- package/deps/jq/{jv.c → src/jv.c} +24 -5
- package/deps/jq/{jv.h → src/jv.h} +46 -11
- package/deps/jq/{jv_alloc.c → src/jv_alloc.c} +0 -0
- package/deps/jq/{jv_alloc.h → src/jv_alloc.h} +0 -0
- package/deps/jq/{jv_aux.c → src/jv_aux.c} +38 -14
- package/deps/jq/{jv_dtoa.c → src/jv_dtoa.c} +4 -5
- package/deps/jq/{jv_dtoa.h → src/jv_dtoa.h} +0 -0
- package/deps/jq/src/jv_file.c +81 -0
- package/deps/jq/{jv_parse.c → src/jv_parse.c} +8 -2
- package/deps/jq/{jv_print.c → src/jv_print.c} +80 -27
- package/deps/jq/{jv_unicode.c → src/jv_unicode.c} +28 -4
- package/deps/jq/{jv_unicode.h → src/jv_unicode.h} +1 -0
- package/deps/jq/{jv_utf8_tables.h → src/jv_utf8_tables.h} +0 -0
- package/deps/jq/{lexer.c → src/lexer.c} +317 -292
- package/deps/jq/{lexer.h → src/lexer.h} +16 -12
- package/deps/jq/{lexer.l → src/lexer.l} +5 -4
- package/deps/jq/src/libm.h +291 -0
- package/deps/jq/{linker.c → src/linker.c} +5 -3
- package/deps/jq/{linker.h → src/linker.h} +0 -0
- package/deps/jq/{locfile.c → src/locfile.c} +1 -1
- package/deps/jq/{locfile.h → src/locfile.h} +0 -0
- package/deps/jq/{main.c → src/main.c} +202 -100
- package/deps/jq/{opcode_list.h → src/opcode_list.h} +4 -0
- package/deps/jq/{parser.c → src/parser.c} +1149 -1069
- package/deps/jq/{parser.h → src/parser.h} +28 -24
- package/deps/jq/{parser.y → src/parser.y} +108 -52
- package/deps/jq/{util.c → src/util.c} +12 -9
- package/deps/jq/{util.h → src/util.h} +0 -0
- package/deps/jq/tests/base64.test +35 -0
- package/deps/jq/tests/base64test +5 -0
- package/deps/jq/tests/jq-f-test.sh +4 -0
- package/deps/jq/tests/jq.test +305 -21
- package/deps/jq/tests/jqtest +1 -1
- package/deps/jq/tests/mantest +1 -1
- package/deps/jq/tests/onig.test +13 -0
- package/deps/jq/tests/onigtest +1 -1
- package/deps/jq/tests/optional.test +20 -0
- package/deps/jq/tests/optionaltest +5 -0
- package/deps/jq/tests/setup +7 -1
- package/deps/jq/tests/shtest +133 -29
- package/deps/jq/tests/utf8-truncate.jq +3 -0
- package/deps/jq/tests/utf8test +10 -0
- package/lib/index.js +7 -1
- package/package.json +3 -3
- package/test/santiy.test.js +24 -0
- package/deps/jq/docs/default_manpage.md +0 -22
- package/deps/jq/docs/public/bootstrap/css/bootstrap-responsive.css +0 -1058
- package/deps/jq/docs/public/bootstrap/css/bootstrap-responsive.min.css +0 -9
- package/deps/jq/docs/public/bootstrap/css/bootstrap.css +0 -5224
- package/deps/jq/docs/public/bootstrap/css/bootstrap.min.css +0 -9
- package/deps/jq/docs/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
- package/deps/jq/docs/public/bootstrap/img/glyphicons-halflings.png +0 -0
- package/deps/jq/docs/public/bootstrap/js/bootstrap.js +0 -2027
- package/deps/jq/docs/public/bootstrap/js/bootstrap.min.js +0 -6
- package/deps/jq/docs/templates/shared/_header.liquid +0 -26
- package/deps/jq/jq.1.default +0 -39
- package/deps/jq/jv_file.c +0 -49
- package/deps/jq/libm.h +0 -160
- package/deps/jq/setup.sh +0 -33
- package/reports/jest-port-api.xml +0 -35
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
#define _BSD_SOURCE
|
|
2
2
|
#define _GNU_SOURCE
|
|
3
|
-
#
|
|
3
|
+
#ifndef __sun__
|
|
4
|
+
# define _XOPEN_SOURCE
|
|
5
|
+
# define _XOPEN_SOURCE_EXTENDED 1
|
|
6
|
+
#else
|
|
7
|
+
# define _XPG6
|
|
8
|
+
# define __EXTENSIONS__
|
|
9
|
+
#endif
|
|
4
10
|
#include <sys/time.h>
|
|
5
11
|
#include <stdlib.h>
|
|
6
12
|
#include <stddef.h>
|
|
@@ -23,7 +29,7 @@ void *alloca (size_t);
|
|
|
23
29
|
#include <ctype.h>
|
|
24
30
|
#include <limits.h>
|
|
25
31
|
#include <math.h>
|
|
26
|
-
#ifdef
|
|
32
|
+
#ifdef HAVE_LIBONIG
|
|
27
33
|
#include <oniguruma.h>
|
|
28
34
|
#endif
|
|
29
35
|
#include <string.h>
|
|
@@ -35,6 +41,7 @@ void *alloca (size_t);
|
|
|
35
41
|
#include "linker.h"
|
|
36
42
|
#include "locfile.h"
|
|
37
43
|
#include "jv_unicode.h"
|
|
44
|
+
#include "jv_alloc.h"
|
|
38
45
|
|
|
39
46
|
|
|
40
47
|
static jv type_error(jv bad, const char* msg) {
|
|
@@ -60,6 +67,17 @@ static jv type_error2(jv bad1, jv bad2, const char* msg) {
|
|
|
60
67
|
return err;
|
|
61
68
|
}
|
|
62
69
|
|
|
70
|
+
static inline jv ret_error(jv bad, jv msg) {
|
|
71
|
+
jv_free(bad);
|
|
72
|
+
return jv_invalid_with_msg(msg);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static inline jv ret_error2(jv bad1, jv bad2, jv msg) {
|
|
76
|
+
jv_free(bad1);
|
|
77
|
+
jv_free(bad2);
|
|
78
|
+
return jv_invalid_with_msg(msg);
|
|
79
|
+
}
|
|
80
|
+
|
|
63
81
|
static jv f_plus(jq_state *jq, jv input, jv a, jv b) {
|
|
64
82
|
jv_free(input);
|
|
65
83
|
if (jv_get_kind(a) == JV_KIND_NULL) {
|
|
@@ -95,21 +113,90 @@ static jv f_ ## name(jq_state *jq, jv input) { \
|
|
|
95
113
|
|
|
96
114
|
#define LIBM_DDD(name) \
|
|
97
115
|
static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
|
|
98
|
-
if (jv_get_kind(a) != JV_KIND_NUMBER || jv_get_kind(b) != JV_KIND_NUMBER) \
|
|
99
|
-
return type_error(input, "number required"); \
|
|
100
116
|
jv_free(input); \
|
|
117
|
+
if (jv_get_kind(a) != JV_KIND_NUMBER) { \
|
|
118
|
+
jv_free(b); \
|
|
119
|
+
return type_error(a, "number required"); \
|
|
120
|
+
} \
|
|
121
|
+
if (jv_get_kind(b) != JV_KIND_NUMBER) { \
|
|
122
|
+
jv_free(a); \
|
|
123
|
+
return type_error(b, "number required"); \
|
|
124
|
+
} \
|
|
101
125
|
jv ret = jv_number(name(jv_number_value(a), jv_number_value(b))); \
|
|
102
126
|
jv_free(a); \
|
|
103
127
|
jv_free(b); \
|
|
104
128
|
return ret; \
|
|
105
129
|
}
|
|
106
130
|
#define LIBM_DDD_NO(name)
|
|
131
|
+
|
|
132
|
+
#define LIBM_DDDD(name) \
|
|
133
|
+
static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
|
|
134
|
+
jv_free(input); \
|
|
135
|
+
if (jv_get_kind(a) != JV_KIND_NUMBER) { \
|
|
136
|
+
jv_free(b); \
|
|
137
|
+
jv_free(c); \
|
|
138
|
+
return type_error(a, "number required"); \
|
|
139
|
+
} \
|
|
140
|
+
if (jv_get_kind(b) != JV_KIND_NUMBER) { \
|
|
141
|
+
jv_free(a); \
|
|
142
|
+
jv_free(c); \
|
|
143
|
+
return type_error(b, "number required"); \
|
|
144
|
+
} \
|
|
145
|
+
if (jv_get_kind(c) != JV_KIND_NUMBER) { \
|
|
146
|
+
jv_free(a); \
|
|
147
|
+
jv_free(b); \
|
|
148
|
+
return type_error(c, "number required"); \
|
|
149
|
+
} \
|
|
150
|
+
jv ret = jv_number(name(jv_number_value(a), jv_number_value(b), jv_number_value(c))); \
|
|
151
|
+
jv_free(a); \
|
|
152
|
+
jv_free(b); \
|
|
153
|
+
jv_free(c); \
|
|
154
|
+
return ret; \
|
|
155
|
+
}
|
|
156
|
+
#define LIBM_DDDD_NO(name)
|
|
107
157
|
#include "libm.h"
|
|
158
|
+
#undef LIBM_DDDD_NO
|
|
108
159
|
#undef LIBM_DDD_NO
|
|
109
160
|
#undef LIBM_DD_NO
|
|
161
|
+
#undef LIBM_DDDD
|
|
110
162
|
#undef LIBM_DDD
|
|
111
163
|
#undef LIBM_DD
|
|
112
164
|
|
|
165
|
+
#ifdef HAVE_FREXP
|
|
166
|
+
static jv f_frexp(jq_state *jq, jv input) {
|
|
167
|
+
if (jv_get_kind(input) != JV_KIND_NUMBER) {
|
|
168
|
+
return type_error(input, "number required");
|
|
169
|
+
}
|
|
170
|
+
int exp;
|
|
171
|
+
double d = frexp(jv_number_value(input), &exp);
|
|
172
|
+
jv ret = JV_ARRAY(jv_number(d), jv_number(exp));
|
|
173
|
+
jv_free(input);
|
|
174
|
+
return ret;
|
|
175
|
+
}
|
|
176
|
+
#endif
|
|
177
|
+
#ifdef HAVE_MODF
|
|
178
|
+
static jv f_modf(jq_state *jq, jv input) {
|
|
179
|
+
if (jv_get_kind(input) != JV_KIND_NUMBER) {
|
|
180
|
+
return type_error(input, "number required");
|
|
181
|
+
}
|
|
182
|
+
double i;
|
|
183
|
+
jv ret = JV_ARRAY(jv_number(modf(jv_number_value(input), &i)));
|
|
184
|
+
jv_free(input);
|
|
185
|
+
return jv_array_append(ret, jv_number(i));
|
|
186
|
+
}
|
|
187
|
+
#endif
|
|
188
|
+
#ifdef HAVE_LGAMMA_R
|
|
189
|
+
static jv f_lgamma_r(jq_state *jq, jv input) {
|
|
190
|
+
if (jv_get_kind(input) != JV_KIND_NUMBER) {
|
|
191
|
+
return type_error(input, "number required");
|
|
192
|
+
}
|
|
193
|
+
int sign;
|
|
194
|
+
jv ret = JV_ARRAY(jv_number(lgamma_r(jv_number_value(input), &sign)));
|
|
195
|
+
jv_free(input);
|
|
196
|
+
return jv_array_append(ret, jv_number(sign));
|
|
197
|
+
}
|
|
198
|
+
#endif
|
|
199
|
+
|
|
113
200
|
static jv f_negate(jq_state *jq, jv input) {
|
|
114
201
|
if (jv_get_kind(input) != JV_KIND_NUMBER) {
|
|
115
202
|
return type_error(input, "cannot be negated");
|
|
@@ -121,7 +208,7 @@ static jv f_negate(jq_state *jq, jv input) {
|
|
|
121
208
|
|
|
122
209
|
static jv f_startswith(jq_state *jq, jv a, jv b) {
|
|
123
210
|
if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING)
|
|
124
|
-
return
|
|
211
|
+
return ret_error2(a, b, jv_string("startswith() requires string inputs"));
|
|
125
212
|
int alen = jv_string_length_bytes(jv_copy(a));
|
|
126
213
|
int blen = jv_string_length_bytes(jv_copy(b));
|
|
127
214
|
jv ret;
|
|
@@ -137,7 +224,7 @@ static jv f_startswith(jq_state *jq, jv a, jv b) {
|
|
|
137
224
|
|
|
138
225
|
static jv f_endswith(jq_state *jq, jv a, jv b) {
|
|
139
226
|
if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING)
|
|
140
|
-
return
|
|
227
|
+
return ret_error2(a, b, jv_string("endswith() requires string inputs"));
|
|
141
228
|
const char *astr = jv_string_value(a);
|
|
142
229
|
const char *bstr = jv_string_value(b);
|
|
143
230
|
size_t alen = jv_string_length_bytes(jv_copy(a));
|
|
@@ -367,8 +454,32 @@ static jv f_tostring(jq_state *jq, jv input) {
|
|
|
367
454
|
}
|
|
368
455
|
}
|
|
369
456
|
|
|
457
|
+
static jv f_utf8bytelength(jq_state *jq, jv input) {
|
|
458
|
+
if (jv_get_kind(input) != JV_KIND_STRING)
|
|
459
|
+
return type_error(input, "only strings have UTF-8 byte length");
|
|
460
|
+
return jv_number(jv_string_length_bytes(input));
|
|
461
|
+
}
|
|
462
|
+
|
|
370
463
|
#define CHARS_ALPHANUM "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
|
371
464
|
|
|
465
|
+
static const unsigned char BASE64_ENCODE_TABLE[64 + 1] = CHARS_ALPHANUM "+/";
|
|
466
|
+
static const unsigned char BASE64_INVALID_ENTRY = 0xFF;
|
|
467
|
+
static const unsigned char BASE64_DECODE_TABLE[255] = {
|
|
468
|
+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
469
|
+
62, // +
|
|
470
|
+
0xFF, 0xFF, 0xFF,
|
|
471
|
+
63, // /
|
|
472
|
+
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // 0-9
|
|
473
|
+
0xFF, 0xFF, 0xFF,
|
|
474
|
+
99, // =
|
|
475
|
+
0xFF, 0xFF, 0xFF,
|
|
476
|
+
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, // A-Z
|
|
477
|
+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
|
478
|
+
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, // a-z
|
|
479
|
+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
|
|
372
483
|
static jv escape_string(jv input, const char* escapings) {
|
|
373
484
|
|
|
374
485
|
assert(jv_get_kind(input) == JV_KIND_STRING);
|
|
@@ -521,7 +632,6 @@ static jv f_format(jq_state *jq, jv input, jv fmt) {
|
|
|
521
632
|
jv_free(fmt);
|
|
522
633
|
input = f_tostring(jq, input);
|
|
523
634
|
jv line = jv_string("");
|
|
524
|
-
const char b64[64 + 1] = CHARS_ALPHANUM "+/";
|
|
525
635
|
const unsigned char* data = (const unsigned char*)jv_string_value(input);
|
|
526
636
|
int len = jv_string_length_bytes(jv_copy(input));
|
|
527
637
|
for (int i=0; i<len; i+=3) {
|
|
@@ -533,7 +643,7 @@ static jv f_format(jq_state *jq, jv input, jv fmt) {
|
|
|
533
643
|
}
|
|
534
644
|
char buf[4];
|
|
535
645
|
for (int j=0; j<4; j++) {
|
|
536
|
-
buf[j] =
|
|
646
|
+
buf[j] = BASE64_ENCODE_TABLE[(code >> (18 - j*6)) & 0x3f];
|
|
537
647
|
}
|
|
538
648
|
if (n < 3) buf[3] = '=';
|
|
539
649
|
if (n < 2) buf[2] = '=';
|
|
@@ -541,6 +651,49 @@ static jv f_format(jq_state *jq, jv input, jv fmt) {
|
|
|
541
651
|
}
|
|
542
652
|
jv_free(input);
|
|
543
653
|
return line;
|
|
654
|
+
} else if (!strcmp(fmt_s, "base64d")) {
|
|
655
|
+
jv_free(fmt);
|
|
656
|
+
input = f_tostring(jq, input);
|
|
657
|
+
const unsigned char* data = (const unsigned char*)jv_string_value(input);
|
|
658
|
+
int len = jv_string_length_bytes(jv_copy(input));
|
|
659
|
+
size_t decoded_len = (3 * len) / 4; // 3 usable bytes for every 4 bytes of input
|
|
660
|
+
char *result = jv_mem_calloc(decoded_len, sizeof(char));
|
|
661
|
+
memset(result, 0, decoded_len * sizeof(char));
|
|
662
|
+
uint32_t ri = 0;
|
|
663
|
+
int input_bytes_read=0;
|
|
664
|
+
uint32_t code = 0;
|
|
665
|
+
for (int i=0; i<len && data[i] != '='; i++) {
|
|
666
|
+
if (BASE64_DECODE_TABLE[data[i]] == BASE64_INVALID_ENTRY) {
|
|
667
|
+
free(result);
|
|
668
|
+
return type_error(input, "is not valid base64 data");
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
code <<= 6;
|
|
672
|
+
code |= BASE64_DECODE_TABLE[data[i]];
|
|
673
|
+
input_bytes_read++;
|
|
674
|
+
|
|
675
|
+
if (input_bytes_read == 4) {
|
|
676
|
+
result[ri++] = (code >> 16) & 0xFF;
|
|
677
|
+
result[ri++] = (code >> 8) & 0xFF;
|
|
678
|
+
result[ri++] = code & 0xFF;
|
|
679
|
+
input_bytes_read = 0;
|
|
680
|
+
code = 0;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if (input_bytes_read == 3) {
|
|
684
|
+
result[ri++] = (code >> 10) & 0xFF;
|
|
685
|
+
result[ri++] = (code >> 2) & 0xFF;
|
|
686
|
+
} else if (input_bytes_read == 2) {
|
|
687
|
+
result[ri++] = (code >> 4) & 0xFF;
|
|
688
|
+
} else if (input_bytes_read == 1) {
|
|
689
|
+
free(result);
|
|
690
|
+
return type_error(input, "trailing base64 byte found");
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
jv line = jv_string_sized(result, ri);
|
|
694
|
+
jv_free(input);
|
|
695
|
+
free(result);
|
|
696
|
+
return line;
|
|
544
697
|
} else {
|
|
545
698
|
jv_free(input);
|
|
546
699
|
return jv_invalid_with_msg(jv_string_concat(fmt, jv_string(" is not a valid format")));
|
|
@@ -591,7 +744,7 @@ static jv f_group_by_impl(jq_state *jq, jv input, jv keys) {
|
|
|
591
744
|
}
|
|
592
745
|
}
|
|
593
746
|
|
|
594
|
-
#ifdef
|
|
747
|
+
#ifdef HAVE_LIBONIG
|
|
595
748
|
static int f_match_name_iter(const UChar* name, const UChar *name_end, int ngroups,
|
|
596
749
|
int *groups, regex_t *reg, void *arg) {
|
|
597
750
|
jv captures = *(jv*)arg;
|
|
@@ -795,11 +948,11 @@ static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
|
|
|
795
948
|
jv_free(regex);
|
|
796
949
|
return result;
|
|
797
950
|
}
|
|
798
|
-
#else /* !
|
|
951
|
+
#else /* !HAVE_LIBONIG */
|
|
799
952
|
static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
|
|
800
953
|
return jv_invalid_with_msg(jv_string("jq was compiled without ONIGURUMA regex libary. match/test/sub and related functions are not available."));
|
|
801
954
|
}
|
|
802
|
-
#endif /*
|
|
955
|
+
#endif /* HAVE_LIBONIG */
|
|
803
956
|
|
|
804
957
|
static jv minmax_by(jv values, jv keys, int is_min) {
|
|
805
958
|
if (jv_get_kind(values) != JV_KIND_ARRAY)
|
|
@@ -907,14 +1060,14 @@ static jv f_error(jq_state *jq, jv input, jv msg) {
|
|
|
907
1060
|
|
|
908
1061
|
// FIXME Should autoconf check for this!
|
|
909
1062
|
#ifndef WIN32
|
|
910
|
-
extern
|
|
1063
|
+
extern char **environ;
|
|
911
1064
|
#endif
|
|
912
1065
|
|
|
913
1066
|
static jv f_env(jq_state *jq, jv input) {
|
|
914
1067
|
jv_free(input);
|
|
915
1068
|
jv env = jv_object();
|
|
916
1069
|
const char *var, *val;
|
|
917
|
-
for (
|
|
1070
|
+
for (char **e = environ; *e != NULL; e++) {
|
|
918
1071
|
var = e[0];
|
|
919
1072
|
val = strchr(e[0], '=');
|
|
920
1073
|
if (val == NULL)
|
|
@@ -925,6 +1078,21 @@ static jv f_env(jq_state *jq, jv input) {
|
|
|
925
1078
|
return env;
|
|
926
1079
|
}
|
|
927
1080
|
|
|
1081
|
+
static jv f_halt(jq_state *jq, jv input) {
|
|
1082
|
+
jv_free(input);
|
|
1083
|
+
jq_halt(jq, jv_invalid(), jv_invalid());
|
|
1084
|
+
return jv_true();
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
static jv f_halt_error(jq_state *jq, jv input, jv a) {
|
|
1088
|
+
if (jv_get_kind(a) != JV_KIND_NUMBER) {
|
|
1089
|
+
jv_free(a);
|
|
1090
|
+
return type_error(input, "halt_error/1: number required");
|
|
1091
|
+
}
|
|
1092
|
+
jq_halt(jq, a, input);
|
|
1093
|
+
return jv_true();
|
|
1094
|
+
}
|
|
1095
|
+
|
|
928
1096
|
static jv f_get_search_list(jq_state *jq, jv input) {
|
|
929
1097
|
jv_free(input);
|
|
930
1098
|
return jq_get_lib_dirs(jq);
|
|
@@ -942,17 +1110,14 @@ static jv f_get_jq_origin(jq_state *jq, jv input) {
|
|
|
942
1110
|
|
|
943
1111
|
static jv f_string_split(jq_state *jq, jv a, jv b) {
|
|
944
1112
|
if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING) {
|
|
945
|
-
|
|
946
|
-
jv_free(b);
|
|
947
|
-
return jv_invalid_with_msg(jv_string("split input and separator must be strings"));
|
|
1113
|
+
return ret_error2(a, b, jv_string("split input and separator must be strings"));
|
|
948
1114
|
}
|
|
949
1115
|
return jv_string_split(a, b);
|
|
950
1116
|
}
|
|
951
1117
|
|
|
952
1118
|
static jv f_string_explode(jq_state *jq, jv a) {
|
|
953
1119
|
if (jv_get_kind(a) != JV_KIND_STRING) {
|
|
954
|
-
|
|
955
|
-
return jv_invalid_with_msg(jv_string("explode input must be a string"));
|
|
1120
|
+
return ret_error(a, jv_string("explode input must be a string"));
|
|
956
1121
|
}
|
|
957
1122
|
return jv_string_explode(a);
|
|
958
1123
|
}
|
|
@@ -963,21 +1128,22 @@ static jv f_string_indexes(jq_state *jq, jv a, jv b) {
|
|
|
963
1128
|
|
|
964
1129
|
static jv f_string_implode(jq_state *jq, jv a) {
|
|
965
1130
|
if (jv_get_kind(a) != JV_KIND_ARRAY) {
|
|
966
|
-
|
|
967
|
-
return jv_invalid_with_msg(jv_string("implode input must be an array"));
|
|
1131
|
+
return ret_error(a, jv_string("implode input must be an array"));
|
|
968
1132
|
}
|
|
969
1133
|
return jv_string_implode(a);
|
|
970
1134
|
}
|
|
971
1135
|
|
|
972
1136
|
static jv f_setpath(jq_state *jq, jv a, jv b, jv c) { return jv_setpath(a, b, c); }
|
|
973
|
-
|
|
1137
|
+
extern jv _jq_path_append(jq_state *, jv, jv, jv);
|
|
1138
|
+
static jv f_getpath(jq_state *jq, jv a, jv b) {
|
|
1139
|
+
return _jq_path_append(jq, a, b, jv_getpath(jv_copy(a), jv_copy(b)));
|
|
1140
|
+
}
|
|
974
1141
|
static jv f_delpaths(jq_state *jq, jv a, jv b) { return jv_delpaths(a, b); }
|
|
975
1142
|
static jv f_has(jq_state *jq, jv a, jv b) { return jv_has(a, b); }
|
|
976
1143
|
|
|
977
1144
|
static jv f_modulemeta(jq_state *jq, jv a) {
|
|
978
1145
|
if (jv_get_kind(a) != JV_KIND_STRING) {
|
|
979
|
-
|
|
980
|
-
return jv_invalid_with_msg(jv_string("modulemeta input module name must be a string"));
|
|
1146
|
+
return ret_error(a, jv_string("modulemeta input module name must be a string"));
|
|
981
1147
|
}
|
|
982
1148
|
return load_module_meta(jq, a);
|
|
983
1149
|
}
|
|
@@ -1006,7 +1172,6 @@ static jv f_debug(jq_state *jq, jv input) {
|
|
|
1006
1172
|
|
|
1007
1173
|
static jv f_stderr(jq_state *jq, jv input) {
|
|
1008
1174
|
jv_dumpf(jv_copy(input), stderr, 0);
|
|
1009
|
-
fprintf(stderr, "\n");
|
|
1010
1175
|
return input;
|
|
1011
1176
|
}
|
|
1012
1177
|
|
|
@@ -1036,45 +1201,135 @@ static jv tm2jv(struct tm *tm) {
|
|
|
1036
1201
|
*
|
|
1037
1202
|
* Returns (time_t)-2 if mktime()'s side-effects cannot be corrected.
|
|
1038
1203
|
*/
|
|
1039
|
-
static time_t
|
|
1204
|
+
static time_t my_timegm(struct tm *tm) {
|
|
1040
1205
|
#ifdef HAVE_TIMEGM
|
|
1041
1206
|
return timegm(tm);
|
|
1042
1207
|
#else /* HAVE_TIMEGM */
|
|
1208
|
+
char *tz;
|
|
1209
|
+
|
|
1210
|
+
tz = (tz = getenv("TZ")) != NULL ? strdup(tz) : NULL;
|
|
1211
|
+
if (tz != NULL)
|
|
1212
|
+
setenv("TZ", "", 1);
|
|
1213
|
+
time_t t = mktime(tm);
|
|
1214
|
+
if (tz != NULL)
|
|
1215
|
+
setenv("TZ", tz, 1);
|
|
1216
|
+
return t;
|
|
1217
|
+
#endif /* !HAVE_TIMEGM */
|
|
1218
|
+
}
|
|
1219
|
+
static time_t my_mktime(struct tm *tm) {
|
|
1043
1220
|
time_t t = mktime(tm);
|
|
1044
1221
|
if (t == (time_t)-1)
|
|
1045
1222
|
return t;
|
|
1046
1223
|
#ifdef HAVE_TM_TM_GMT_OFF
|
|
1047
|
-
return t + tm
|
|
1048
|
-
#elif
|
|
1049
|
-
return t + tm
|
|
1224
|
+
return t + tm->tm_gmtoff;
|
|
1225
|
+
#elif HAVE_TM___TM_GMT_OFF
|
|
1226
|
+
return t + tm->__tm_gmtoff;
|
|
1050
1227
|
#else
|
|
1051
1228
|
return (time_t)-2; /* Not supported */
|
|
1052
1229
|
#endif
|
|
1053
|
-
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
/* Compute and set tm_wday */
|
|
1233
|
+
static void set_tm_wday(struct tm *tm) {
|
|
1234
|
+
/*
|
|
1235
|
+
* https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Gauss.27s_algorithm
|
|
1236
|
+
* https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html
|
|
1237
|
+
*
|
|
1238
|
+
* Tested with dates from 1900-01-01 through 2100-01-01. This
|
|
1239
|
+
* algorithm produces the wrong day-of-the-week number for dates in
|
|
1240
|
+
* the range 1900-01-01..1900-02-28, and for 2100-01-01..2100-02-28.
|
|
1241
|
+
* Since this is only needed on OS X and *BSD, we might just document
|
|
1242
|
+
* this.
|
|
1243
|
+
*/
|
|
1244
|
+
int century = (1900 + tm->tm_year) / 100;
|
|
1245
|
+
int year = (1900 + tm->tm_year) % 100;
|
|
1246
|
+
if (tm->tm_mon < 2)
|
|
1247
|
+
year--;
|
|
1248
|
+
/*
|
|
1249
|
+
* The month value in the wday computation below is shifted so that
|
|
1250
|
+
* March is 1, April is 2, .., January is 11, and February is 12.
|
|
1251
|
+
*/
|
|
1252
|
+
int mon = tm->tm_mon - 1;
|
|
1253
|
+
if (mon < 1)
|
|
1254
|
+
mon += 12;
|
|
1255
|
+
int wday =
|
|
1256
|
+
(tm->tm_mday + (int)floor((2.6 * mon - 0.2)) + year + (int)floor(year / 4.0) + (int)floor(century / 4.0) - 2 * century) % 7;
|
|
1257
|
+
if (wday < 0)
|
|
1258
|
+
wday += 7;
|
|
1259
|
+
#if 0
|
|
1260
|
+
/* See commentary above */
|
|
1261
|
+
assert(wday == tm->tm_wday || tm->tm_wday == 8);
|
|
1262
|
+
#endif
|
|
1263
|
+
tm->tm_wday = wday;
|
|
1264
|
+
}
|
|
1265
|
+
/*
|
|
1266
|
+
* Compute and set tm_yday.
|
|
1267
|
+
*
|
|
1268
|
+
*/
|
|
1269
|
+
static void set_tm_yday(struct tm *tm) {
|
|
1270
|
+
static const int d[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
|
1271
|
+
int mon = tm->tm_mon;
|
|
1272
|
+
int year = 1900 + tm->tm_year;
|
|
1273
|
+
int leap_day = 0;
|
|
1274
|
+
if (tm->tm_mon > 1 &&
|
|
1275
|
+
((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
|
|
1276
|
+
leap_day = 1;
|
|
1277
|
+
|
|
1278
|
+
/* Bound check index into d[] */
|
|
1279
|
+
if (mon < 0)
|
|
1280
|
+
mon = -mon;
|
|
1281
|
+
if (mon > 11)
|
|
1282
|
+
mon %= 12;
|
|
1283
|
+
|
|
1284
|
+
int yday = d[mon] + leap_day + tm->tm_mday - 1;
|
|
1285
|
+
assert(yday == tm->tm_yday || tm->tm_yday == 367);
|
|
1286
|
+
tm->tm_yday = yday;
|
|
1054
1287
|
}
|
|
1055
1288
|
|
|
1056
1289
|
#ifdef HAVE_STRPTIME
|
|
1057
1290
|
static jv f_strptime(jq_state *jq, jv a, jv b) {
|
|
1058
|
-
if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING)
|
|
1059
|
-
return
|
|
1291
|
+
if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING) {
|
|
1292
|
+
return ret_error2(a, b, jv_string("strptime/1 requires string inputs and arguments"));
|
|
1293
|
+
}
|
|
1060
1294
|
|
|
1061
1295
|
struct tm tm;
|
|
1062
1296
|
memset(&tm, 0, sizeof(tm));
|
|
1297
|
+
tm.tm_wday = 8; // sentinel
|
|
1298
|
+
tm.tm_yday = 367; // sentinel
|
|
1063
1299
|
const char *input = jv_string_value(a);
|
|
1064
1300
|
const char *fmt = jv_string_value(b);
|
|
1065
1301
|
const char *end = strptime(input, fmt, &tm);
|
|
1066
1302
|
|
|
1067
1303
|
if (end == NULL || (*end != '\0' && !isspace(*end))) {
|
|
1068
|
-
|
|
1069
|
-
jv_free(a);
|
|
1070
|
-
jv_free(b);
|
|
1071
|
-
return e;
|
|
1304
|
+
return ret_error2(a, b, jv_string_fmt("date \"%s\" does not match format \"%s\"", input, fmt));
|
|
1072
1305
|
}
|
|
1073
1306
|
jv_free(b);
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1307
|
+
/*
|
|
1308
|
+
* This is OS X or some *BSD whose strptime() is just not that
|
|
1309
|
+
* helpful!
|
|
1310
|
+
*
|
|
1311
|
+
* We don't know that the format string did involve parsing a
|
|
1312
|
+
* year, or a month (if tm->tm_mon == 0). But with our invalid
|
|
1313
|
+
* day-of-week and day-of-year sentinel checks above, the worst
|
|
1314
|
+
* this can do is produce garbage.
|
|
1315
|
+
*/
|
|
1316
|
+
#ifdef __APPLE__
|
|
1317
|
+
/*
|
|
1318
|
+
* Apple has made it worse, and different versions of the OS have different
|
|
1319
|
+
* behaviors. Some versions just don't touch the fields, but others do, and
|
|
1320
|
+
* sometimes provide wrong answers, at that! We can't tell at compile-time
|
|
1321
|
+
* which behavior the target system will have, so instead we always use our
|
|
1322
|
+
* functions to set these on OS X, and document that %u and %j are
|
|
1323
|
+
* unsupported on OS X.
|
|
1324
|
+
*/
|
|
1325
|
+
set_tm_wday(&tm);
|
|
1326
|
+
set_tm_yday(&tm);
|
|
1327
|
+
#else
|
|
1328
|
+
if (tm.tm_wday == 8 && tm.tm_mday != 0 && tm.tm_mon >= 0 && tm.tm_mon <= 11)
|
|
1329
|
+
set_tm_wday(&tm);
|
|
1330
|
+
if (tm.tm_yday == 367 && tm.tm_mday != 0 && tm.tm_mon >= 0 && tm.tm_mon <= 11)
|
|
1331
|
+
set_tm_yday(&tm);
|
|
1332
|
+
#endif
|
|
1078
1333
|
jv r = tm2jv(&tm);
|
|
1079
1334
|
if (*end != '\0')
|
|
1080
1335
|
r = jv_array_append(r, jv_string(end));
|
|
@@ -1092,8 +1347,10 @@ static jv f_strptime(jq_state *jq, jv a, jv b) {
|
|
|
1092
1347
|
#define TO_TM_FIELD(t, j, i) \
|
|
1093
1348
|
do { \
|
|
1094
1349
|
jv n = jv_array_get(jv_copy(j), (i)); \
|
|
1095
|
-
if (jv_get_kind(n) != (JV_KIND_NUMBER))
|
|
1350
|
+
if (jv_get_kind(n) != (JV_KIND_NUMBER)) { \
|
|
1351
|
+
jv_free(j); \
|
|
1096
1352
|
return 0; \
|
|
1353
|
+
} \
|
|
1097
1354
|
t = jv_number_value(n); \
|
|
1098
1355
|
jv_free(n); \
|
|
1099
1356
|
} while (0)
|
|
@@ -1126,9 +1383,9 @@ static int jv2tm(jv a, struct tm *tm) {
|
|
|
1126
1383
|
|
|
1127
1384
|
static jv f_mktime(jq_state *jq, jv a) {
|
|
1128
1385
|
if (jv_get_kind(a) != JV_KIND_ARRAY)
|
|
1129
|
-
return
|
|
1386
|
+
return ret_error(a, jv_string("mktime requires array inputs"));
|
|
1130
1387
|
if (jv_array_length(jv_copy(a)) < 6)
|
|
1131
|
-
return
|
|
1388
|
+
return ret_error(a, jv_string("mktime requires parsed datetime inputs"));
|
|
1132
1389
|
struct tm tm;
|
|
1133
1390
|
if (!jv2tm(a, &tm))
|
|
1134
1391
|
return jv_invalid_with_msg(jv_string("mktime requires parsed datetime inputs"));
|
|
@@ -1143,7 +1400,7 @@ static jv f_mktime(jq_state *jq, jv a) {
|
|
|
1143
1400
|
#ifdef HAVE_GMTIME_R
|
|
1144
1401
|
static jv f_gmtime(jq_state *jq, jv a) {
|
|
1145
1402
|
if (jv_get_kind(a) != JV_KIND_NUMBER)
|
|
1146
|
-
return
|
|
1403
|
+
return ret_error(a, jv_string("gmtime() requires numeric inputs"));
|
|
1147
1404
|
struct tm tm, *tmp;
|
|
1148
1405
|
memset(&tm, 0, sizeof(tm));
|
|
1149
1406
|
double fsecs = jv_number_value(a);
|
|
@@ -1158,7 +1415,7 @@ static jv f_gmtime(jq_state *jq, jv a) {
|
|
|
1158
1415
|
#elif defined HAVE_GMTIME
|
|
1159
1416
|
static jv f_gmtime(jq_state *jq, jv a) {
|
|
1160
1417
|
if (jv_get_kind(a) != JV_KIND_NUMBER)
|
|
1161
|
-
return
|
|
1418
|
+
return ret_error(a, jv_string("gmtime requires numeric inputs"));
|
|
1162
1419
|
struct tm tm, *tmp;
|
|
1163
1420
|
memset(&tm, 0, sizeof(tm));
|
|
1164
1421
|
double fsecs = jv_number_value(a);
|
|
@@ -1177,16 +1434,56 @@ static jv f_gmtime(jq_state *jq, jv a) {
|
|
|
1177
1434
|
}
|
|
1178
1435
|
#endif
|
|
1179
1436
|
|
|
1437
|
+
#ifdef HAVE_LOCALTIME_R
|
|
1438
|
+
static jv f_localtime(jq_state *jq, jv a) {
|
|
1439
|
+
if (jv_get_kind(a) != JV_KIND_NUMBER)
|
|
1440
|
+
return ret_error(a, jv_string("localtime() requires numeric inputs"));
|
|
1441
|
+
struct tm tm, *tmp;
|
|
1442
|
+
memset(&tm, 0, sizeof(tm));
|
|
1443
|
+
double fsecs = jv_number_value(a);
|
|
1444
|
+
time_t secs = fsecs;
|
|
1445
|
+
jv_free(a);
|
|
1446
|
+
tmp = localtime_r(&secs, &tm);
|
|
1447
|
+
if (tmp == NULL)
|
|
1448
|
+
return jv_invalid_with_msg(jv_string("error converting number of seconds since epoch to datetime"));
|
|
1449
|
+
a = tm2jv(tmp);
|
|
1450
|
+
return jv_array_set(a, 5, jv_number(jv_number_value(jv_array_get(jv_copy(a), 5)) + (fsecs - floor(fsecs))));
|
|
1451
|
+
}
|
|
1452
|
+
#elif defined HAVE_GMTIME
|
|
1453
|
+
static jv f_localtime(jq_state *jq, jv a) {
|
|
1454
|
+
if (jv_get_kind(a) != JV_KIND_NUMBER)
|
|
1455
|
+
return ret_error(a, jv_string("localtime requires numeric inputs"));
|
|
1456
|
+
struct tm tm, *tmp;
|
|
1457
|
+
memset(&tm, 0, sizeof(tm));
|
|
1458
|
+
double fsecs = jv_number_value(a);
|
|
1459
|
+
time_t secs = fsecs;
|
|
1460
|
+
jv_free(a);
|
|
1461
|
+
tmp = localtime(&secs);
|
|
1462
|
+
if (tmp == NULL)
|
|
1463
|
+
return jv_invalid_with_msg(jv_string("error converting number of seconds since epoch to datetime"));
|
|
1464
|
+
a = tm2jv(tmp);
|
|
1465
|
+
return jv_array_set(a, 5, jv_number(jv_number_value(jv_array_get(jv_copy(a), 5)) + (fsecs - floor(fsecs))));
|
|
1466
|
+
}
|
|
1467
|
+
#else
|
|
1468
|
+
static jv f_localtime(jq_state *jq, jv a) {
|
|
1469
|
+
jv_free(a);
|
|
1470
|
+
return jv_invalid_with_msg(jv_string("localtime not implemented on this platform"));
|
|
1471
|
+
}
|
|
1472
|
+
#endif
|
|
1473
|
+
|
|
1180
1474
|
#ifdef HAVE_STRFTIME
|
|
1181
1475
|
static jv f_strftime(jq_state *jq, jv a, jv b) {
|
|
1182
1476
|
if (jv_get_kind(a) == JV_KIND_NUMBER) {
|
|
1183
1477
|
a = f_gmtime(jq, a);
|
|
1184
1478
|
} else if (jv_get_kind(a) != JV_KIND_ARRAY) {
|
|
1185
|
-
return
|
|
1479
|
+
return ret_error2(a, b, jv_string("strftime/1 requires parsed datetime inputs"));
|
|
1480
|
+
} else if (jv_get_kind(b) != JV_KIND_STRING) {
|
|
1481
|
+
return ret_error2(a, b, jv_string("strftime/1 requires a string format"));
|
|
1186
1482
|
}
|
|
1187
1483
|
struct tm tm;
|
|
1188
1484
|
if (!jv2tm(a, &tm))
|
|
1189
|
-
return
|
|
1485
|
+
return ret_error(b, jv_string("strftime/1 requires parsed datetime inputs"));
|
|
1486
|
+
|
|
1190
1487
|
const char *fmt = jv_string_value(b);
|
|
1191
1488
|
size_t alloced = strlen(fmt) + 100;
|
|
1192
1489
|
char *buf = alloca(alloced);
|
|
@@ -1198,13 +1495,43 @@ static jv f_strftime(jq_state *jq, jv a, jv b) {
|
|
|
1198
1495
|
return jv_string(buf);
|
|
1199
1496
|
}
|
|
1200
1497
|
#else
|
|
1201
|
-
static jv f_strftime(jq_state *jq, jv a) {
|
|
1498
|
+
static jv f_strftime(jq_state *jq, jv a, jv b) {
|
|
1202
1499
|
jv_free(a);
|
|
1203
1500
|
jv_free(b);
|
|
1204
1501
|
return jv_invalid_with_msg(jv_string("strftime/1 not implemented on this platform"));
|
|
1205
1502
|
}
|
|
1206
1503
|
#endif
|
|
1207
1504
|
|
|
1505
|
+
#ifdef HAVE_STRFTIME
|
|
1506
|
+
static jv f_strflocaltime(jq_state *jq, jv a, jv b) {
|
|
1507
|
+
if (jv_get_kind(a) == JV_KIND_NUMBER) {
|
|
1508
|
+
a = f_localtime(jq, a);
|
|
1509
|
+
} else if (jv_get_kind(a) != JV_KIND_ARRAY) {
|
|
1510
|
+
return ret_error2(a, b, jv_string("strflocaltime/1 requires parsed datetime inputs"));
|
|
1511
|
+
} else if (jv_get_kind(b) != JV_KIND_STRING) {
|
|
1512
|
+
return ret_error2(a, b, jv_string("strflocaltime/1 requires a string format"));
|
|
1513
|
+
}
|
|
1514
|
+
struct tm tm;
|
|
1515
|
+
if (!jv2tm(a, &tm))
|
|
1516
|
+
return jv_invalid_with_msg(jv_string("strflocaltime/1 requires parsed datetime inputs"));
|
|
1517
|
+
const char *fmt = jv_string_value(b);
|
|
1518
|
+
size_t alloced = strlen(fmt) + 100;
|
|
1519
|
+
char *buf = alloca(alloced);
|
|
1520
|
+
size_t n = strftime(buf, alloced, fmt, &tm);
|
|
1521
|
+
jv_free(b);
|
|
1522
|
+
/* POSIX doesn't provide errno values for strftime() failures; weird */
|
|
1523
|
+
if (n == 0 || n > alloced)
|
|
1524
|
+
return jv_invalid_with_msg(jv_string("strflocaltime/1: unknown system failure"));
|
|
1525
|
+
return jv_string(buf);
|
|
1526
|
+
}
|
|
1527
|
+
#else
|
|
1528
|
+
static jv f_strflocaltime(jq_state *jq, jv a, jv b) {
|
|
1529
|
+
jv_free(a);
|
|
1530
|
+
jv_free(b);
|
|
1531
|
+
return jv_invalid_with_msg(jv_string("strflocaltime/1 not implemented on this platform"));
|
|
1532
|
+
}
|
|
1533
|
+
#endif
|
|
1534
|
+
|
|
1208
1535
|
#ifdef HAVE_GETTIMEOFDAY
|
|
1209
1536
|
static jv f_now(jq_state *jq, jv a) {
|
|
1210
1537
|
jv_free(a);
|
|
@@ -1220,27 +1547,43 @@ static jv f_now(jq_state *jq, jv a) {
|
|
|
1220
1547
|
}
|
|
1221
1548
|
#endif
|
|
1222
1549
|
|
|
1223
|
-
static jv f_current_filename(jq_state *jq) {
|
|
1550
|
+
static jv f_current_filename(jq_state *jq, jv a) {
|
|
1551
|
+
jv_free(a);
|
|
1552
|
+
|
|
1224
1553
|
jv r = jq_util_input_get_current_filename(jq);
|
|
1225
1554
|
if (jv_is_valid(r))
|
|
1226
1555
|
return r;
|
|
1227
1556
|
jv_free(r);
|
|
1228
1557
|
return jv_null();
|
|
1229
1558
|
}
|
|
1230
|
-
static jv f_current_line(jq_state *jq) {
|
|
1559
|
+
static jv f_current_line(jq_state *jq, jv a) {
|
|
1560
|
+
jv_free(a);
|
|
1231
1561
|
return jq_util_input_get_current_line(jq);
|
|
1232
1562
|
}
|
|
1233
1563
|
|
|
1234
1564
|
#define LIBM_DD(name) \
|
|
1235
|
-
{(cfunction_ptr)f_ ## name,
|
|
1565
|
+
{(cfunction_ptr)f_ ## name, #name, 1},
|
|
1236
1566
|
#define LIBM_DD_NO(name)
|
|
1237
1567
|
|
|
1238
1568
|
#define LIBM_DDD(name) \
|
|
1239
|
-
{(cfunction_ptr)f_ ## name,
|
|
1569
|
+
{(cfunction_ptr)f_ ## name, #name, 3},
|
|
1240
1570
|
#define LIBM_DDD_NO(name)
|
|
1241
1571
|
|
|
1572
|
+
#define LIBM_DDDD(name) \
|
|
1573
|
+
{(cfunction_ptr)f_ ## name, #name, 4},
|
|
1574
|
+
#define LIBM_DDDD_NO(name)
|
|
1575
|
+
|
|
1242
1576
|
static const struct cfunction function_list[] = {
|
|
1243
1577
|
#include "libm.h"
|
|
1578
|
+
#ifdef HAVE_FREXP
|
|
1579
|
+
{(cfunction_ptr)f_frexp,"frexp", 1},
|
|
1580
|
+
#endif
|
|
1581
|
+
#ifdef HAVE_MODF
|
|
1582
|
+
{(cfunction_ptr)f_modf,"modf", 1},
|
|
1583
|
+
#endif
|
|
1584
|
+
#ifdef HAVE_LGAMMA_R
|
|
1585
|
+
{(cfunction_ptr)f_lgamma_r,"lgamma_r", 1},
|
|
1586
|
+
#endif
|
|
1244
1587
|
{(cfunction_ptr)f_plus, "_plus", 3},
|
|
1245
1588
|
{(cfunction_ptr)f_negate, "_negate", 1},
|
|
1246
1589
|
{(cfunction_ptr)f_minus, "_minus", 3},
|
|
@@ -1273,6 +1616,7 @@ static const struct cfunction function_list[] = {
|
|
|
1273
1616
|
{(cfunction_ptr)f_greatereq, "_greatereq", 3},
|
|
1274
1617
|
{(cfunction_ptr)f_contains, "contains", 2},
|
|
1275
1618
|
{(cfunction_ptr)f_length, "length", 1},
|
|
1619
|
+
{(cfunction_ptr)f_utf8bytelength, "utf8bytelength", 1},
|
|
1276
1620
|
{(cfunction_ptr)f_type, "type", 1},
|
|
1277
1621
|
{(cfunction_ptr)f_isinfinite, "isinfinite", 1},
|
|
1278
1622
|
{(cfunction_ptr)f_isnan, "isnan", 1},
|
|
@@ -1289,6 +1633,8 @@ static const struct cfunction function_list[] = {
|
|
|
1289
1633
|
{(cfunction_ptr)f_error, "error", 2},
|
|
1290
1634
|
{(cfunction_ptr)f_format, "format", 2},
|
|
1291
1635
|
{(cfunction_ptr)f_env, "env", 1},
|
|
1636
|
+
{(cfunction_ptr)f_halt, "halt", 1},
|
|
1637
|
+
{(cfunction_ptr)f_halt_error, "halt_error", 2},
|
|
1292
1638
|
{(cfunction_ptr)f_get_search_list, "get_search_list", 1},
|
|
1293
1639
|
{(cfunction_ptr)f_get_prog_origin, "get_prog_origin", 1},
|
|
1294
1640
|
{(cfunction_ptr)f_get_jq_origin, "get_jq_origin", 1},
|
|
@@ -1299,14 +1645,18 @@ static const struct cfunction function_list[] = {
|
|
|
1299
1645
|
{(cfunction_ptr)f_stderr, "stderr", 1},
|
|
1300
1646
|
{(cfunction_ptr)f_strptime, "strptime", 2},
|
|
1301
1647
|
{(cfunction_ptr)f_strftime, "strftime", 2},
|
|
1648
|
+
{(cfunction_ptr)f_strflocaltime, "strflocaltime", 2},
|
|
1302
1649
|
{(cfunction_ptr)f_mktime, "mktime", 1},
|
|
1303
1650
|
{(cfunction_ptr)f_gmtime, "gmtime", 1},
|
|
1651
|
+
{(cfunction_ptr)f_localtime, "localtime", 1},
|
|
1304
1652
|
{(cfunction_ptr)f_now, "now", 1},
|
|
1305
1653
|
{(cfunction_ptr)f_current_filename, "input_filename", 1},
|
|
1306
1654
|
{(cfunction_ptr)f_current_line, "input_line_number", 1},
|
|
1307
1655
|
};
|
|
1656
|
+
#undef LIBM_DDDD_NO
|
|
1308
1657
|
#undef LIBM_DDD_NO
|
|
1309
1658
|
#undef LIBM_DD_NO
|
|
1659
|
+
#undef LIBM_DDDD
|
|
1310
1660
|
#undef LIBM_DDD
|
|
1311
1661
|
#undef LIBM_DD
|
|
1312
1662
|
|
|
@@ -1339,315 +1689,68 @@ static block bind_bytecoded_builtins(block b) {
|
|
|
1339
1689
|
{
|
|
1340
1690
|
// Note that we can now define `range` as a jq-coded function
|
|
1341
1691
|
block rangevar = gen_op_var_fresh(STOREV, "rangevar");
|
|
1342
|
-
block
|
|
1343
|
-
block range = BLOCK(
|
|
1692
|
+
block rangestart = gen_op_var_fresh(STOREV, "rangestart");
|
|
1693
|
+
block range = BLOCK(gen_op_simple(DUP),
|
|
1694
|
+
gen_call("start", gen_noop()),
|
|
1695
|
+
rangestart,
|
|
1344
1696
|
gen_call("end", gen_noop()),
|
|
1697
|
+
gen_op_simple(DUP),
|
|
1698
|
+
gen_op_bound(LOADV, rangestart),
|
|
1699
|
+
// Reset rangevar for every value generated by "end"
|
|
1700
|
+
rangevar,
|
|
1345
1701
|
gen_op_bound(RANGE, rangevar));
|
|
1346
1702
|
builtins = BLOCK(builtins, gen_function("range",
|
|
1347
1703
|
BLOCK(gen_param("start"), gen_param("end")),
|
|
1348
1704
|
range));
|
|
1349
1705
|
}
|
|
1350
|
-
|
|
1351
|
-
return block_bind_referenced(builtins, b, OP_IS_CALL_PSEUDO);
|
|
1706
|
+
return block_bind(builtins, b, OP_IS_CALL_PSEUDO);
|
|
1352
1707
|
}
|
|
1353
1708
|
|
|
1354
|
-
#define LIBM_DD(name) "def " #name ": _" #name ";",
|
|
1355
|
-
#define LIBM_DDD(name) "def " #name "(a;b): _" #name "(a;b);",
|
|
1356
|
-
#define LIBM_DD_NO(name) "def " #name ": \"Error: " #name "() not found at build time\"|error;",
|
|
1357
|
-
#define LIBM_DDD_NO(name) "def " #name "(a;b): \"Error: " #name "() not found at build time\"|error;",
|
|
1358
1709
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1710
|
+
|
|
1711
|
+
static const char* const jq_builtins =
|
|
1712
|
+
/* Include jq-coded builtins */
|
|
1713
|
+
#include "src/builtin.inc"
|
|
1714
|
+
|
|
1715
|
+
/* Include unsupported math functions next */
|
|
1716
|
+
#define LIBM_DD(name)
|
|
1717
|
+
#define LIBM_DDD(name)
|
|
1718
|
+
#define LIBM_DDDD(name)
|
|
1719
|
+
#define LIBM_DD_NO(name) "def " #name ": \"Error: " #name "/0 not found at build time\"|error;"
|
|
1720
|
+
#define LIBM_DDD_NO(name) "def " #name "(a;b): \"Error: " #name "/2 not found at build time\"|error;"
|
|
1721
|
+
#define LIBM_DDDD_NO(name) "def " #name "(a;b;c): \"Error: " #name "/3 not found at build time\"|error;"
|
|
1369
1722
|
#include "libm.h"
|
|
1370
|
-
|
|
1371
|
-
"def
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
"def
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
"def
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
"def to_entries: [keys_unsorted[] as $k | {key: $k, value: .[$k]}];",
|
|
1383
|
-
"def from_entries: map({(.key // .Key // .Name): (if has(\"value\") then .value else .Value end)}) | add | .//={};",
|
|
1384
|
-
"def with_entries(f): to_entries | map(f) | from_entries;",
|
|
1385
|
-
"def reverse: [.[length - 1 - range(0;length)]];",
|
|
1386
|
-
"def indices($i): if type == \"array\" and ($i|type) == \"array\" then .[$i]"
|
|
1387
|
-
" elif type == \"array\" then .[[$i]]"
|
|
1388
|
-
" elif type == \"string\" and ($i|type) == \"string\" then _strindices($i)"
|
|
1389
|
-
" else .[$i] end;",
|
|
1390
|
-
"def index($i): indices($i) | .[0];", // TODO: optimize
|
|
1391
|
-
"def rindex($i): indices($i) | .[-1:][0];", // TODO: optimize
|
|
1392
|
-
"def paths: path(recurse(if (type|. == \"array\" or . == \"object\") then .[] else empty end))|select(length > 0);",
|
|
1393
|
-
"def paths(node_filter): . as $dot|paths|select(. as $p|$dot|getpath($p)|node_filter);",
|
|
1394
|
-
"def any(generator; condition):"
|
|
1395
|
-
" [label $out | foreach generator as $i"
|
|
1396
|
-
" (false;"
|
|
1397
|
-
" if . then break $out elif $i | condition then true else . end;"
|
|
1398
|
-
" if . then . else empty end)] | length == 1;",
|
|
1399
|
-
"def any(condition): any(.[]; condition);",
|
|
1400
|
-
"def any: any(.);",
|
|
1401
|
-
"def all(generator; condition): "
|
|
1402
|
-
" [label $out | foreach generator as $i"
|
|
1403
|
-
" (true;"
|
|
1404
|
-
" if .|not then break $out elif $i | condition then . else false end;"
|
|
1405
|
-
" if .|not then . else empty end)] | length == 0;",
|
|
1406
|
-
"def all(condition): all(.[]; condition);",
|
|
1407
|
-
"def all: all(.);",
|
|
1408
|
-
"def isfinite: type == \"number\" and (isinfinite | not);",
|
|
1409
|
-
"def arrays: select(type == \"array\");",
|
|
1410
|
-
"def objects: select(type == \"object\");",
|
|
1411
|
-
"def iterables: arrays, objects;",
|
|
1412
|
-
"def booleans: select(type == \"boolean\");",
|
|
1413
|
-
"def numbers: select(type == \"number\");",
|
|
1414
|
-
"def normals: select(isnormal);",
|
|
1415
|
-
"def finites: select(isfinite);",
|
|
1416
|
-
"def strings: select(type == \"string\");",
|
|
1417
|
-
"def nulls: select(type == \"null\");",
|
|
1418
|
-
"def values: select(. != null);",
|
|
1419
|
-
"def scalars: select(. == null or . == true or . == false or type == \"number\" or type == \"string\");",
|
|
1420
|
-
"def scalars_or_empty: select(. == null or . == true or . == false or type == \"number\" or type == \"string\" or ((type==\"array\" or type==\"object\") and length==0));",
|
|
1421
|
-
"def leaf_paths: paths(scalars);",
|
|
1422
|
-
"def join($x): reduce .[] as $i (null; (.//\"\") + (if . == null then $i else $x + $i end))//\"\";",
|
|
1423
|
-
"def _flatten($x): reduce .[] as $i ([]; if $i | type == \"array\" and $x != 0 then . + ($i | _flatten($x-1)) else . + [$i] end);",
|
|
1424
|
-
"def flatten($x): if $x < 0 then error(\"flatten depth must not be negative\") else _flatten($x) end;",
|
|
1425
|
-
"def flatten: _flatten(-1);",
|
|
1426
|
-
"def range($x): range(0;$x);",
|
|
1427
|
-
"def fromdateiso8601: strptime(\"%Y-%m-%dT%H:%M:%SZ\")|mktime;",
|
|
1428
|
-
"def todateiso8601: strftime(\"%Y-%m-%dT%H:%M:%SZ\");",
|
|
1429
|
-
"def fromdate: fromdateiso8601;",
|
|
1430
|
-
"def todate: todateiso8601;",
|
|
1431
|
-
"def match(re; mode): _match_impl(re; mode; false)|.[];",
|
|
1432
|
-
"def match($val): ($val|type) as $vt | if $vt == \"string\" then match($val; null)"
|
|
1433
|
-
" elif $vt == \"array\" and ($val | length) > 1 then match($val[0]; $val[1])"
|
|
1434
|
-
" elif $vt == \"array\" and ($val | length) > 0 then match($val[0]; null)"
|
|
1435
|
-
" else error( $vt + \" not a string or array\") end;",
|
|
1436
|
-
"def test(re; mode): _match_impl(re; mode; true);",
|
|
1437
|
-
"def test($val): ($val|type) as $vt | if $vt == \"string\" then test($val; null)"
|
|
1438
|
-
" elif $vt == \"array\" and ($val | length) > 1 then test($val[0]; $val[1])"
|
|
1439
|
-
" elif $vt == \"array\" and ($val | length) > 0 then test($val[0]; null)"
|
|
1440
|
-
" else error( $vt + \" not a string or array\") end;",
|
|
1441
|
-
"def capture(re; mods): match(re; mods) | reduce ( .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair ({}; . + $pair);",
|
|
1442
|
-
"def capture($val): ($val|type) as $vt | if $vt == \"string\" then capture($val; null)"
|
|
1443
|
-
" elif $vt == \"array\" and ($val | length) > 1 then capture($val[0]; $val[1])"
|
|
1444
|
-
" elif $vt == \"array\" and ($val | length) > 0 then capture($val[0]; null)"
|
|
1445
|
-
" else error( $vt + \" not a string or array\") end;",
|
|
1446
|
-
"def scan(re):"
|
|
1447
|
-
" match(re; \"g\")"
|
|
1448
|
-
" | if (.captures|length > 0)"
|
|
1449
|
-
" then [ .captures | .[] | .string ]"
|
|
1450
|
-
" else .string"
|
|
1451
|
-
" end ;",
|
|
1452
|
-
//
|
|
1453
|
-
// If input is an array, then emit a stream of successive subarrays of length n (or less),
|
|
1454
|
-
// and similarly for strings.
|
|
1455
|
-
"def _nwise(a; $n): if a|length <= $n then a else a[0:$n] , _nwise(a[$n:]; $n) end;",
|
|
1456
|
-
"def _nwise($n): _nwise(.; $n);",
|
|
1457
|
-
//
|
|
1458
|
-
// splits/1 produces a stream; split/1 is retained for backward compatibility.
|
|
1459
|
-
"def splits($re; flags): . as $s"
|
|
1460
|
-
// # multiple occurrences of "g" are acceptable
|
|
1461
|
-
" | [ match($re; \"g\" + flags) | (.offset, .offset + .length) ]"
|
|
1462
|
-
" | [0] + . +[$s|length]"
|
|
1463
|
-
" | _nwise(2)"
|
|
1464
|
-
" | $s[.[0]:.[1] ] ;",
|
|
1465
|
-
"def splits($re): splits($re; null);",
|
|
1466
|
-
//
|
|
1467
|
-
// split emits an array for backward compatibility
|
|
1468
|
-
"def split($re; flags): [ splits($re; flags) ];",
|
|
1469
|
-
//
|
|
1470
|
-
// If s contains capture variables, then create a capture object and pipe it to s
|
|
1471
|
-
"def sub($re; s):"
|
|
1472
|
-
" . as $in"
|
|
1473
|
-
" | [match($re)]"
|
|
1474
|
-
" | if length == 0 then $in"
|
|
1475
|
-
" else .[0]"
|
|
1476
|
-
" | . as $r"
|
|
1477
|
-
// # create the \"capture\" object:
|
|
1478
|
-
" | reduce ( $r | .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair"
|
|
1479
|
-
" ({}; . + $pair)"
|
|
1480
|
-
" | $in[0:$r.offset] + s + $in[$r.offset+$r.length:]"
|
|
1481
|
-
" end ;",
|
|
1482
|
-
//
|
|
1483
|
-
// If s contains capture variables, then create a capture object and pipe it to s
|
|
1484
|
-
"def sub($re; s; flags):"
|
|
1485
|
-
" def subg: explode | select(. != 103) | implode;"
|
|
1486
|
-
// # "fla" should be flags with all occurrences of g removed; gs should be non-nil if flags has a g
|
|
1487
|
-
" def sub1(fla; gs):"
|
|
1488
|
-
" def mysub:"
|
|
1489
|
-
" . as $in"
|
|
1490
|
-
" | [match($re; fla)]"
|
|
1491
|
-
" | if length == 0 then $in"
|
|
1492
|
-
" else .[0] as $edit"
|
|
1493
|
-
" | ($edit | .offset + .length) as $len"
|
|
1494
|
-
// # create the "capture" object:
|
|
1495
|
-
" | reduce ( $edit | .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair"
|
|
1496
|
-
" ({}; . + $pair)"
|
|
1497
|
-
" | $in[0:$edit.offset]"
|
|
1498
|
-
" + s"
|
|
1499
|
-
" + ($in[$len:] | if gs then mysub else . end)"
|
|
1500
|
-
" end ;"
|
|
1501
|
-
" mysub ;"
|
|
1502
|
-
" (flags | index(\"g\")) as $gs"
|
|
1503
|
-
" | (flags | if $gs then subg else . end) as $fla"
|
|
1504
|
-
" | sub1($fla; $gs);",
|
|
1505
|
-
//
|
|
1506
|
-
"def sub($re; s): sub($re; s; \"\");",
|
|
1507
|
-
// repeated substitution of re (which may contain named captures)
|
|
1508
|
-
"def gsub($re; s; flags): sub($re; s; flags + \"g\");",
|
|
1509
|
-
"def gsub($re; s): sub($re; s; \"g\");",
|
|
1510
|
-
|
|
1511
|
-
//#######################################################################
|
|
1512
|
-
// range/3, with a `by` expression argument
|
|
1513
|
-
"def range($init; $upto; $by): "
|
|
1514
|
-
" def _range: "
|
|
1515
|
-
" if ($by > 0 and . < $upto) or ($by < 0 and . > $upto) then ., ((.+$by)|_range) else . end; "
|
|
1516
|
-
" if $by == 0 then $init else $init|_range end | select(($by > 0 and . < $upto) or ($by < 0 and . > $upto));",
|
|
1517
|
-
// generic iterator/generator
|
|
1518
|
-
"def while(cond; update): "
|
|
1519
|
-
" def _while: "
|
|
1520
|
-
" if cond then ., (update | _while) else empty end; "
|
|
1521
|
-
" _while;",
|
|
1522
|
-
"def until(cond; next): "
|
|
1523
|
-
" def _until: "
|
|
1524
|
-
" if cond then . else (next|_until) end;"
|
|
1525
|
-
" _until;",
|
|
1526
|
-
"def limit($n; exp): if $n < 0 then exp else label $out | foreach exp as $item ([$n, null]; if .[0] < 1 then break $out else [.[0] -1, $item] end; .[1]) end;",
|
|
1527
|
-
"def first(g): label $out | foreach g as $item ([false, null]; if .[0]==true then break $out else [true, $item] end; .[1]);",
|
|
1528
|
-
"def last(g): reduce g as $item (null; $item);",
|
|
1529
|
-
"def nth($n; g): if $n < 0 then error(\"nth doesn't support negative indices\") else last(limit($n + 1; g)) end;",
|
|
1530
|
-
"def first: .[0];",
|
|
1531
|
-
"def last: .[-1];",
|
|
1532
|
-
"def nth($n): .[$n];",
|
|
1533
|
-
"def combinations:"
|
|
1534
|
-
" if length == 0 then [] else"
|
|
1535
|
-
" .[0][] as $x"
|
|
1536
|
-
" | (.[1:] | combinations) as $y"
|
|
1537
|
-
" | [$x] + $y"
|
|
1538
|
-
" end;",
|
|
1539
|
-
"def combinations(n):"
|
|
1540
|
-
" . as $dot"
|
|
1541
|
-
" | [range(n) | $dot]"
|
|
1542
|
-
" | combinations;",
|
|
1543
|
-
// # transpose a possibly jagged matrix, quickly;
|
|
1544
|
-
// # rows are padded with nulls so the result is always rectangular.
|
|
1545
|
-
"def transpose:"
|
|
1546
|
-
" if . == [] then []"
|
|
1547
|
-
" else . as $in"
|
|
1548
|
-
" | (map(length) | max) as $max"
|
|
1549
|
-
" | length as $length"
|
|
1550
|
-
" | reduce range(0; $max) as $j"
|
|
1551
|
-
" ([]; . + [reduce range(0;$length) as $i ([]; . + [ $in[$i][$j] ] )] )"
|
|
1552
|
-
" end;",
|
|
1553
|
-
"def in(xs): . as $x | xs | has($x);",
|
|
1554
|
-
"def inside(xs): . as $x | xs | contains($x);",
|
|
1555
|
-
"def input: _input;",
|
|
1556
|
-
"def repeat(exp): "
|
|
1557
|
-
" def _repeat: "
|
|
1558
|
-
" exp, _repeat;"
|
|
1559
|
-
" _repeat;",
|
|
1560
|
-
"def inputs: try repeat(_input) catch if .==\"break\" then empty else .|error end;",
|
|
1561
|
-
// # like ruby's downcase - only characters A to Z are affected
|
|
1562
|
-
"def ascii_downcase:"
|
|
1563
|
-
" explode | map( if 65 <= . and . <= 90 then . + 32 else . end) | implode;",
|
|
1564
|
-
// # like ruby's upcase - only characters a to z are affected
|
|
1565
|
-
"def ascii_upcase:"
|
|
1566
|
-
" explode | map( if 97 <= . and . <= 122 then . - 32 else . end) | implode;",
|
|
1567
|
-
|
|
1568
|
-
// Streaming utilities
|
|
1569
|
-
"def truncate_stream(stream):"
|
|
1570
|
-
" . as $n | null | stream | . as $input | if (.[0]|length) > $n then setpath([0];$input[0][1:]) else empty end;",
|
|
1571
|
-
"def fromstream(i):"
|
|
1572
|
-
" foreach i as $item ("
|
|
1573
|
-
" [null,false,null,false];"
|
|
1574
|
-
" if ($item[0]|length) == 0 then [null,false,.[2],.[3]]"
|
|
1575
|
-
" elif ($item|length) == 1 and ($item[0]|length) < 2 then [null,false,.[0],.[1]]"
|
|
1576
|
-
" else . end |"
|
|
1577
|
-
" . as $state |"
|
|
1578
|
-
" if ($item|length) > 1 and ($item[0]|length) > 0 then"
|
|
1579
|
-
" [.[0]|setpath(($item|.[0]); ($item|.[1])), "
|
|
1580
|
-
" true, "
|
|
1581
|
-
" $state[2], "
|
|
1582
|
-
" $state[3]] "
|
|
1583
|
-
" else ."
|
|
1584
|
-
" end;"
|
|
1585
|
-
" if ($item[0]|length) == 1 and ($item|length == 1) and .[3] then .[2] else empty end,"
|
|
1586
|
-
" if ($item[0]|length) == 0 then $item[1] else empty end"
|
|
1587
|
-
" );",
|
|
1588
|
-
"def tostream:\n"
|
|
1589
|
-
" {string:true,number:true,boolean:true,null:true} as $leaf_types |\n"
|
|
1590
|
-
" . as $dot |\n"
|
|
1591
|
-
" if $leaf_types[$dot|type] or length==0 then [[],$dot]\n"
|
|
1592
|
-
" else\n"
|
|
1593
|
-
" # We really need a _streaming_ form of `keys`.\n"
|
|
1594
|
-
" # We can use `range` for arrays, but not for objects.\n"
|
|
1595
|
-
" keys as $keys |\n"
|
|
1596
|
-
" $keys[-1] as $last|\n"
|
|
1597
|
-
" ((# for each key\n"
|
|
1598
|
-
" $keys[] | . as $key |\n"
|
|
1599
|
-
" $dot[$key] | . as $dot |\n"
|
|
1600
|
-
" # recurse on each key/value\n"
|
|
1601
|
-
" tostream|.[0]|=[$key]+.),\n"
|
|
1602
|
-
" # then add the closing marker\n"
|
|
1603
|
-
" [[$last]])\n"
|
|
1604
|
-
" end;",
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
// # Assuming the input array is sorted, bsearch/1 returns
|
|
1608
|
-
// # the index of the target if the target is in the input array; and otherwise
|
|
1609
|
-
// # (-1 - ix), where ix is the insertion point that would leave the array sorted.
|
|
1610
|
-
// # If the input is not sorted, bsearch will terminate but with irrelevant results.
|
|
1611
|
-
"def bsearch(target):"
|
|
1612
|
-
" if length == 0 then -1"
|
|
1613
|
-
" elif length == 1 then"
|
|
1614
|
-
" if target == .[0] then 0 elif target < .[0] then -1 else -2 end"
|
|
1615
|
-
" else . as $in"
|
|
1616
|
-
"" // # state variable: [start, end, answer]
|
|
1617
|
-
"" // # where start and end are the upper and lower offsets to use.
|
|
1618
|
-
" | [0, length-1, null]"
|
|
1619
|
-
" | until( .[0] > .[1] ;"
|
|
1620
|
-
" if .[2] != null then (.[1] = -1)" // # i.e. break
|
|
1621
|
-
" else"
|
|
1622
|
-
" ( ( (.[1] + .[0]) / 2 ) | floor ) as $mid"
|
|
1623
|
-
" | $in[$mid] as $monkey"
|
|
1624
|
-
" | if $monkey == target then (.[2] = $mid)" // # success
|
|
1625
|
-
" elif .[0] == .[1] then (.[1] = -1)" // # failure
|
|
1626
|
-
" elif $monkey < target then (.[0] = ($mid + 1))"
|
|
1627
|
-
" else (.[1] = ($mid - 1))"
|
|
1628
|
-
" end"
|
|
1629
|
-
" end )"
|
|
1630
|
-
" | if .[2] == null then" // # compute the insertion point
|
|
1631
|
-
" if $in[ .[0] ] < target then (-2 -.[0])"
|
|
1632
|
-
" else (-1 -.[0])"
|
|
1633
|
-
" end"
|
|
1634
|
-
" else .[2]"
|
|
1635
|
-
" end"
|
|
1636
|
-
" end;",
|
|
1637
|
-
};
|
|
1723
|
+
#ifndef HAVE_FREXP
|
|
1724
|
+
"def frexp: \"Error: frexp/0 not found found at build time\"|error;"
|
|
1725
|
+
#endif
|
|
1726
|
+
#ifndef HAVE_MODF
|
|
1727
|
+
"def modf: \"Error: modf/0 not found found at build time\"|error;"
|
|
1728
|
+
#endif
|
|
1729
|
+
#ifndef HAVE_LGAMMA_R
|
|
1730
|
+
"def lgamma_r: \"Error: lgamma_r/0 not found found at build time\"|error;"
|
|
1731
|
+
#endif
|
|
1732
|
+
;
|
|
1733
|
+
|
|
1734
|
+
#undef LIBM_DDDD_NO
|
|
1638
1735
|
#undef LIBM_DDD_NO
|
|
1639
1736
|
#undef LIBM_DD_NO
|
|
1737
|
+
#undef LIBM_DDDD
|
|
1640
1738
|
#undef LIBM_DDD
|
|
1641
1739
|
#undef LIBM_DD
|
|
1642
1740
|
|
|
1643
1741
|
|
|
1742
|
+
static block gen_builtin_list(block builtins) {
|
|
1743
|
+
jv list = jv_array_append(block_list_funcs(builtins, 1), jv_string("builtins/0"));
|
|
1744
|
+
return BLOCK(builtins, gen_function("builtins", gen_noop(), gen_const(list)));
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1644
1747
|
static int builtins_bind_one(jq_state *jq, block* bb, const char* code) {
|
|
1645
1748
|
struct locfile* src;
|
|
1646
1749
|
src = locfile_init(jq, "<builtin>", code, strlen(code));
|
|
1647
1750
|
block funcs;
|
|
1648
1751
|
int nerrors = jq_parse_library(src, &funcs);
|
|
1649
1752
|
if (nerrors == 0) {
|
|
1650
|
-
*bb =
|
|
1753
|
+
*bb = block_bind(funcs, *bb, OP_IS_CALL_PSEUDO);
|
|
1651
1754
|
}
|
|
1652
1755
|
locfile_free(src);
|
|
1653
1756
|
return nerrors;
|
|
@@ -1669,16 +1772,18 @@ static int slurp_lib(jq_state *jq, block* bb) {
|
|
|
1669
1772
|
}
|
|
1670
1773
|
|
|
1671
1774
|
int builtins_bind(jq_state *jq, block* bb) {
|
|
1775
|
+
block builtins = gen_noop();
|
|
1672
1776
|
int nerrors = slurp_lib(jq, bb);
|
|
1673
1777
|
if (nerrors) {
|
|
1674
1778
|
block_free(*bb);
|
|
1675
1779
|
return nerrors;
|
|
1676
1780
|
}
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
*bb =
|
|
1781
|
+
nerrors = builtins_bind_one(jq, &builtins, jq_builtins);
|
|
1782
|
+
assert(!nerrors);
|
|
1783
|
+
builtins = bind_bytecoded_builtins(builtins);
|
|
1784
|
+
builtins = gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), builtins);
|
|
1785
|
+
builtins = gen_builtin_list(builtins);
|
|
1786
|
+
*bb = block_bind(builtins, *bb, OP_IS_CALL_PSEUDO);
|
|
1787
|
+
*bb = block_drop_unreferenced(*bb);
|
|
1683
1788
|
return nerrors;
|
|
1684
1789
|
}
|