aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy1
-rw-r--r--.github/workflows/main.yml89
-rw-r--r--.github/workflows/release.yml25
-rw-r--r--VERSION2
-rw-r--r--changelogs/changes-2.4.0.md20
-rw-r--r--doc/appendix/json-api.qdoc1
-rw-r--r--doc/qbs.qdoc103
-rw-r--r--doc/reference/cli/builtin/cli-build.qdoc2
-rw-r--r--doc/reference/cli/builtin/cli-resolve.qdoc1
-rw-r--r--doc/reference/items/probe/conanfile-probe.qdoc3
-rw-r--r--doc/reference/module-providers/conan-module-provider.qdoc101
-rw-r--r--doc/reference/module-providers/qbspkgconfig-module-provider.qdoc11
-rw-r--r--doc/reference/modules/flatbuf-c-module.qdoc83
-rw-r--r--doc/reference/modules/flatbuf-cpp-module.qdoc144
-rw-r--r--doc/reference/modules/qt-core-module.qdoc16
-rw-r--r--doc/tutorial.qdoc96
-rw-r--r--examples/flatbuffers/.clang-format2
-rw-r--r--examples/flatbuffers/monster-c/conanfile.txt6
-rw-r--r--examples/flatbuffers/monster-c/monster-c.qbs12
-rw-r--r--examples/flatbuffers/monster-c/monster.c367
-rw-r--r--examples/flatbuffers/monster-cpp/conanfile.txt6
-rw-r--r--examples/flatbuffers/monster-cpp/monster-cpp.qbs12
-rw-r--r--examples/flatbuffers/monster-cpp/monster.cpp104
-rw-r--r--examples/flatbuffers/shared/monster.fbs32
-rw-r--r--examples/protobuf/addressbook_conan/addressbook_conan.qbs20
-rw-r--r--examples/protobuf/addressbook_conan/conanfile.txt6
-rw-r--r--examples/protobuf/addressbook_conan/main.cpp180
-rw-r--r--qbs-resources/imports/QbsLibrary.qbs3
-rw-r--r--scripts/conan-profiles/mac_x64/qbs-test8
-rw-r--r--scripts/conan-profiles/win_x64/qbs-test9
-rwxr-xr-xscripts/setup-conan-profiles.sh62
-rw-r--r--share/qbs/imports/qbs/PathTools/path-tools.js22
-rw-r--r--share/qbs/imports/qbs/Probes/LibraryProbe.qbs22
-rw-r--r--share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js26
-rw-r--r--share/qbs/imports/qbs/Probes/qmake-probe.js32
-rw-r--r--share/qbs/module-providers/Qt/setup-qt.js2
-rw-r--r--share/qbs/module-providers/Qt/templates/core.qbs6
-rw-r--r--share/qbs/module-providers/conan.js239
-rw-r--r--share/qbs/module-providers/conan.qbs12
-rw-r--r--share/qbs/module-providers/qbspkgconfig.qbs24
-rw-r--r--share/qbs/modules/capnproto/capnprotobase.qbs5
-rw-r--r--share/qbs/modules/capnproto/cpp/capnprotocpp.qbs1
-rw-r--r--share/qbs/modules/flatbuf/c/flatbuffers-c.qbs61
-rw-r--r--share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs69
-rw-r--r--share/qbs/modules/flatbuf/flatbuffers.js126
-rw-r--r--share/qbs/modules/flatbuf/flatbuffersbase.qbs58
-rw-r--r--share/qbs/modules/protobuf/cpp/protobufcpp.qbs4
-rw-r--r--share/qbs/modules/protobuf/protobufbase.qbs2
-rw-r--r--share/qbs/modules/xcode/xcode.qbs16
-rw-r--r--src/app/qbs/commandlinefrontend.cpp14
-rw-r--r--src/app/qbs/parser/commandlineoption.cpp11
-rw-r--r--src/app/qbs/parser/commandlineoption.h17
-rw-r--r--src/app/qbs/parser/commandlineoptionpool.cpp9
-rw-r--r--src/app/qbs/parser/commandlineoptionpool.h1
-rw-r--r--src/app/qbs/parser/commandlineparser.cpp5
-rw-r--r--src/app/qbs/parser/commandlineparser.h1
-rw-r--r--src/app/qbs/parser/parsercommand.cpp24
-rw-r--r--src/conan/extensions/generators/qbsdeps.py218
-rw-r--r--src/lib/corelib/CMakeLists.txt1
-rw-r--r--src/lib/corelib/buildgraph/abstractcommandexecutor.cpp11
-rw-r--r--src/lib/corelib/buildgraph/buildgraph.cpp2
-rw-r--r--src/lib/corelib/buildgraph/qtmocscanner.cpp13
-rw-r--r--src/lib/corelib/buildgraph/rulecommands.cpp11
-rw-r--r--src/lib/corelib/buildgraph/rulecommands.h2
-rw-r--r--src/lib/corelib/buildgraph/rulesapplicator.cpp17
-rw-r--r--src/lib/corelib/jsextensions/domxml.cpp2
-rw-r--r--src/lib/corelib/jsextensions/moduleproperties.cpp2
-rw-r--r--src/lib/corelib/language/builtindeclarations.cpp16
-rw-r--r--src/lib/corelib/language/evaluator.cpp36
-rw-r--r--src/lib/corelib/language/evaluator.h6
-rw-r--r--src/lib/corelib/language/scriptengine.cpp34
-rw-r--r--src/lib/corelib/language/scriptengine.h2
-rw-r--r--src/lib/corelib/loader/dependenciesresolver.cpp53
-rw-r--r--src/lib/corelib/loader/itemreaderastvisitor.cpp2
-rw-r--r--src/lib/corelib/loader/loaderutils.h1
-rw-r--r--src/lib/corelib/loader/moduleloader.cpp30
-rw-r--r--src/lib/corelib/loader/moduleloader.h9
-rw-r--r--src/lib/corelib/loader/moduleproviderloader.cpp22
-rw-r--r--src/lib/corelib/loader/moduleproviderloader.h9
-rw-r--r--src/lib/corelib/tools/codelocation.cpp73
-rw-r--r--src/lib/corelib/tools/codelocation.h29
-rw-r--r--src/lib/corelib/tools/scripttools.cpp9
-rw-r--r--src/lib/corelib/tools/scripttools.h2
-rw-r--r--src/lib/corelib/tools/setupprojectparameters.cpp18
-rw-r--r--src/lib/corelib/tools/setupprojectparameters.h3
-rw-r--r--src/lib/corelib/tools/span.h81
-rw-r--r--src/lib/corelib/tools/stringutils.h28
-rw-r--r--src/lib/pkgconfig/CMakeLists.txt9
-rw-r--r--src/lib/pkgconfig/pcpackage.h19
-rw-r--r--src/lib/pkgconfig/pcparser.cpp21
-rw-r--r--src/lib/pkgconfig/pkgconfig.cpp34
-rw-r--r--src/lib/pkgconfig/pkgconfig.qbs12
-rw-r--r--src/shared/CMakeLists.txt2
-rw-r--r--src/shared/quickjs/.clang-format2
-rw-r--r--src/shared/quickjs/CMakeLists.txt1
-rw-r--r--src/shared/quickjs/LICENSE2
-rw-r--r--src/shared/quickjs/cutils.c6
-rw-r--r--src/shared/quickjs/cutils.h90
-rw-r--r--src/shared/quickjs/libbf.c8475
-rw-r--r--src/shared/quickjs/libbf.h543
-rw-r--r--src/shared/quickjs/libregexp-opcode.h5
-rw-r--r--src/shared/quickjs/libregexp.c483
-rw-r--r--src/shared/quickjs/libregexp.h49
-rw-r--r--src/shared/quickjs/libunicode-table.h2650
-rw-r--r--src/shared/quickjs/libunicode.c518
-rw-r--r--src/shared/quickjs/libunicode.h102
-rw-r--r--src/shared/quickjs/list.h11
-rw-r--r--src/shared/quickjs/quickjs-atom.h18
-rw-r--r--src/shared/quickjs/quickjs-opcode.h23
-rw-r--r--src/shared/quickjs/quickjs.c7962
-rw-r--r--src/shared/quickjs/quickjs.diff4061
-rw-r--r--src/shared/quickjs/quickjs.h59
-rw-r--r--src/shared/quickjs/quickjs.qbs5
-rw-r--r--src/shared/span/.clang-format2
-rw-r--r--src/shared/span/CMakeLists.txt4
-rw-r--r--src/shared/span/LICENSE_1_0.txt (renamed from src/shared/variant/LICENSE.md)0
-rw-r--r--src/shared/span/README.md557
-rw-r--r--src/shared/span/span.hpp1947
-rw-r--r--src/shared/span/span.qbs (renamed from src/shared/variant/variant.qbs)7
-rw-r--r--src/shared/variant/CMakeLists.txt4
-rw-r--r--src/shared/variant/README.md37
-rw-r--r--src/shared/variant/variant.h63
-rw-r--r--src/shared/variant/variant.hpp2465
-rw-r--r--src/src.qbs2
-rw-r--r--tests/auto/api/tst_api.cpp7
-rw-r--r--tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs2
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs11
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt3
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/main.cpp8
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt9
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py36
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp7
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h10
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt7
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py35
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt1
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp6
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h3
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py15
-rw-r--r--tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h6
-rw-r--r--tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs2
-rw-r--r--tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs1
-rw-r--r--tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs1
-rw-r--r--tests/auto/blackbox/testdata/capnproto/capnproto_cpp_pkgconfig.qbs19
-rw-r--r--tests/auto/blackbox/testdata/capnproto/conanfile.txt6
-rw-r--r--tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs5
-rw-r--r--tests/auto/blackbox/testdata/external-libs/external-libs.qbs2
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/bar.fbs9
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/baz.fbs9
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/conanfile.txt6
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat.c36
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat.cpp22
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp25
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs24
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_c.qbs21
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs21
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp22
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs23
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp22
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs23
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp26
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs25
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp25
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs22
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/foo.fbs8
-rw-r--r--tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs8
-rw-r--r--tests/auto/blackbox/testdata/grpc/conanfile.txt7
-rw-r--r--tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs3
-rw-r--r--tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs18
-rw-r--r--tests/auto/blackbox/testdata/linkerMode/darwin.s6
-rw-r--r--tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs2
-rw-r--r--tests/auto/blackbox/testdata/linkerMode/main.s1
-rw-r--r--tests/auto/blackbox/testdata/protobuf/conanfile.txt6
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp221
-rw-r--r--tests/auto/blackbox/tst_blackbox.h7
-rw-r--r--tests/auto/blackbox/tst_blackboxbase.cpp13
-rw-r--r--tests/auto/blackbox/tst_blackboxbase.h5
-rw-r--r--tests/auto/blackbox/tst_blackboxexamples.cpp1
-rw-r--r--tests/auto/blackbox/tst_blackboxproviders.cpp106
-rw-r--r--tests/auto/blackbox/tst_blackboxproviders.h4
-rw-r--r--tests/auto/language/testdata/erroneous/module-with-id.qbs4
-rw-r--r--tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs1
-rw-r--r--tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs1
-rw-r--r--tests/auto/language/testdata/erroneous/modules/recursion_helper/recursion_helper.qbs3
-rw-r--r--tests/auto/language/testdata/erroneous/recursive-property-direct.qbs3
-rw-r--r--tests/auto/language/testdata/erroneous/recursive-property-indirect-via-module.qbs4
-rw-r--r--tests/auto/language/testdata/erroneous/recursive-property-indirect.qbs5
-rw-r--r--tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs3
-rw-r--r--tests/auto/language/tst_language.cpp4
-rw-r--r--tests/auto/tools/tst_tools.cpp88
-rw-r--r--tests/auto/tools/tst_tools.h4
-rw-r--r--tests/benchmarker/benchmarker-main.cpp2
-rw-r--r--tutorial/LICENSE49
-rw-r--r--tutorial/chapter-5/app/app.qbs50
-rw-r--r--tutorial/chapter-5/app/main.c50
-rw-r--r--tutorial/chapter-6/app/app.qbs50
-rw-r--r--tutorial/chapter-6/app/main.c50
-rw-r--r--tutorial/chapter-6/test/test.qbs50
-rw-r--r--tutorial/chapter-7/app/main.c50
-rw-r--r--tutorial/chapter-7/qbs/imports/MyAutoTest.qbs50
-rw-r--r--tutorial/chapter-7/test/test.qbs50
-rw-r--r--tutorial/chapter-8/app/app.qbs50
-rw-r--r--tutorial/chapter-8/app/main.c50
-rw-r--r--tutorial/chapter-8/qbs/imports/MyApplication.qbs50
-rw-r--r--tutorial/chapter-8/qbs/imports/MyAutoTest.qbs50
-rw-r--r--tutorial/chapter-8/test/test.qbs50
-rw-r--r--tutorial/chapter-9/app/app.qbs9
-rw-r--r--tutorial/chapter-9/app/main.c14
-rw-r--r--tutorial/chapter-9/lib/lib.c10
-rw-r--r--tutorial/chapter-9/lib/lib.h8
-rw-r--r--tutorial/chapter-9/lib/lib.qbs10
-rw-r--r--tutorial/chapter-9/lib/lib_global.h25
-rw-r--r--tutorial/chapter-9/myproject.qbs32
-rw-r--r--tutorial/chapter-9/qbs/imports/MyApplication.qbs10
-rw-r--r--tutorial/chapter-9/qbs/imports/MyAutoTest.qbs3
-rw-r--r--tutorial/chapter-9/qbs/imports/MyLibrary.qbs26
-rw-r--r--tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs30
-rw-r--r--tutorial/chapter-9/test/test.c18
-rw-r--r--tutorial/chapter-9/test/test.qbs5
-rw-r--r--tutorial/chapter-9/version-header/version-header.qbs57
-rw-r--r--tutorial/chapter-9/version-header/version.h.in9
221 files changed, 22620 insertions, 12774 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 92e6eeefe..d448466b9 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -13,7 +13,6 @@ Checks: >
google-build-namespaces,
google-global-names-in-headers,
google-objc-*,
- -google-readability-casting,
google-readability-namespace-comments,
google-runtime-operator,
misc-definitions-in-headers,
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 71c1ae4ac..44ed18531 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -34,11 +34,16 @@ jobs:
- uses: actions/checkout@v1
- name: Create .ccache dir
run: mkdir -p ~/.ccache
+ - name: prepare timestamp
+ id: get-timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+ shell: bash
- name: ccache cache files
uses: actions/cache@v4
with:
path: ~/.ccache
- key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache
+ key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache-${{ steps.get-timestamp.outputs.timestamp }}
+ restore-keys: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache
- name: Pull the Docker Image
run: docker-compose pull ${{ matrix.config.image }}
- name: Print ccache stats
@@ -110,11 +115,16 @@ jobs:
- uses: actions/checkout@v1
- name: Create .ccache dir
run: mkdir -p ~/.ccache
+ - name: prepare timestamp
+ id: get-timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+ shell: bash
- name: ccache cache files
uses: actions/cache@v4
with:
path: ~/.ccache
- key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache
+ key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache-${{ steps.get-timestamp.outputs.timestamp }}
+ restore-keys: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache
- name: Pull the Docker Image
run: docker-compose pull ${{ matrix.config.image }}
- name: Print ccache stats
@@ -157,11 +167,16 @@ jobs:
- uses: actions/checkout@v1
- name: Create .ccache dir
run: mkdir -p ~/.ccache
+ - name: prepare timestamp
+ id: get-timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+ shell: bash
- name: ccache cache files
uses: actions/cache@v4
with:
path: ~/.ccache
- key: ${{ runner.os }}-ccache
+ key: ${{ runner.os }}-clang-ccache-${{ steps.get-timestamp.outputs.timestamp }}
+ restore-keys: ${{ runner.os }}-clang-ccache
- name: Install required packages
run: |
brew install ccache p7zip
@@ -207,12 +222,29 @@ jobs:
QT_ASSUME_STDERR_HAS_CONSOLE: 1
steps:
- uses: actions/checkout@v1
+ - name: prepare timestamp
+ id: get-timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+ shell: bash
- name: clcache cache files
uses: actions/cache@v4
with:
path: ~/clcache
- key: ${{ runner.os }}-msvc-clcache
- - name: Set up Python ${{ matrix.python-version }}
+ key: ${{ runner.os }}-msvc-clcache-${{ steps.get-timestamp.outputs.timestamp }}
+ restore-keys: ${{ runner.os }}-msvc-clcache
+ - name: Install Conan
+ run: |
+ choco install conan
+ choco install ninja
+ echo "C:\\Program Files\\conan\\conan" >> $GITHUB_PATH
+ echo "C:\\ProgramData\\chocolatey\\lib\\ninja\\tools" >> $GITHUB_PATH
+ shell: bash
+ - name: Configure Conan
+ run: |
+ conan config install src/conan/
+ ./scripts/setup-conan-profiles.sh
+ shell: bash
+ - name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.8
@@ -264,12 +296,17 @@ jobs:
CCACHE_DIR: ${{ github.workspace }}\ccache
steps:
- uses: actions/checkout@v1
+ - name: prepare timestamp
+ id: get-timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+ shell: bash
- name: ccache cache files
uses: actions/cache@v4
with:
- path: ${{ github.workspace }}/ccache
- key: ${{ runner.os }}-mingw-ccache
- - name: Set up Python ${{ matrix.python-version }}
+ path: ~/.ccache
+ key: ${{ runner.os }}-mingw-ccache-${{ steps.get-timestamp.outputs.timestamp }}
+ restore-keys: ${{ runner.os }}-mingw-ccache
+ - name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.8
@@ -678,7 +715,7 @@ jobs:
target: 'desktop',
toolchain: 'clang_64',
xcodeVersion: '',
- testProfile: 'xcode_13_4_1-macosx-x86_64',
+ testProfile: 'clang',
qtVersion: '6.5.0',
script: './scripts/test-qbs.sh',
}
@@ -695,6 +732,20 @@ jobs:
run: echo "./release/install-root/usr/local/bin" >> $GITHUB_PATH
- name: Install required packages
run: brew install capnp ccache grpc icoutils makensis protobuf p7zip
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ if: matrix.config.toolchain == 'clang_64'
+ with:
+ python-version: 3.12
+ - name: Install Conan
+ if: matrix.config.toolchain == 'clang_64'
+ uses: turtlebrowser/get-conan@main
+ - name: Setup Conan
+ if: matrix.config.toolchain == 'clang_64'
+ run: |
+ brew install ninja
+ conan config install src/conan/
+ ./scripts/setup-conan-profiles.sh
- name: Install Host Qt
if: matrix.config.toolchain == 'ios'
uses: ./.github/actions/download-qt
@@ -810,6 +861,26 @@ jobs:
version: ${{ matrix.config.qtVersion }}
- name: Install MinGW
uses: ./.github/actions/download-mingw
+ - name: Install Ninja
+ if: matrix.config.toolchain == 'win64_msvc2019_64'
+ run: |
+ choco install ninja
+ echo "C:\\ProgramData\\chocolatey\\lib\\ninja\\tools" >> $GITHUB_PATH
+ shell: bash
+ - name: Install Conan
+ if: matrix.config.toolchain == 'win64_msvc2019_64'
+ run: |
+ choco install conan
+ choco install ninja
+ echo "C:\\Program Files\\conan\\conan" >> $GITHUB_PATH
+ echo "C:\\ProgramData\\chocolatey\\lib\\ninja\\tools" >> $GITHUB_PATH
+ shell: bash
+ - name: Configure Conan
+ if: matrix.config.toolchain == 'win64_msvc2019_64'
+ run: |
+ conan config install src/conan/
+ ./scripts/setup-conan-profiles.sh
+ shell: bash
- name: Setup Qbs
run: |
qbs setup-toolchains --detect
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 1b65762e7..168518385 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -35,13 +35,16 @@ jobs:
- uses: actions/checkout@v1
- name: Create .ccache dir
run: mkdir -p ~/.ccache
- - name: test
- run: echo ${{ github.ref }}
+ - name: prepare timestamp
+ id: get-timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+ shell: bash
- name: ccache cache files
uses: actions/cache@v4
with:
path: ~/.ccache
- key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache
+ key: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache-${{ steps.get-timestamp.outputs.timestamp }}
+ restore-keys: ${{ runner.os }}-${{ matrix.config.cacheid }}-ccache
- name: Pull the Docker Image
run: docker-compose pull jammy-qt6
- name: Print ccache stats
@@ -77,11 +80,16 @@ jobs:
- uses: actions/checkout@v1
- name: Create .ccache dir
run: mkdir -p ~/.ccache
+ - name: prepare timestamp
+ id: get-timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+ shell: bash
- name: ccache cache files
uses: actions/cache@v4
with:
path: ~/.ccache
- key: ${{ runner.os }}-release-ccache
+ key: ${{ runner.os }}-release-ccache-${{ steps.get-timestamp.outputs.timestamp }}
+ restore-keys: ${{ runner.os }}-release-ccache
- name: Install required packages
run: |
brew install ccache p7zip
@@ -124,11 +132,16 @@ jobs:
- name: Create .ccache dir
run: mkdir -p ~/.ccache
shell: bash
+ - name: prepare timestamp
+ id: get-timestamp
+ run: echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+ shell: bash
- name: clcache cache files
uses: actions/cache@v4
with:
- path: ~/.ccache
- key: ${{ runner.os }}-release-msvc-docker-clcache
+ path: ~/clcache
+ key: ${{ runner.os }}-release-msvc-docker-clcache-${{ steps.get-timestamp.outputs.timestamp }}
+ restore-keys: ${{ runner.os }}-release-msvc-docker-clcache
- name: Pull the Windows Image
run: docker-compose pull windows
- name: Print clcache stats
diff --git a/VERSION b/VERSION
index f90b1afc0..437459cd9 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.3.2
+2.5.0
diff --git a/changelogs/changes-2.4.0.md b/changelogs/changes-2.4.0.md
new file mode 100644
index 000000000..862908280
--- /dev/null
+++ b/changelogs/changes-2.4.0.md
@@ -0,0 +1,20 @@
+# General
+* Added a Conan module provider (QBS-1665).
+* Added a flatbuffers module (QBS-1666).
+* Rules trying to create artifacts outside the build directory is now a hard error (QBS-1268).
+* More details are now printed when a command times out (QBS-1750).
+* Updated the bundled quickjs library.
+
+# Language
+* The pkg-config based fallback provider was removed.
+* It is no longer allowed to attach a QML id to a module item.
+* Property evaluation now detects infinite recursion (QBS-1793).
+
+# Documentation
+* Added more tutorials.
+
+# Contributors
+* Christian Kandeler
+* Ivan Komissarov
+* Kai Dohmen
+* Raphael Cotty
diff --git a/doc/appendix/json-api.qdoc b/doc/appendix/json-api.qdoc
index 02ec6aef3..7b093bc4e 100644
--- a/doc/appendix/json-api.qdoc
+++ b/doc/appendix/json-api.qdoc
@@ -126,7 +126,6 @@
\row \li dry-run \li bool \li no
\row \li environment \li \l Environment \li no
\row \li error-handling-mode \li string \li no
- \row \li fallback-provider-enabled \li bool \li no
\row \li force-probe-execution \li bool \li no
\row \li log-time \li bool \li no
\row \li log-level \li \l LogLevel \li no
diff --git a/doc/qbs.qdoc b/doc/qbs.qdoc
index bde1da008..136c7eb9f 100644
--- a/doc/qbs.qdoc
+++ b/doc/qbs.qdoc
@@ -80,6 +80,7 @@
\li \l{tutorial-6.html}{Project Properties}
\li \l{tutorial-7.html}{Buildconfig Module}
\li \l{tutorial-8.html}{Configurable Library}
+ \li \l{tutorial-9.html}{Version Header}
\endlist
\li \l{How-tos}
\li \l{Reference}
@@ -1899,8 +1900,80 @@
For instance, the overall set of modules related to a certain task might depend
on some information present on the local platform.
- \note Module providers are an advanced concept that you will rarely need to use directly.
- Reading this section is not required for most people's everyday work.
+ Use Module Providers to create new modules during the \c resolve stage, for example when
+ locating external dependencies such as libraries.
+
+ Consider the following example:
+
+ \code
+ CppApplication {
+ files: "main.cpp"
+ Depends { name: "zlib" }
+ qbsModuleProviders: ["conan", "qbspkgconfig"]
+ }
+ \endcode
+ Here, we want to use the \l{https://www.zlib.net}{zlib} compression library in our application.
+ Since there is no pre-defined module called \c "zlib", \QBS will try to create it using
+ Module Providers. \QBS will invoke all providers specified in the
+ \l{Product::qbsModuleProviders}{qbsModuleProviders} property and those providers will create
+ the requested module if possible. Providers contribute to the \l{Product::}{qbsSearchPaths}
+ in the order specified by this property, so modules generated by providers specified earlier
+ are prioritised. In the example above, modules created by the \l conan provider have higher
+ priority than modules created by \c qbspkgconfig.
+
+ \section1 Lookup Based on Module Name
+ Originally, the \l{Qt} module provider was a the only provider in \QBS and we wanted to make
+ its usage transparent to users. Thus, it was implemented by automatically kicking in when \QBS
+ saw the dependency on the \c Qt module such as "Qt.core". It is also possible to specify the
+ order of providers explicitly:
+ \code
+ CppApplication {
+ files: "main.cpp"
+ Depends { name: "Qt.core" }
+ qbsModuleProviders: ["Qt", "qbspkgconfig"]
+ }
+ \endcode
+ That way, users have more control over the module priorities.
+
+ Note that setting the \c qbsModuleProviders property disables the lookup based on the
+ module name entirely.
+
+ \section1 Provider Eagerness
+ Historically, providers were implemented in an \e eager way meaning that once a provider is
+ called, it creates as many modules as it can. For example, when called, the \l{qbspkgconfig}
+ provider created a module for each .pc file found in the system. Even though providers are
+ quite fast, this violates the zero-overhead principle (you don't pay for what you don't use).
+ Thus, we introduced non-eager providers which only create one module at a time when that
+ module is requested by the \l{Depends} item. This behavior is controlled by the
+ \l{ModuleProvider::isEager}{isEager} property. We advise against using eager providers in
+ new code.
+
+ \section1 Selecting Module Providers
+
+ As described above, you can select which providers to run using the
+ \l{Product::qbsModuleProviders}{qbsModuleProviders} property. This property can be set on the
+ Product as well as the \l{Project::qbsModuleProviders}{Project} level:
+
+ \code
+ $ qbs resolve project.qbsModuleProviders:providerA \ # sets property globally for the Project
+ projects.SomeProject.qbsModuleProviders:providerB \ # overrides property for the specific Project
+ products.SomeProduct.qbsModuleProviders:providerC \ # overrides property for the specific Product
+ \endcode
+
+ \section1 Parameterizing Module Providers
+
+ You can pass information to module providers from the command line, via profiles or
+ from within a product, in a similar way as you would do for modules. For instance, the
+ following invocation of \QBS passes information to two module providers \c a and \c b:
+ \code
+ $ qbs moduleProviders.a.p1:true moduleProviders.a.p2:true moduleProviders.b.p:false
+ \endcode
+ \QBS will set the properties of the respective module providers accordingly.
+ In the above example, module provider \c a needs to declare two boolean properties \c p1
+ and \c p2, and they will be set to \c true and \c false, respectively.
+
+ \note The following section contains some implementation details. Reading this section is not
+ required for most people's everyday work.
\section1 How \QBS Uses Module Providers
@@ -1928,32 +2001,6 @@
of whether it created any modules or not.
\endlist
- \section1 Selecting Module Providers
-
- As described above, it is possible to select which providers to run using the
- \l{Product::qbsModuleProviders}{qbsModuleProviders} property. Providers contribute to the
- \l{Product::}{qbsSearchPaths} in the order specified by this property, so modules generated
- by providers specified earlier are prioritized. This property can be set on the
- Product as well as the \l{Project::qbsModuleProviders}{Project} level:
-
- \code
- $ qbs resolve project.qbsModuleProviders:providerA \ # sets property globally for the Project
- projects.SomeProject.qbsModuleProviders:providerB \ # overrides property for the specific Project
- products.SomeProduct.qbsModuleProviders:providerC \ # overrides property for the specific Product
- \endcode
-
- \section1 Parameterizing Module Providers
-
- You can pass information to module providers from the command line, via profiles or
- from within a product, in a similar way as you would do for modules. For instance, the
- following invocation of \QBS passes information to two module providers \c a and \c b:
- \code
- $ qbs moduleProviders.a.p1:true moduleProviders.a.p2:true moduleProviders.b.p:false
- \endcode
- \QBS will set the properties of the respective module providers accordingly.
- In the above example, module provider \c a needs to declare two boolean properties \c p1
- and \c p2, and they will be set to \c true and \c false, respectively.
-
*/
/*!
diff --git a/doc/reference/cli/builtin/cli-build.qdoc b/doc/reference/cli/builtin/cli-build.qdoc
index 683b1ebb8..8547a78d2 100644
--- a/doc/reference/cli/builtin/cli-build.qdoc
+++ b/doc/reference/cli/builtin/cli-build.qdoc
@@ -78,8 +78,6 @@
\include cli-options.qdocinc products-specified
\include cli-options.qdocinc settings-dir
\include cli-options.qdocinc show-progress
- \target no-fallback-module-provider
- \include cli-options.qdocinc no-fallback-module-provider
\include cli-options.qdocinc wait-lock
\section1 Parameters
diff --git a/doc/reference/cli/builtin/cli-resolve.qdoc b/doc/reference/cli/builtin/cli-resolve.qdoc
index 4569980bd..99f1658ea 100644
--- a/doc/reference/cli/builtin/cli-resolve.qdoc
+++ b/doc/reference/cli/builtin/cli-resolve.qdoc
@@ -55,7 +55,6 @@
\include cli-options.qdocinc more-verbose
\include cli-options.qdocinc settings-dir
\include cli-options.qdocinc show-progress
- \include cli-options.qdocinc no-fallback-module-provider
\include cli-options.qdocinc deprecation-warnings
\section1 Parameters
diff --git a/doc/reference/items/probe/conanfile-probe.qdoc b/doc/reference/items/probe/conanfile-probe.qdoc
index cc91b9237..f1b30f0c3 100644
--- a/doc/reference/items/probe/conanfile-probe.qdoc
+++ b/doc/reference/items/probe/conanfile-probe.qdoc
@@ -43,6 +43,9 @@
properties in products. \c ConanfileProbe can also be used to run other
Conan generators and to retrieve their output.
+ \note This probe only works with Conan 1.x since the \c json generator was removed in Conan
+ 2.0. Use the \l{conan}{conan} module provider and \c QbsDeps generator with Conan 2.0 instead.
+
\section1 Examples
In the following examples we assume that our project contains a \c conanfile.py.
diff --git a/doc/reference/module-providers/conan-module-provider.qdoc b/doc/reference/module-providers/conan-module-provider.qdoc
new file mode 100644
index 000000000..4edba94d8
--- /dev/null
+++ b/doc/reference/module-providers/conan-module-provider.qdoc
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype conan
+ \inqmlmodule QbsModuleProviders
+ \since 2.4
+
+ \brief Module provider for the Conan package manager.
+
+ This module provider allows integration with the \l{https://conan.io}{Conan} package manager.
+
+ \section1 Prerequisites
+ In order to use this provider, you will need to install the
+ \l{https://github.com/qbs/qbs/blob/master/src/conan/extensions/generators/qbsdeps.py}{QbsDeps generator}
+ first. In order to do so, clone the \QBS repository and run the following command from the \QBS
+ source directory:
+ \code
+ $ conan config install src/conan/
+ \endcode
+ This will copy the generator to \c .conan2/extensions/generators/qbsdeps.py in the user's home
+ directory.
+ Alternatively, you can use \c curl to download the file:
+ \code
+ $ curl 'https://github.com/qbs/qbs/raw/master/src/conan/extensions/generators/qbsdeps.py' -o ~/.conan2/extensions/generators/qbsdeps.py
+ \endcode
+
+ \section1 Example
+ For details on how to setup a project to use with Conan, see the \
+ l{https://github.com/qbs/qbs/blob/master/examples/protobuf/addressbook_conan}{addressbook_conan}
+ folder in examples.
+ First, you will need a \l{https://docs.conan.io/2/reference/conanfile_txt.html}{conanfile} as
+ shown below.
+ \code
+ [requires]
+ protobuf/3.21.12
+ [tool_requires]
+ protobuf/3.21.12
+ [generators]
+ QbsDeps
+ \endcode
+ We use the text version for simplicity, but you can use the Python conanfile as well.
+
+ Next, set the \l{Product::qbsModuleProviders}{qbsModuleProviders} property to \c "conan":
+ \snippet ../examples/protobuf/addressbook_conan/addressbook_conan.qbs 0
+
+ Install Conan dependencies and run the QbsDeps generator from the \c addressbook_conan dir:
+ \code
+ $ conan install . -g=QbsDeps --output-folder=build --build missing
+ \endcode
+ This will create the \c{./build/qbs-deps} directory contaning files for provider. Now you can
+ pass the conan install directory to the provider:
+ \code
+ $ qbs moduleProviders.conan.installDirectory:build
+ \endcode
+ You should see the following output if everything is correct:
+ \code
+ Build graph does not yet exist for configuration 'default'. Starting from scratch.
+ Resolving project for configuration default
+ Setting up Conan module 'protobuflib'
+ Setting up Conan module 'zlib'
+ ...
+ Build done for configuration default.
+ \endcode
+*/
+
+/*!
+ \qmlproperty string conan::installDirectory
+
+ The path to the conan install installDirectory.
+
+ \QBS searches for files created by the QbsDeps generator in that directory.
+
+ If not set, the provider will not be run.
+
+ \defaultvalue undefined
+*/
diff --git a/doc/reference/module-providers/qbspkgconfig-module-provider.qdoc b/doc/reference/module-providers/qbspkgconfig-module-provider.qdoc
index b5d720d01..a7f6fe6b7 100644
--- a/doc/reference/module-providers/qbspkgconfig-module-provider.qdoc
+++ b/doc/reference/module-providers/qbspkgconfig-module-provider.qdoc
@@ -99,6 +99,17 @@
*/
/*!
+ \qmlproperty stringList qbspkgconfig::executableNames
+
+ The names of the \c pkg-config executable to search for.
+
+ Note that since newer distributions use \l{http://pkgconf.org}{pkgconf} by default, it has
+ higher priority over \c pkg-config.
+
+ \defaultvalue \c{["pkgconf", "pkg-config"]}
+*/
+
+/*!
\qmlproperty path qbspkgconfig::sysroot
Set this property if you need to overwrite the default search sysroot path used by
diff --git a/doc/reference/modules/flatbuf-c-module.qdoc b/doc/reference/modules/flatbuf-c-module.qdoc
new file mode 100644
index 000000000..d486ab3bf
--- /dev/null
+++ b/doc/reference/modules/flatbuf-c-module.qdoc
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype flatbuf.c
+ \inqmlmodule QbsModules
+ \since Qbs 2.4
+
+ \brief Provides support for \l{https://google.github.io/flatbuffers/}{FlatBuffers} for the
+ C language.
+
+ The \c flatbuf.c module provides support for generating C headers
+ and sources from flatbuffers definition files using the \c flatcc tool.
+
+ \section2 Relevant File Tags
+
+ \table
+ \header
+ \li Tag
+ \li Auto-tagged File Names
+ \li Since
+ \li Description
+ \row
+ \li \c{"flatbuffers.input"}
+ \li \c{*.fbs}
+ \li 2.4.0
+ \li Source files with this tag are considered inputs to the \c flatcc compiler.
+ \endtable
+
+ \section2 Dependencies
+ This module depends on the \c flatcc module which can be created via the \l{conan}{Conan}
+ module provider.
+*/
+
+/*!
+ \qmlproperty string flatbuf.c::compilerName
+
+ The name of the \c flatcc binary.
+
+ \defaultvalue \c "flatcc"
+*/
+
+/*!
+ \qmlproperty string flatbuf.c::compilerPath
+
+ The path to the \c flatcc binary.
+
+ Use this property to override the auto-detected location.
+
+ \defaultvalue \c auto-detected
+*/
+
+/*!
+ \qmlproperty pathList flatbuf.c::importPaths
+
+ The list of import paths that are passed to the \c flatcc tool via the \c -I option.
+
+ \defaultvalue \c []
+*/
diff --git a/doc/reference/modules/flatbuf-cpp-module.qdoc b/doc/reference/modules/flatbuf-cpp-module.qdoc
new file mode 100644
index 000000000..a4b6915ab
--- /dev/null
+++ b/doc/reference/modules/flatbuf-cpp-module.qdoc
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \qmltype flatbuf.cpp
+ \inqmlmodule QbsModules
+ \since Qbs 2.4
+
+ \brief Provides support for \l{https://google.github.io/flatbuf/}{flatbuf} for the
+ C++ language.
+
+ The \c flatbuf.cpp module provides support for generating C++ headers
+ and sources from flatbuf definition files using the \c flatc tool.
+
+ A simple qbs file that uses flatbuf can be written as follows:
+ \code
+ CppApplication {
+ Depends { name: "flatbuf.cpp" }
+ files: ["foo.fbs", "main.cpp"]
+ }
+ \endcode
+ A generated header now can be included in the C++ sources:
+ \code
+ #include <foo_generated.h>
+
+ int main(int argc, char* argv[]) {
+ flatbuf::FlatBufferBuilder builder;
+
+ auto foo = QbsTest::CreateFoo(builder, 42);
+ return 0;
+ }
+ \endcode
+
+ \section2 Relevant File Tags
+
+ \table
+ \header
+ \li Tag
+ \li Auto-tagged File Names
+ \li Since
+ \li Description
+ \row
+ \li \c{"flatbuf.input"}
+ \li \c{*.fbs}
+ \li 2.4.0
+ \li Source files with this tag are considered inputs to the \c flatc compiler.
+ \endtable
+
+ \section2 Dependencies
+ This module depends on the \c flatbuffers module which can be created via the \l{conan}{Conan}
+ module provider.
+*/
+
+/*!
+ \qmlproperty string flatbuf.cpp::compilerName
+
+ The name of the \c flatc binary.
+
+ \defaultvalue \c "flatc"
+*/
+
+/*!
+ \qmlproperty string flatbuf.cpp::compilerPath
+
+ The path to the \c flatc binary.
+
+ Use this property to override the auto-detected location.
+
+ \defaultvalue \c auto-detected
+*/
+
+/*!
+ \qmlproperty string flatbuf.cpp::filenameExtension
+
+ The extension appended to the generated file names. If not specified, the default extension
+ (\c ".h") is used.
+
+ This property corresponds to the \c --filename-ext option of the \c flatc tool.
+
+ \nodefaultvalue
+*/
+
+/*!
+ \qmlproperty string flatbuf.cpp::filenameSuffix
+
+ The suffix appended to the generated file names. If not specified, the default suffix
+ (\c "_generated") is used.
+
+ This property corresponds to the \c --filename-suffix option of the \c flatc tool.
+
+ \nodefaultvalue
+*/
+
+/*!
+ \qmlproperty pathList flatbuf.cpp::importPaths
+
+ The list of import paths that are passed to the \c flatc tool via the \c -I option.
+
+ \defaultvalue \c []
+*/
+
+/*!
+ \qmlproperty string flatbuf.cpp::includePrefix
+
+ Prefix path prepended to any generated include statements.
+
+ This property corresponds to the \c --include-prefix option of the \c flatc tool.
+
+ \nodefaultvalue
+*/
+
+/*!
+ \qmlproperty bool flatbuf.cpp::keepPrefix
+
+ Whether to keep original prefix of schema include statement.
+
+ This property corresponds to the \c --keep-prefix option of the \c flatc tool.
+
+ \defaultvalue \c false
+*/
diff --git a/doc/reference/modules/qt-core-module.qdoc b/doc/reference/modules/qt-core-module.qdoc
index 6aedf2a69..85d1c66c6 100644
--- a/doc/reference/modules/qt-core-module.qdoc
+++ b/doc/reference/modules/qt-core-module.qdoc
@@ -174,6 +174,14 @@
*/
/*!
+ \qmlproperty stringList Qt.core::disabledFeatures
+
+ Corresponds to cmake's \c QT_DISABLED_PUBLIC_FEATURES variable.
+
+ \readonly
+*/
+
+/*!
\qmlproperty path Qt.core::docPath
The path in which the Qt documentation is located.
@@ -182,6 +190,14 @@
*/
/*!
+ \qmlproperty stringList Qt.core::enabledFeatures
+
+ Corresponds to cmake's \c QT_ENABLED_PUBLIC_FEATURES variable.
+
+ \readonly
+*/
+
+/*!
\qmlproperty bool Qt.core::enableKeywords
Set this property to \c false if you do not want Qt to define the symbols
diff --git a/doc/tutorial.qdoc b/doc/tutorial.qdoc
index 681d84758..b17cf4faf 100644
--- a/doc/tutorial.qdoc
+++ b/doc/tutorial.qdoc
@@ -44,6 +44,7 @@
\li \l{tutorial-6.html}{Project Properties}
\li \l{tutorial-7.html}{Buildconfig Module}
\li \l{tutorial-8.html}{Configurable Library}
+ \li \l{tutorial-9.html}{Version Header}
\endlist
*/
@@ -481,7 +482,7 @@
/*!
\previouspage tutorial-7.html
\page tutorial-8.html
- \nextpage howtos.html
+ \nextpage tutorial-9.html
\title Configurable Library
@@ -551,3 +552,96 @@
libmylib.a
\endcode
*/
+
+/*!
+ \previouspage tutorial-8.html
+ \page tutorial-9.html
+ \nextpage howtos.html
+
+ \title Version Header
+
+ To create new files, such as version headers, during the build, use \l{Rules}. Every command
+ \QBS executes, such as compile or linker commands, is described by a corresponding Rule in a
+ Module or a Product.
+
+ In this section, we will create a simple header with a string constant based on the variable
+ in our project.
+
+ First, we add this variable to our \c mybuildconfig module:
+ \snippet ../tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs 0
+
+ Next, we create a new file, \c{version.h.in}, located in the \c{version-header} directory. This
+ file contains the template for our header:
+ \snippet ../tutorial/chapter-9/version-header/version.h.in 0
+
+ Now we create a file called \c{version-header.qbs} in the same directory. This file contains
+ a \l{Product} with a \l{Rule} that turns the \c{version.h.in} into a real header.
+ Let's go through the contents of the file:
+ \snippet ../tutorial/chapter-9/version-header/version-header.qbs 0
+
+ First, we import \l{TextFile Service}{TextFile}. We will need this class to read the template
+ and write the resulting header. Second, we declare a new \l{Product} named \c{"version_header"}
+ and with the \c{"hpp"} type. This is the type of the artifact we will create in the Rule.
+ Third, we add the dependency on the \c mybuildconfig module to use the new
+ \c mybuildconfig.productVersion variable.
+
+ We also add a \l{Group} with the template file and assign the \c{version_h_in} tag to the file:
+ \snippet ../tutorial/chapter-9/version-header/version-header.qbs 1
+
+ \QBS Rules work with file tags, instead of working with files directly, which makes
+ it easy to reuse rules. The name of the tag is chosen arbitrarily here. We could use the name
+ of the file as a tag, but to avoid confusion between file name and file tag, we use underscores
+ in the tag instead of dots.
+
+ Now we can create a Rule itself:
+ \snippet ../tutorial/chapter-9/version-header/version-header.qbs 2
+ Here, we specify that our Rule takes files tagged as \c "version_h_in" and produces an
+ \l{Artifact} with the name \c "version.h" and tagged \c "hpp". By default, files are created in
+ the \l{Product::destinationDirectory}{Product.destinationDirectory} folder. We add the \c "hpp"
+ tag for the header as this is the tag the \l{cpp}{cpp module} uses for headers. That way, \QBS
+ can track changes and process our generated file the same way it treats all other
+ headers. Note that earlier we set the product type to \c "hpp" as well. \QBS requires that
+ artifact type should match the product type directly or be accessible via the chain of Rules.
+ Otherwise, the Rule won't be executed. For details, see the \l{Rules and Product Types}
+ section.
+
+ The actual code generation happens in the \l{Rule::prepare}{Rule.prepare} script:
+ \snippet ../tutorial/chapter-9/version-header/version-header.qbs 3
+
+ In this script, we create a \l {JavaScriptCommand} object and set some meta properties, such as
+ the description and highlight. For details about Commands, see
+ \l{Command and JavaScriptCommand}. In the sourceCode variable, we create a JavaScript
+ function that opens the \l{The inputs and outputs Variables}{input file}, reads its content
+ using the \l{TextFile Service}{TextFile} object, replaces the \c "${PRODUCT_VERSION}"
+ placeholder with the actual value in the \c product.mybuildconfig.productVersion variable, and
+ writes the resulting content into the \l{The inputs and outputs Variables}{output file}.
+
+ Finally, we export the \l{Product::buildDirectory}{exportingProduct.buildDirectory} so that
+ products that depend on this product can include our generated header:
+
+ \snippet ../tutorial/chapter-9/version-header/version-header.qbs 4
+
+ The full content of the file should look like this:
+
+ \snippet ../tutorial/chapter-9/version-header/version-header.qbs 5
+
+ Let's now add our Product into the root project so \QBS will be aware of it:
+ \snippet ../tutorial/chapter-9/myproject.qbs 0
+
+ We also need to add the dependency on the \c "version_header" to our application:
+ \snippet ../tutorial/chapter-9/app/app.qbs 0
+
+ Now we can include the header in the \c main.c file and print the contents of the string
+ constant:
+
+ \snippet ../tutorial/chapter-9/app/main.c 0
+
+ Let's try and run our application. You should see something like this:
+ \code
+ $ qbs run -p "My Application"
+ Starting target. Full command line: .../default/install-root/usr/local/bin/myapp
+ Hello, world
+ Hello from library
+ ProductVersion = 1.0.0
+ \endcode
+*/
diff --git a/examples/flatbuffers/.clang-format b/examples/flatbuffers/.clang-format
new file mode 100644
index 000000000..47a38a93f
--- /dev/null
+++ b/examples/flatbuffers/.clang-format
@@ -0,0 +1,2 @@
+DisableFormat: true
+SortIncludes: Never
diff --git a/examples/flatbuffers/monster-c/conanfile.txt b/examples/flatbuffers/monster-c/conanfile.txt
new file mode 100644
index 000000000..613119ec2
--- /dev/null
+++ b/examples/flatbuffers/monster-c/conanfile.txt
@@ -0,0 +1,6 @@
+[requires]
+flatcc/0.6.1
+[tool_requires]
+flatcc/0.6.1
+[generators]
+QbsDeps
diff --git a/examples/flatbuffers/monster-c/monster-c.qbs b/examples/flatbuffers/monster-c/monster-c.qbs
new file mode 100644
index 000000000..e6abe749e
--- /dev/null
+++ b/examples/flatbuffers/monster-c/monster-c.qbs
@@ -0,0 +1,12 @@
+CppApplication {
+ Depends { name: "flatbuf.c"; required: false }
+
+ name: "monster_c"
+ consoleApplication: true
+ condition: flatbuf.c.present && qbs.targetPlatform === qbs.hostPlatform
+
+ files: [
+ "monster.c",
+ "../shared/monster.fbs"
+ ]
+}
diff --git a/examples/flatbuffers/monster-c/monster.c b/examples/flatbuffers/monster-c/monster.c
new file mode 100644
index 000000000..6bf49d628
--- /dev/null
+++ b/examples/flatbuffers/monster-c/monster.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2019 dvidelabs.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Example on how to build a Monster FlatBuffer.
+
+
+// Note: while some older C89 compilers are supported when
+// -DFLATCC_PORTABLE is defined, this particular sample is known not to
+// not work with MSVC 2010 (MSVC 2013 is OK) due to inline variable
+// declarations. These are easily move to the start of code blocks, but
+// since we follow the step-wise tutorial, it isn't really practical
+// in this case. The comment style is technically also in violation of C89.
+
+
+#include "monster_builder.h"
+// <string.h> and <assert.h> already included.
+
+// Convenient namespace macro to manage long namespace prefix.
+// The ns macro makes it possible to write `ns(Monster_create(...))`
+// instead of `MyGame_Sample_Monster_create(...)`
+#undef ns
+#define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema.
+
+// A helper to simplify creating vectors from C-arrays.
+#define c_vec_len(V) (sizeof(V)/sizeof((V)[0]))
+
+// This allows us to verify result in optimized builds.
+#define test_assert(x) do { if (!(x)) { assert(0); return -1; }} while (0)
+
+// Bottom-up approach where we create child objects and store these
+// in temporary references before a parent object is created with
+// these references.
+int create_monster_bottom_up(flatcc_builder_t *B, int flexible)
+{
+ flatbuffers_string_ref_t weapon_one_name = flatbuffers_string_create_str(B, "Sword");
+ uint16_t weapon_one_damage = 3;
+
+ flatbuffers_string_ref_t weapon_two_name = flatbuffers_string_create_str(B, "Axe");
+ uint16_t weapon_two_damage = 5;
+
+ // Use the `MyGame_Sample_Weapon_create` shortcut to create Weapons
+ // with all the fields set.
+ //
+ // In the C-API, verbs (here create) always follow the type name
+ // (here Weapon), prefixed by the namespace (here MyGame_Sample_):
+ // MyGame_Sample_Weapon_create(...), or ns(Weapone_create(...)).
+ ns(Weapon_ref_t) sword = ns(Weapon_create(B, weapon_one_name, weapon_one_damage));
+ ns(Weapon_ref_t) axe = ns(Weapon_create(B, weapon_two_name, weapon_two_damage));
+
+ // Serialize a name for our monster, called "Orc".
+ // The _str suffix indicates the source is an ascii-z string.
+ flatbuffers_string_ref_t name = flatbuffers_string_create_str(B, "Orc");
+
+ // Create a `vector` representing the inventory of the Orc. Each number
+ // could correspond to an item that can be claimed after he is slain.
+ uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ flatbuffers_uint8_vec_ref_t inventory;
+ // `c_vec_len` is the convenience macro we defined earlier.
+ inventory = flatbuffers_uint8_vec_create(B, treasure, c_vec_len(treasure));
+
+ // Here we use a top-down approach locally to build a Weapons vector
+ // in-place instead of creating a temporary external vector to use
+ // as argument like we did with the `inventory` earlier on, but the
+ // overall approach is still bottom-up.
+ ns(Weapon_vec_start(B));
+ ns(Weapon_vec_push(B, sword));
+ ns(Weapon_vec_push(B, axe));
+ ns(Weapon_vec_ref_t) weapons = ns(Weapon_vec_end(B));
+
+
+ // Create a `Vec3`, representing the Orc's position in 3-D space.
+ ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f };
+
+
+ // Set his hit points to 300 and his mana to 150.
+ uint16_t hp = 300;
+ // The default value is 150, so we will never store this field.
+ uint16_t mana = 150;
+
+ // Create the equipment union. In the C++ language API this is given
+ // as two arguments to the create call, or as two separate add
+ // operations for the type and the table reference. Here we create
+ // a single union value that carries both the type and reference.
+ ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe));
+
+ if (!flexible) {
+ // Finally, create the monster using the `Monster_create` helper function
+ // to set all fields.
+ //
+ // Note that the Equipment union only take up one argument in C, where
+ // C++ takes a type and an object argument.
+ ns(Monster_create_as_root(B, &pos, mana, hp, name, inventory, ns(Color_Red),
+ weapons, equipped));
+
+ // Unlike C++ we do not use a Finish call. Instead we use the
+ // `create_as_root` action which has better type safety and
+ // simplicity.
+ //
+ // However, we can also express this as:
+ //
+ // ns(Monster_ref_t) orc = ns(Monster_create(B, ...));
+ // flatcc_builder_buffer_create(orc);
+ //
+ // In this approach the function should return the orc and
+ // let a calling function handle the flatcc_buffer_create call
+ // for a more composable setup that is also able to create child
+ // monsters. In general, `flatcc_builder` calls are best isolated
+ // in a containing driver function.
+
+ } else {
+
+ // A more flexible approach where we mix bottom-up and top-down
+ // style. We still create child objects first, but then create
+ // a top-down style monster object that we can manipulate in more
+ // detail.
+
+ // It is important to pair `start_as_root` with `end_as_root`.
+ ns(Monster_start_as_root(B));
+ ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f));
+ // or alternatively
+ //ns(Monster_pos_add(&pos);
+
+ ns(Monster_hp_add(B, hp));
+ // Notice that `Monser_name_add` adds a string reference unlike the
+ // add_str and add_strn variants.
+ ns(Monster_name_add(B, name));
+ ns(Monster_inventory_add(B, inventory));
+ ns(Monster_color_add(B, ns(Color_Red)));
+ ns(Monster_weapons_add(B, weapons));
+ ns(Monster_equipped_add(B, equipped));
+ // Complete the monster object and make it the buffer root object.
+ ns(Monster_end_as_root(B));
+
+ // We could also drop the `as_root` suffix from Monster_start/end(B)
+ // and add the table as buffer root later:
+ //
+ // ns(Monster_ref_t) orc = ns(Monster_start(B));
+ // ...
+ // ns(Monster_ref_t) orc = ns(Monster_end(B));
+ // flatcc_builder_buffer_create(orc);
+ //
+ // It is best to keep the `flatcc_builder` calls in a containing
+ // driver function for modularity.
+ }
+ return 0;
+}
+
+// Alternative top-down approach where parent objects are created before
+// their children. We only need to save one reference because the `axe`
+// object is used in two places effectively making the buffer object
+// graph a DAG.
+int create_monster_top_down(flatcc_builder_t *B)
+{
+ uint8_t treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ size_t treasure_count = c_vec_len(treasure);
+ ns(Weapon_ref_t) axe;
+
+ // NOTE: if we use end_as_root, we MUST also start as root.
+ ns(Monster_start_as_root(B));
+ ns(Monster_pos_create(B, 1.0f, 2.0f, 3.0f));
+ ns(Monster_hp_add(B, 300));
+ //ns(Monster_mana_add(B, 150));
+ // We use create_str instead of add because we have no existing string reference.
+ ns(Monster_name_create_str(B, "Orc"));
+ // Again we use create because we no existing vector object, only a C-array.
+ ns(Monster_inventory_create(B, treasure, treasure_count));
+ ns(Monster_color_add(B, ns(Color_Red)));
+ if (1) {
+ ns(Monster_weapons_start(B));
+ ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Sword"), 3));
+ // We reuse the axe object later. Note that we dereference a pointer
+ // because push always returns a short-term pointer to the stored element.
+ // We could also have created the axe object first and simply pushed it.
+ axe = *ns(Monster_weapons_push_create(B, flatbuffers_string_create_str(B, "Axe"), 5));
+ ns(Monster_weapons_end(B));
+ } else {
+ // We can have more control with the table elements added to a vector:
+ //
+ ns(Monster_weapons_start(B));
+ ns(Monster_weapons_push_start(B));
+ ns(Weapon_name_create_str(B, "Sword"));
+ ns(Weapon_damage_add(B, 3));
+ ns(Monster_weapons_push_end(B));
+ ns(Monster_weapons_push_start(B));
+ ns(Weapon_name_create_str(B, "Axe"));
+ ns(Weapon_damage_add(B, 5));
+ axe = *ns(Monster_weapons_push_end(B));
+ ns(Monster_weapons_end(B));
+ }
+ // Unions can get their type by using a type-specific add/create/start method.
+ ns(Monster_equipped_Weapon_add(B, axe));
+
+ ns(Monster_end_as_root(B));
+ return 0;
+}
+
+// This isn't strictly needed because the builder already included the reader,
+// but we would need it if our reader were in a separate file.
+#include "monster_reader.h"
+
+#undef ns
+#define ns(x) FLATBUFFERS_WRAP_NAMESPACE(MyGame_Sample, x) // Specified in the schema.
+
+int access_monster_buffer(const void *buffer)
+{
+ // Note that we use the `table_t` suffix when reading a table object
+ // as opposed to the `ref_t` suffix used during the construction of
+ // the buffer.
+ ns(Monster_table_t) monster = ns(Monster_as_root(buffer));
+
+ // Note: root object pointers are NOT the same as the `buffer` pointer.
+
+ // Make sure the buffer is accessible.
+ test_assert(monster != 0);
+
+ uint16_t hp = ns(Monster_hp(monster));
+ uint16_t mana = ns(Monster_mana(monster));
+ // This is just a const char *, but it also supports a fast length operation.
+ flatbuffers_string_t name = ns(Monster_name(monster));
+ size_t name_len = flatbuffers_string_len(name);
+
+ test_assert(hp == 300);
+ // Since 150 is the default, we are reading a value that wasn't stored.
+ test_assert(mana == 150);
+ test_assert(0 == strcmp(name, "Orc"));
+ test_assert(name_len == strlen("Orc"));
+
+ int hp_present = ns(Monster_hp_is_present(monster)); // 1
+ int mana_present = ns(Monster_mana_is_present(monster)); // 0
+ test_assert(hp_present);
+ test_assert(!mana_present);
+
+ ns(Vec3_struct_t) pos = ns(Monster_pos(monster));
+ // Make sure pos has been set.
+ test_assert(pos != 0);
+ float x = ns(Vec3_x(pos));
+ float y = ns(Vec3_y(pos));
+ float z = ns(Vec3_z(pos));
+
+ // The literal `f` suffix is important because double literals does
+ // not always map cleanly to 32-bit represention even with only a few digits:
+ // `1.0 == 1.0f`, but `3.2 != 3.2f`.
+ test_assert(x == 1.0f);
+ test_assert(y == 2.0f);
+ test_assert(z == 3.0f);
+
+ // We can also read the position into a C-struct. We have to copy
+ // because we generally do not know if the native endian format
+ // matches the one stored in the buffer (pe: protocol endian).
+ ns(Vec3_t) pos_vec;
+ // `pe` indicates endian conversion from protocol to native.
+ ns(Vec3_copy_from_pe(&pos_vec, pos));
+ test_assert(pos_vec.x == 1.0f);
+ test_assert(pos_vec.y == 2.0f);
+ test_assert(pos_vec.z == 3.0f);
+
+ // This is a const uint8_t *, but it shouldn't be accessed directly
+ // to ensure proper endian conversion. However, uint8 (ubyte) are
+ // not sensitive endianness, so we *could* have accessed it directly.
+ // The compiler likely optimizes this so that it doesn't matter.
+ flatbuffers_uint8_vec_t inv = ns(Monster_inventory(monster));
+ size_t inv_len = flatbuffers_uint8_vec_len(inv);
+ // Make sure the inventory has been set.
+ test_assert(inv != 0);
+ // If `inv` were absent, the length would 0, so the above test is redundant.
+ test_assert(inv_len == 10);
+ // Index 0 is the first, index 2 is the third.
+ // NOTE: C++ uses the `Get` terminology for vector elemetns, C use `at`.
+ uint8_t third_item = flatbuffers_uint8_vec_at(inv, 2);
+ test_assert(third_item == 2);
+
+ ns(Weapon_vec_t) weapons = ns(Monster_weapons(monster));
+ size_t weapons_len = ns(Weapon_vec_len(weapons));
+ test_assert(weapons_len == 2);
+ // We can use `const char *` instead of `flatbuffers_string_t`.
+ const char *second_weapon_name = ns(Weapon_name(ns(Weapon_vec_at(weapons, 1))));
+ uint16_t second_weapon_damage = ns(Weapon_damage(ns(Weapon_vec_at(weapons, 1))));
+ test_assert(second_weapon_name != 0 && strcmp(second_weapon_name, "Axe") == 0);
+ test_assert(second_weapon_damage == 5);
+
+ // Access union type field.
+ if (ns(Monster_equipped_type(monster)) == ns(Equipment_Weapon)) {
+ // Cast to appropriate type:
+ // C does not require the cast to Weapon_table_t, but C++ does.
+ ns(Weapon_table_t) weapon = (ns(Weapon_table_t)) ns(Monster_equipped(monster));
+ const char *weapon_name = ns(Weapon_name(weapon));
+ uint16_t weapon_damage = ns(Weapon_damage(weapon));
+
+ test_assert(0 == strcmp(weapon_name, "Axe"));
+ test_assert(weapon_damage == 5);
+ }
+ return 0;
+}
+
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ // Create a `FlatBufferBuilder`, which will be used to create our
+ // monsters' FlatBuffers.
+ flatcc_builder_t builder;
+ void *buf;
+ size_t size;
+
+ // Silence warnings.
+ (void)argc;
+ (void)argv;
+
+ // Initialize the builder object.
+ flatcc_builder_init(&builder);
+ test_assert(0 == create_monster_bottom_up(&builder, 0));
+
+ // Allocate and extract a readable buffer from internal builder heap.
+ // The returned buffer must be deallocated using `free`.
+ // NOTE: Finalizing the buffer does NOT change the builder, it
+ // just creates a snapshot of the builder content.
+ // NOTE2: finalize_buffer uses malloc while finalize_aligned_buffer
+ // uses a portable aligned allocation method. Often the malloc
+ // version is sufficient, but won't work for all schema on all
+ // systems. If the buffer is written to disk or network, but not
+ // accessed in memory, `finalize_buffer` is also sufficient.
+ buf = flatcc_builder_finalize_aligned_buffer(&builder, &size);
+ //buf = flatcc_builder_finalize_buffer(&builder, &size);
+
+ // We now have a FlatBuffer we can store on disk or send over a network.
+ // ** file/network code goes here :) **
+ // Instead, we're going to access it right away (as if we just received it).
+ //access_monster_buffer(buf);
+
+ // prior to v0.5.0, use `aligned_free`
+ flatcc_builder_aligned_free(buf);
+ //free(buf);
+ //
+ // The builder object can optionally be reused after a reset which
+ // is faster than creating a new builder. Subsequent use might
+ // entirely avoid temporary allocations until finalizing the buffer.
+ flatcc_builder_reset(&builder);
+ test_assert(0 == create_monster_bottom_up(&builder, 1));
+ buf = flatcc_builder_finalize_aligned_buffer(&builder, &size);
+ access_monster_buffer(buf);
+ flatcc_builder_aligned_free(buf);
+ flatcc_builder_reset(&builder);
+ create_monster_top_down(&builder);
+ buf = flatcc_builder_finalize_buffer(&builder, &size);
+ test_assert(0 == access_monster_buffer(buf));
+ free(buf);
+ // Eventually the builder must be cleaned up:
+ flatcc_builder_clear(&builder);
+
+ printf("The FlatBuffer was successfully created and accessed!\n");
+
+ return 0;
+}
+
diff --git a/examples/flatbuffers/monster-cpp/conanfile.txt b/examples/flatbuffers/monster-cpp/conanfile.txt
new file mode 100644
index 000000000..188da5897
--- /dev/null
+++ b/examples/flatbuffers/monster-cpp/conanfile.txt
@@ -0,0 +1,6 @@
+[requires]
+flatbuffers/24.3.25
+[tool_requires]
+flatbuffers/24.3.25
+[generators]
+QbsDeps
diff --git a/examples/flatbuffers/monster-cpp/monster-cpp.qbs b/examples/flatbuffers/monster-cpp/monster-cpp.qbs
new file mode 100644
index 000000000..fdcc3fcfd
--- /dev/null
+++ b/examples/flatbuffers/monster-cpp/monster-cpp.qbs
@@ -0,0 +1,12 @@
+CppApplication {
+ Depends { name: "flatbuf.cpp"; required: false }
+
+ name: "monster_cpp"
+ consoleApplication: true
+ condition: flatbuf.cpp.present && qbs.targetPlatform === qbs.hostPlatform
+
+ files: [
+ "monster.cpp",
+ "../shared/monster.fbs"
+ ]
+}
diff --git a/examples/flatbuffers/monster-cpp/monster.cpp b/examples/flatbuffers/monster-cpp/monster.cpp
new file mode 100644
index 000000000..d2348c820
--- /dev/null
+++ b/examples/flatbuffers/monster-cpp/monster.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "monster_generated.h" // Already includes "flatbuffers/flatbuffers.h".
+
+using namespace MyGame::Sample;
+
+// Example how to use FlatBuffers to create and read binary buffers.
+
+int main(int /*argc*/, const char * /*argv*/ []) {
+ // Build up a serialized buffer algorithmically:
+ flatbuffers::FlatBufferBuilder builder;
+
+ // First, lets serialize some weapons for the Monster: A 'sword' and an 'axe'.
+ auto weapon_one_name = builder.CreateString("Sword");
+ short weapon_one_damage = 3;
+
+ auto weapon_two_name = builder.CreateString("Axe");
+ short weapon_two_damage = 5;
+
+ // Use the `CreateWeapon` shortcut to create Weapons with all fields set.
+ auto sword = CreateWeapon(builder, weapon_one_name, weapon_one_damage);
+ auto axe = CreateWeapon(builder, weapon_two_name, weapon_two_damage);
+
+ // Create a FlatBuffer's `vector` from the `std::vector`.
+ std::vector<flatbuffers::Offset<Weapon>> weapons_vector;
+ weapons_vector.push_back(sword);
+ weapons_vector.push_back(axe);
+ auto weapons = builder.CreateVector(weapons_vector);
+
+ // Second, serialize the rest of the objects needed by the Monster.
+ auto position = Vec3(1.0f, 2.0f, 3.0f);
+
+ auto name = builder.CreateString("MyMonster");
+
+ unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ auto inventory = builder.CreateVector(inv_data, 10);
+
+ // Shortcut for creating monster with all fields set:
+ auto orc = CreateMonster(builder, &position, 150, 80, name, inventory,
+ Color_Red, weapons, Equipment_Weapon, axe.Union());
+
+ builder.Finish(orc); // Serialize the root of the object.
+
+ // We now have a FlatBuffer we can store on disk or send over a network.
+
+ // ** file/network code goes here :) **
+ // access builder.GetBufferPointer() for builder.GetSize() bytes
+
+ // Instead, we're going to access it right away (as if we just received it).
+
+ // Get access to the root:
+ auto monster = GetMonster(builder.GetBufferPointer());
+
+ // Get and test some scalar types from the FlatBuffer.
+ assert(monster->hp() == 80);
+ assert(monster->mana() == 150); // default
+ assert(monster->name()->str() == "MyMonster");
+
+ // Get and test a field of the FlatBuffer's `struct`.
+ auto pos = monster->pos();
+ assert(pos);
+ assert(pos->z() == 3.0f);
+ (void)pos;
+
+ // Get a test an element from the `inventory` FlatBuffer's `vector`.
+ auto inv = monster->inventory();
+ assert(inv);
+ assert(inv->Get(9) == 9);
+ (void)inv;
+
+ // Get and test the `weapons` FlatBuffers's `vector`.
+ std::string expected_weapon_names[] = { "Sword", "Axe" };
+ short expected_weapon_damages[] = { 3, 5 };
+ auto weps = monster->weapons();
+ for (unsigned int i = 0; i < weps->size(); i++) {
+ assert(weps->Get(i)->name()->str() == expected_weapon_names[i]);
+ assert(weps->Get(i)->damage() == expected_weapon_damages[i]);
+ }
+ (void)expected_weapon_names;
+ (void)expected_weapon_damages;
+
+ // Get and test the `Equipment` union (`equipped` field).
+ assert(monster->equipped_type() == Equipment_Weapon);
+ auto equipped = static_cast<const Weapon *>(monster->equipped());
+ assert(equipped->name()->str() == "Axe");
+ assert(equipped->damage() == 5);
+ (void)equipped;
+
+ printf("The FlatBuffer was successfully created and verified!\n");
+}
diff --git a/examples/flatbuffers/shared/monster.fbs b/examples/flatbuffers/shared/monster.fbs
new file mode 100644
index 000000000..247b81771
--- /dev/null
+++ b/examples/flatbuffers/shared/monster.fbs
@@ -0,0 +1,32 @@
+// Example IDL file for our monster's schema.
+
+namespace MyGame.Sample;
+
+enum Color:byte { Red = 0, Green, Blue = 2 }
+
+union Equipment { Weapon } // Optionally add more tables.
+
+struct Vec3 {
+ x:float;
+ y:float;
+ z:float;
+}
+
+table Monster {
+ pos:Vec3;
+ mana:short = 150;
+ hp:short = 100;
+ name:string;
+ friendly:bool = false (deprecated);
+ inventory:[ubyte];
+ color:Color = Blue;
+ weapons:[Weapon];
+ equipped:Equipment;
+}
+
+table Weapon {
+ name:string;
+ damage:short;
+}
+
+root_type Monster;
diff --git a/examples/protobuf/addressbook_conan/addressbook_conan.qbs b/examples/protobuf/addressbook_conan/addressbook_conan.qbs
new file mode 100644
index 000000000..c496d14bd
--- /dev/null
+++ b/examples/protobuf/addressbook_conan/addressbook_conan.qbs
@@ -0,0 +1,20 @@
+//![0]
+
+import qbs.Host
+
+CppApplication {
+ consoleApplication: true
+ condition: protobuf.cpp.present && qbs.targetPlatform === Host.platform()
+
+ Depends { name: "cpp" }
+ cpp.minimumMacosVersion: "11.0"
+
+ Depends { name: "protobuf.cpp"; required: false }
+
+ files: [
+ "../shared/addressbook.proto",
+ "main.cpp",
+ ]
+ qbsModuleProviders: "conan"
+}
+//![0]
diff --git a/examples/protobuf/addressbook_conan/conanfile.txt b/examples/protobuf/addressbook_conan/conanfile.txt
new file mode 100644
index 000000000..e7d849b1a
--- /dev/null
+++ b/examples/protobuf/addressbook_conan/conanfile.txt
@@ -0,0 +1,6 @@
+[requires]
+protobuf/3.21.12
+[tool_requires]
+protobuf/3.21.12
+[generators]
+QbsDeps
diff --git a/examples/protobuf/addressbook_conan/main.cpp b/examples/protobuf/addressbook_conan/main.cpp
new file mode 100644
index 000000000..76e1e0d74
--- /dev/null
+++ b/examples/protobuf/addressbook_conan/main.cpp
@@ -0,0 +1,180 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <ctime>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include <google/protobuf/util/time_util.h>
+#pragma GCC diagnostic pop
+#else
+#include <google/protobuf/util/time_util.h>
+#endif // __GNUC__
+
+#include "addressbook.pb.h"
+
+using google::protobuf::util::TimeUtil;
+
+int printUsage(char *argv0)
+{
+ std::cerr << "Usage: " << argv0 << "add|list ADDRESS_BOOK_FILE" << std::endl;
+ return -1;
+}
+
+std::string readString(const std::string &promt)
+{
+ std::string result;
+ std::cout << promt;
+ std::getline(std::cin, result);
+ return result;
+}
+
+// This function fills in a Person message based on user input.
+void promptForAddress(tutorial::Person *person)
+{
+ std::cout << "Enter person ID number: ";
+ int id;
+ std::cin >> id;
+ person->set_id(id);
+ std::cin.ignore(256, '\n');
+
+ *person->mutable_name() = readString("Enter name: ");
+
+ const auto email = readString("Enter email address (blank for none): ");
+ if (!email.empty())
+ person->set_email(email);
+
+ while (true) {
+ const auto number = readString("Enter a phone number (or leave blank to finish): ");
+ if (number.empty())
+ break;
+
+ tutorial::Person::PhoneNumber *phone_number = person->add_phones();
+ phone_number->set_number(number);
+
+ const auto type = readString("Is this a mobile, home, or work phone? ");
+ if (type == "mobile")
+ phone_number->set_type(tutorial::Person::MOBILE);
+ else if (type == "home")
+ phone_number->set_type(tutorial::Person::HOME);
+ else if (type == "work")
+ phone_number->set_type(tutorial::Person::WORK);
+ else
+ std::cout << "Unknown phone type. Using default." << std::endl;
+ }
+ *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
+}
+
+// Iterates though all people in the AddressBook and prints info about them.
+void listPeople(const tutorial::AddressBook &address_book)
+{
+ for (int i = 0; i < address_book.people_size(); i++) {
+ const tutorial::Person &person = address_book.people(i);
+
+ std::cout << "Person ID: " << person.id() << std::endl;
+ std::cout << " Name: " << person.name() << std::endl;
+ if (!person.email().empty()) {
+ std::cout << " E-mail address: " << person.email() << std::endl;
+ }
+
+ for (int j = 0; j < person.phones_size(); j++) {
+ const tutorial::Person::PhoneNumber &phone_number = person.phones(j);
+
+ switch (phone_number.type()) {
+ case tutorial::Person::MOBILE:
+ std::cout << " Mobile phone #: ";
+ break;
+ case tutorial::Person::HOME:
+ std::cout << " Home phone #: ";
+ break;
+ case tutorial::Person::WORK:
+ std::cout << " Work phone #: ";
+ break;
+ default:
+ std::cout << " Unknown phone #: ";
+ break;
+ }
+ std::cout << phone_number.number() << std::endl;
+ }
+ if (person.has_last_updated()) {
+ std::cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << std::endl;
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ // Verify that the version of the library that we linked against is
+ // compatible with the version of the headers we compiled against.
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ if (argc != 3)
+ return printUsage(argv[0]);
+
+ tutorial::AddressBook address_book;
+
+ // Read the existing address book.
+ std::fstream input(argv[2], std::ios::in | std::ios::binary);
+ if (!input) {
+ std::cout << argv[2] << ": File not found." << std::endl;
+ } else if (!address_book.ParseFromIstream(&input)) {
+ std::cerr << "Failed to parse address book." << std::endl;
+ return -1;
+ }
+
+ const std::string mode(argv[1]);
+ if (mode == "add") {
+ // Add an address.
+ promptForAddress(address_book.add_people());
+
+ if (!input)
+ std::cout << "Creating a new file." << std::endl;
+
+ // Write the new address book back to disk.
+ std::fstream output(argv[2], std::ios::out | std::ios::trunc | std::ios::binary);
+ if (!address_book.SerializeToOstream(&output)) {
+ std::cerr << "Failed to write address book." << std::endl;
+ return -1;
+ }
+ } else if (mode == "list") {
+ listPeople(address_book);
+ } else {
+ return printUsage(argv[0]);
+ }
+
+ // Optional: Delete all global objects allocated by libprotobuf.
+ google::protobuf::ShutdownProtobufLibrary();
+
+ return 0;
+}
diff --git a/qbs-resources/imports/QbsLibrary.qbs b/qbs-resources/imports/QbsLibrary.qbs
index f0769dd6c..1538735e4 100644
--- a/qbs-resources/imports/QbsLibrary.qbs
+++ b/qbs-resources/imports/QbsLibrary.qbs
@@ -5,7 +5,7 @@ QbsProduct {
Depends { name: "cpp" }
Depends { name: "Exporter.pkgconfig"; condition: generatePkgConfigFile }
Depends { name: "Exporter.qbs"; condition: generateQbsModule }
- Depends { name: "cpp" }
+ Depends { name: "span" }
property string visibilityType: staticBuild ? "static" : "dynamic"
property string headerInstallPrefix: "/include/qbs"
@@ -59,6 +59,7 @@ QbsProduct {
Export {
Depends { name: "cpp" }
Depends { name: "Qt"; submodules: ["core"] }
+ Depends { name: "span" }
Properties {
condition: exportingProduct.hasExporter
diff --git a/scripts/conan-profiles/mac_x64/qbs-test b/scripts/conan-profiles/mac_x64/qbs-test
new file mode 100644
index 000000000..6a3d0572f
--- /dev/null
+++ b/scripts/conan-profiles/mac_x64/qbs-test
@@ -0,0 +1,8 @@
+[settings]
+arch=x86_64
+build_type=Release
+compiler=apple-clang
+compiler.cppstd=17
+compiler.libcxx=libc++
+compiler.version=13
+os=Macos
diff --git a/scripts/conan-profiles/win_x64/qbs-test b/scripts/conan-profiles/win_x64/qbs-test
new file mode 100644
index 000000000..71b8e706f
--- /dev/null
+++ b/scripts/conan-profiles/win_x64/qbs-test
@@ -0,0 +1,9 @@
+[settings]
+arch=x86_64
+build_type=Release
+compiler=msvc
+compiler.cppstd=14
+compiler.runtime=dynamic
+compiler.runtime_type=Release
+compiler.version=193
+os=Windows
diff --git a/scripts/setup-conan-profiles.sh b/scripts/setup-conan-profiles.sh
new file mode 100755
index 000000000..d7da6846a
--- /dev/null
+++ b/scripts/setup-conan-profiles.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+#############################################################################
+##
+## Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com).
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qbs.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+set -eu
+
+case "$OSTYPE" in
+ *darwin*)
+ HOST_OS=mac_x64
+ ;;
+ msys)
+ HOST_OS=win_x64
+ ;;
+ *)
+ HOST_OS=
+ ;;
+esac
+
+if [ -z "${HOST_OS}" ]; then
+ exit 0
+fi
+
+echo $HOST_OS
+
+mkdir -p "${HOME}/.conan2/profiles"
+SCRIPT_DIR=$( cd "$(dirname "$0")" ; pwd -P )
+cp ${SCRIPT_DIR}/conan-profiles/${HOST_OS}/* "${HOME}/.conan2/profiles"
diff --git a/share/qbs/imports/qbs/PathTools/path-tools.js b/share/qbs/imports/qbs/PathTools/path-tools.js
index a857a7139..c928c33e4 100644
--- a/share/qbs/imports/qbs/PathTools/path-tools.js
+++ b/share/qbs/imports/qbs/PathTools/path-tools.js
@@ -232,3 +232,25 @@ function prependOrSetPath(path, pathList, separator) {
return path;
return path + separator + pathList;
}
+
+function librarySuffixes(targetOS, types, forImport) {
+ if (targetOS.includes("windows")) {
+ if (forImport)
+ return [".lib"];
+ return [].concat(types.includes("shared") ? [".dll"] : []);
+ }
+ if (targetOS.includes("darwin")) {
+ return []
+ .concat(types.includes("shared") ? [".dylib"] : [])
+ .concat(types.includes("static") ? [".a"] : []);
+ }
+ return []
+ .concat(types.includes("shared") ? [".so"] : [])
+ .concat(types.includes("static") ? [".a"] : []);
+}
+
+function libraryNameFilter(targetOS) {
+ if (targetOS.contains("unix"))
+ return function(name) { return "lib" + name; }
+ return function(name) { return name; }
+}
diff --git a/share/qbs/imports/qbs/Probes/LibraryProbe.qbs b/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
index 7631eb441..d67a81372 100644
--- a/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
@@ -28,15 +28,11 @@
**
****************************************************************************/
+import qbs.PathTools
+
PathProbe {
property string endianness
- nameSuffixes: {
- if (qbs.targetOS.contains("windows"))
- return [".lib"];
- if (qbs.targetOS.contains("macos"))
- return [".dylib", ".a"];
- return [".so", ".a"];
- }
+ nameSuffixes: PathTools.librarySuffixes(qbs.targetOS, ["shared", "static"], true)
platformSearchPaths: {
var result = [];
if (qbs.targetOS.contains("unix")) {
@@ -65,17 +61,7 @@ PathProbe {
return result;
}
- nameFilter: {
- if (qbs.targetOS.contains("unix")) {
- return function(name) {
- return "lib" + name;
- }
- } else {
- return function(name) {
- return name;
- }
- }
- }
+ nameFilter: PathTools.libraryNameFilter(qbs.targetOS)
platformEnvironmentPaths: {
if (qbs.targetOS.contains("windows"))
return [ "PATH" ];
diff --git a/share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js b/share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js
index 3978ac4b6..d382dfb02 100644
--- a/share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js
+++ b/share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js
@@ -35,25 +35,6 @@ var PkgConfig = require("qbs.PkgConfig");
var ProviderUtils = require("qbs.ProviderUtils");
var Process = require("qbs.Process");
-// We should probably use BinaryProbe instead in the provider
-function getPkgConfigExecutable() {
- function splitNonEmpty(s, c) { return s.split(c).filter(function(e) { return e; }) }
-
- var pathValue = Environment.getEnv("PATH");
- if (!pathValue)
- return undefined;
- var dirs = splitNonEmpty(pathValue, FileInfo.pathListSeparator());
- for (var i = 0; i < dirs.length; ++i) {
- var candidate =
- FileInfo.joinPaths(dirs[i], "pkg-config" + FileInfo.executableSuffix());
- var canonicalCandidate = FileInfo.canonicalPath(candidate);
- if (!canonicalCandidate || !File.exists(canonicalCandidate))
- continue;
- return canonicalCandidate;
- }
- return undefined;
-}
-
function getQmakePaths(pkg) {
var packageName = pkg.baseFileName;
if (packageName === "QtCore"
@@ -104,13 +85,12 @@ function configure(
if (!options.libDirs) {
// if we have pkg-config/pkgconf installed, let's ask it for its search paths (since
// built-in search paths can differ between platforms)
- var executable = executableFilePath ? executableFilePath : getPkgConfigExecutable();
- if (executable) {
+ if (executableFilePath) {
var p = new Process()
- if (p.exec(executable, ['pkg-config', '--variable=pc_path']) === 0) {
+ if (p.exec(executableFilePath, ['pkg-config', '--variable=pc_path']) === 0) {
var stdout = p.readStdOut().trim();
options.libDirs = stdout ? stdout.split(FileInfo.pathListSeparator()): [];
- var installDir = FileInfo.path(executable);
+ var installDir = FileInfo.path(executableFilePath);
options.libDirs = options.libDirs.map(function(path){
if (FileInfo.isAbsolutePath(path))
return path;
diff --git a/share/qbs/imports/qbs/Probes/qmake-probe.js b/share/qbs/imports/qbs/Probes/qmake-probe.js
index 48b83b873..c9a569223 100644
--- a/share/qbs/imports/qbs/Probes/qmake-probe.js
+++ b/share/qbs/imports/qbs/Probes/qmake-probe.js
@@ -72,7 +72,7 @@ function getQmakeFilePaths(qmakeFilePaths) {
if (filePaths.length === 0) {
console.warn("Could not find any qmake executables in PATH. Either make sure a qmake "
+ "executable is present in PATH or set the moduleProviders.Qt.qmakeFilePaths property "
- + "to point a qmake executable.");
+ + "to point to a qmake executable.");
}
return filePaths;
}
@@ -120,7 +120,33 @@ function configVariable(configContent, key) {
}
function configVariableItems(configContent, key) {
- return splitNonEmpty(configVariable(configContent, key), ' ');
+ var list = [];
+ var configContentLines = configContent.split('\n');
+ var regexp = new RegExp("^\\s*" + key + "\\s*([+-]?=)(.*)");
+ for (var i = 0; i < configContentLines.length; ++i) {
+ var line = configContentLines[i];
+ var match = regexp.exec(line);
+ if (!match)
+ continue;
+ var op = match[1];
+ var lineList = splitNonEmpty(match[2], ' ');
+ if (op === '=') {
+ list = lineList;
+ continue;
+ }
+ if (op === '+=') {
+ list = list.concat(lineList);
+ continue;
+ }
+ if (op === '-=') {
+ for (var j = 0; j < lineList.length; ++j) {
+ var idx = list.indexOf(lineList[j]);
+ if (idx !== -1)
+ list.splice(idx, 1);
+ }
+ }
+ }
+ return list;
}
function msvcCompilerVersionForYear(year) {
@@ -271,6 +297,8 @@ function getQtProperties(qmakeFilePath) {
|| configVariable(qconfigContent, "QT_ARCH") || "x86";
qtProps.configItems = configVariableItems(qconfigContent, "CONFIG");
qtProps.qtConfigItems = configVariableItems(qconfigContent, "QT_CONFIG");
+ qtProps.enabledFeatures = configVariableItems(qconfigContent, "QT.global.enabled_features");
+ qtProps.disabledFeatures = configVariableItems(qconfigContent, "QT.global.disabled_features");
// retrieve the mkspec
if (qtProps.qtMajorVersion >= 5) {
diff --git a/share/qbs/module-providers/Qt/setup-qt.js b/share/qbs/module-providers/Qt/setup-qt.js
index 9a314822b..781251c4b 100644
--- a/share/qbs/module-providers/Qt/setup-qt.js
+++ b/share/qbs/module-providers/Qt/setup-qt.js
@@ -213,6 +213,8 @@ function replaceSpecialValues(content, module, qtProps, abi) {
targetPlatform: ModUtils.toJSLiteral(qbsTargetPlatformFromQtMkspec(qtProps)),
config: ModUtils.toJSLiteral(qtProps.configItems),
qtConfig: ModUtils.toJSLiteral(qtProps.qtConfigItems),
+ enabledFeatures: ModUtils.toJSLiteral(qtProps.enabledFeatures),
+ disabledFeatures: ModUtils.toJSLiteral(qtProps.disabledFeatures),
binPath: ModUtils.toJSLiteral(qtProps.binaryPath),
installPath: ModUtils.toJSLiteral(qtProps.installPath),
installPrefixPath: ModUtils.toJSLiteral(qtProps.installPrefixPath),
diff --git a/share/qbs/module-providers/Qt/templates/core.qbs b/share/qbs/module-providers/Qt/templates/core.qbs
index 485402716..b44edbeb0 100644
--- a/share/qbs/module-providers/Qt/templates/core.qbs
+++ b/share/qbs/module-providers/Qt/templates/core.qbs
@@ -40,6 +40,8 @@ Module {
property string libInfix: @libInfix@
property stringList config: @config@
property stringList qtConfig: @qtConfig@
+ readonly property stringList enabledFeatures: @enabledFeatures@
+ readonly property stringList disabledFeatures: @disabledFeatures@
property path binPath: @binPath@
property path installPath: @installPath@
property path incPath: @incPath@
@@ -444,6 +446,10 @@ Module {
"-o", output.filePath];
if (input.Qt.core.enableBigResources)
args.push("-pass", "1");
+ if (product.Qt.core.disabledFeatures.contains("zstd")
+ && Utilities.versionCompare(product.Qt.core.version, "5.13") >= 0) {
+ args.push("--no-zstd");
+ }
var cmd = new Command(Rcc.fullPath(product), args);
cmd.description = "rcc "
+ (input.Qt.core.enableBigResources ? "(pass 1) " : "")
diff --git a/share/qbs/module-providers/conan.js b/share/qbs/module-providers/conan.js
new file mode 100644
index 000000000..a44af7eec
--- /dev/null
+++ b/share/qbs/module-providers/conan.js
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Kai Dohmen
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
+var PathProbe = require("../imports/qbs/Probes/path-probe.js")
+var PathTools = require("qbs.PathTools");
+var TextFile = require("qbs.TextFile");
+var Utilities = require("qbs.Utilities");
+
+const architectureMap = {
+ 'x86': 'x86',
+ 'x86_64': 'x86_64',
+ 'ppc32be': 'ppc',
+ 'ppc32': 'ppc',
+ 'ppc64le': 'ppc64',
+ 'ppc64': 'ppc64',
+ 'armv4': 'arm',
+ 'armv4i': 'arm',
+ 'armv5el': 'arm',
+ 'armv5hf': 'arm',
+ 'armv6': 'arm',
+ 'armv7': 'arm',
+ 'armv7hf': 'arm',
+ 'armv7s': 'arm',
+ 'armv7k': 'arm',
+ 'armv8': 'arm64',
+ 'armv8_32': 'arm64',
+ 'armv8.3': 'arm64',
+ 'sparc': 'sparc',
+ 'sparcv9': 'sparc64',
+ 'mips': 'mips',
+ 'mips64': 'mips64',
+ 'avr': 'avr',
+ 's390': 's390x',
+ 's390x': 's390x',
+ 'sh4le': 'sh'
+}
+
+const platformMap = {
+ 'Windows': 'windows',
+ 'WindowsStore': 'windows',
+ 'WindowsCE': 'windows',
+ 'Linux': 'linux',
+ 'Macos': 'macos',
+ 'Android': 'android',
+ 'iOS': 'ios',
+ 'watchOS': 'watchos',
+ 'tvOS': 'tvos',
+ 'FreeBSD': 'freebsd',
+ 'SunOS': 'solaris',
+ 'AIX': 'aix',
+ 'Emscripten': undefined,
+ 'Arduino': 'none',
+ 'Neutrino': 'qnx',
+ 'baremetal': 'none',
+ 'VxWorks': 'vxworks',
+}
+
+function findLibs(libnames, libdirs, libtypes, targetOS, forImport) {
+ var result = [];
+ if (libnames === null || libdirs === null)
+ return result;
+ libnames.forEach(function(libraryName) {
+ const suffixes = PathTools.librarySuffixes(targetOS, libtypes, forImport);
+ const lib = PathProbe.configure(
+ undefined, // selectors
+ [libraryName],
+ suffixes,
+ PathTools.libraryNameFilter(targetOS),
+ undefined, // candidateFilter
+ libdirs, // searchPaths
+ undefined, // pathSuffixes
+ [], // platformSearchPaths
+ undefined, // environmentPaths
+ undefined // platformEnvironmentPaths
+ );
+ if (lib.found)
+ result.push(lib.files[0].filePath);
+ });
+ return result;
+}
+
+function getLibraryTypes(options) {
+ if (options !== undefined && options !== null) {
+ if (options.shared === undefined)
+ return ["shared", "static"];
+ else if (options.shared === "True")
+ return ["shared"];
+ else if (options.shared === "False")
+ return ["static"];
+ }
+ return ["shared", "static"];
+}
+
+function configure(installDirectory, moduleName, outputBaseDir, jsonProbe) {
+ const moduleMapping = {"protobuflib": "protobuf"}
+ const realModuleName = moduleMapping[moduleName] || moduleName;
+
+ const moduleFilePath =
+ FileInfo.joinPaths(installDirectory, "conan-qbs-deps", realModuleName + ".json")
+ if (!File.exists(moduleFilePath))
+ return [];
+
+ var reverseMapping = {}
+ for (var key in moduleMapping)
+ reverseMapping[moduleMapping[key]] = key
+
+ console.info("Setting up Conan module '" + moduleName + "'");
+
+ var moduleFile = new TextFile(moduleFilePath, TextFile.ReadOnly);
+ const moduleInfo = JSON.parse(moduleFile.readAll());
+
+ const outputDir = FileInfo.joinPaths(outputBaseDir, "modules", moduleName.replace(".", "/"));
+ File.makePath(outputDir);
+ const outputFilePath = FileInfo.joinPaths(outputDir, "module.qbs");
+
+ const cppInfo = moduleInfo.cpp_info;
+
+ var moduleContent = "";
+
+ // function write(data) { moduleContent = moduleContent + data }
+ function writeLine(data) { moduleContent = moduleContent + data + "\n"; }
+
+ function writeProperty(propertyName, propertyValue) {
+ if (propertyValue === undefined || propertyValue === null)
+ propertyValue = [];
+ writeLine(" readonly property stringList " + propertyName
+ + ": " + ModUtils.toJSLiteral(propertyValue));
+ }
+ function writeCppProperty(propertyName, propertyValue) {
+ writeProperty(propertyName, propertyValue);
+ // skip empty props for simplicity of the module file
+ if (propertyValue !== undefined && propertyValue != null && propertyValue.length !== 0) {
+ writeLine(" cpp." + propertyName + ": " + propertyName);
+ }
+ }
+
+ writeLine("Module {");
+
+ writeLine(" version: " + ModUtils.toJSLiteral(moduleInfo.version));
+
+ const architecture = architectureMap[moduleInfo.settings.arch];
+ const platform = platformMap[moduleInfo.settings.os];
+ const targetOS = Utilities.canonicalPlatform(platform);
+
+ writeLine(" readonly property string architecture: " + ModUtils.toJSLiteral(architecture));
+ writeLine(" readonly property string platform: " + ModUtils.toJSLiteral(platform));
+ writeLine(" condition: true");
+ if (architecture !== undefined) {
+ writeLine(" && (!qbs.architecture || qbs.architecture === architecture)");
+ }
+ if (platform !== undefined) {
+ if (["ios", "tvos", "watchos"].includes(platform)) {
+ writeLine(" && (qbs.targetPlatform === platform || qbs.targetPlatform === platform + \"-simulator\")");
+ } else {
+ writeLine(" && qbs.targetPlatform === platform");
+ }
+ }
+
+ writeLine(" Depends { name: 'cpp' }");
+
+ moduleInfo.dependencies.forEach(function(dep) {
+ const realDepName = reverseMapping[dep.name] || dep.name;
+ writeLine(" Depends { name: " + ModUtils.toJSLiteral(realDepName)
+ + "; version: " + ModUtils.toJSLiteral(dep.version) + "}");
+ });
+
+ writeLine(" readonly property stringList hostBinDirs: (" + ModUtils.toJSLiteral(moduleInfo.build_bindirs) + ")");
+ // target bindirs
+ writeLine(" readonly property stringList binDirs: (" + ModUtils.toJSLiteral(cppInfo.bindirs) + ")");
+
+ // TODO: there's a weird issue with system include dirs with xcode-less clang - incorrect include order?
+ writeCppProperty("includePaths", cppInfo.includedirs);
+ writeCppProperty("frameworkPaths", cppInfo.frameworkdirs);
+ writeCppProperty("frameworks", cppInfo.frameworks);
+ writeCppProperty("defines", cppInfo.defines);
+ writeCppProperty("cFlags", cppInfo.cflags);
+ writeCppProperty("cxxFlags", cppInfo.cxxflags);
+ writeCppProperty("linkerFlags", (cppInfo.sharedlinkflags || []).concat(cppInfo.exelinkflags || []));
+
+ writeProperty("resources", cppInfo.resdirs);
+
+ const isForImport = targetOS.includes("windows")
+ const libraryTypes = getLibraryTypes(moduleInfo.options);
+ libraryTypes.forEach(function(libraryType){
+ const cppInfoLibs = cppInfo.libs === null ? [] : cppInfo.libs;
+ const libs = findLibs(cppInfoLibs, cppInfo.libdirs, libraryType, targetOS, isForImport)
+ .concat(cppInfo.system_libs === null ? [] : cppInfo.system_libs);
+ const property = libraryType === "shared" ? "dynamicLibraries" : "staticLibraries";
+ writeCppProperty(property, libs);
+ });
+
+ writeLine("}");
+
+ var moduleFile = new TextFile(outputFilePath, TextFile.WriteOnly);
+ moduleFile.write(moduleContent);
+ moduleFile.close();
+
+ return "";
+}
diff --git a/share/qbs/module-providers/conan.qbs b/share/qbs/module-providers/conan.qbs
new file mode 100644
index 000000000..6391eeb65
--- /dev/null
+++ b/share/qbs/module-providers/conan.qbs
@@ -0,0 +1,12 @@
+import "conan.js" as ConanHelper
+
+ModuleProvider {
+ /* input */
+ property path installDirectory
+
+ isEager: false
+
+ relativeSearchPaths: {
+ return ConanHelper.configure(installDirectory, moduleName, outputBaseDir);
+ }
+}
diff --git a/share/qbs/module-providers/qbspkgconfig.qbs b/share/qbs/module-providers/qbspkgconfig.qbs
index 5e027788e..885a6da7a 100644
--- a/share/qbs/module-providers/qbspkgconfig.qbs
+++ b/share/qbs/module-providers/qbspkgconfig.qbs
@@ -51,7 +51,8 @@ import qbs.TextFile
import "Qt/setup-qt.js" as SetupQt
ModuleProvider {
- property string executableFilePath
+ property stringList executableNames: ["pkgconf", "pkg-config"]
+ property string executableFilePath: pkgConfigProbe.filePath
property stringList extraPaths
property stringList libDirs
property bool staticMode: false
@@ -62,16 +63,20 @@ ModuleProvider {
property path sysroot: qbs.toolchain && qbs.toolchain.includes("xcode")
? undefined : qbs.sysroot
+ Probes.BinaryProbe {
+ id: pkgConfigProbe
+ condition: !executableFilePath
+ names: executableNames
+ }
+
Probes.QbsPkgConfigProbe {
id: theProbe
- // TODO: without explicit 'parent' we do not have access to the fake "qbs" scope
- _executableFilePath: parent.executableFilePath
- _extraPaths: parent.extraPaths
- _sysroot: parent.sysroot
- _libDirs: parent.libDirs
- _staticMode: parent.staticMode
- _definePrefix: parent.definePrefix
- _mergeDependencies: parent.mergeDependencies
+ _executableFilePath: executableFilePath
+ _extraPaths: extraPaths
+ _sysroot: sysroot
+ _libDirs: libDirs
+ _staticMode: staticMode
+ _definePrefix: definePrefix
}
Probes.QmakeProbe {
@@ -143,7 +148,6 @@ ModuleProvider {
var outputDir = FileInfo.joinPaths(outputBaseDir, "modules");
File.makePath(outputDir);
- // TODO: ponder how we can solve forward mapping with Packages so we can fill deps
var moduleMapping = {
"protobuf": "protobuflib"
}
diff --git a/share/qbs/modules/capnproto/capnprotobase.qbs b/share/qbs/modules/capnproto/capnprotobase.qbs
index 56d542770..916e53a51 100644
--- a/share/qbs/modules/capnproto/capnprotobase.qbs
+++ b/share/qbs/modules/capnproto/capnprotobase.qbs
@@ -28,6 +28,7 @@
**
****************************************************************************/
+import qbs.FileInfo
import qbs.Probes
import "capnproto.js" as HelperFunctions
@@ -42,14 +43,18 @@ Module {
property string outputDir: product.buildDirectory + "/capnp"
+ property var _searchPaths
+
Probes.BinaryProbe {
id: compilerProbe
names: compilerName ? [compilerName] : []
+ searchPaths: _searchPaths
}
Probes.BinaryProbe {
id: pluginProbe
names: pluginName ? [pluginName] : []
+ searchPaths: _searchPaths
}
FileTagger {
diff --git a/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs b/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs
index bccfca192..83192b7de 100644
--- a/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs
+++ b/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs
@@ -40,6 +40,7 @@ CapnProtoBase {
pluginName: "capnpc-c++"
version: capnp.version
+ _searchPaths: capnp.hostBinDirs
cpp.systemIncludePaths: outputDir
cpp.cxxLanguageVersion: "c++14"
diff --git a/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs b/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs
new file mode 100644
index 000000000..9f5b2b70c
--- /dev/null
+++ b/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs
+import qbs.FileInfo
+
+import "../flatbuffers.js" as Flatbuf
+import "../flatbuffersbase.qbs" as FlatbufBase
+
+FlatbufBase {
+ Depends { name: "cpp" }
+ Depends { name: "flatcc" }
+
+ compilerName: "flatcc"
+
+ _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf", "c")
+ _searchPaths: flatbuffers.hostBinDirs
+
+ cpp.systemIncludePaths: base.concat([_outputDir])
+
+ Rule {
+ inputs: ["flatbuf.input"]
+ outputFileTags: ["hpp"]
+ outputArtifacts: [Flatbuf.artifactC(input.flatbuf.c, input, "hpp", "_generated.h")]
+
+ prepare: {
+ return Flatbuf.doPrepareC(input.flatbuf.c, input);
+ }
+ }
+
+ validate: {
+ Flatbuf.validateCompiler(compilerName, compilerPath);
+ }
+}
diff --git a/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs b/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs
new file mode 100644
index 000000000..4614d4949
--- /dev/null
+++ b/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs
+import qbs.FileInfo
+
+import "../flatbuffers.js" as Flatbuf
+import "../flatbuffersbase.qbs" as FlatbufBase
+
+FlatbufBase {
+ Depends { name: "cpp" }
+ Depends { name: "flatbuffers" }
+
+ property string filenameExtension: "h"
+ property string filenameSuffix: "_generated"
+ property string includePrefix // TODO: test
+ property bool keepPrefix: false
+
+ _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf", "cpp")
+ _searchPaths: flatbuffers.hostBinDirs
+
+ cpp.cxxLanguageVersion: "c++11"
+ cpp.systemIncludePaths: base.concat([_outputDir])
+
+ Rule {
+ inputs: ["flatbuf.input"]
+ outputFileTags: ["hpp"]
+ outputArtifacts: {
+ var module = input.flatbuf.cpp;
+ var fullSuffix = module.filenameSuffix + "." + module.filenameExtension;
+ return [ Flatbuf.artifact(module, input, "hpp", fullSuffix) ];
+ }
+
+ prepare: {
+ return Flatbuf.doPrepareCpp(input.flatbuf.cpp, input, output);
+ }
+ }
+
+ validate: {
+ Flatbuf.validateCompiler(compilerName, compilerPath);
+ }
+}
diff --git a/share/qbs/modules/flatbuf/flatbuffers.js b/share/qbs/modules/flatbuf/flatbuffers.js
new file mode 100644
index 000000000..24fd91168
--- /dev/null
+++ b/share/qbs/modules/flatbuf/flatbuffers.js
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+var File = require("qbs.File");
+
+function validateCompiler(compilerName, compilerPath) {
+ if (!File.exists(compilerPath)) {
+ throw "Can't find '" + compilerName + "' binary. Please set the compilerPath property or "
+ + "make sure the compiler is found in PATH";
+ }
+}
+
+function getOutputDir(module, input) {
+ var outputDir = module._outputDir;
+ if (!module.keepPrefix)
+ return outputDir;
+ var importPaths = module.importPaths;
+ if (importPaths !== undefined && importPaths.length !== 0) {
+ var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath));
+ for (var i = 0; i < importPaths.length; ++i) {
+ var path = File.canonicalFilePath(importPaths[i]);
+
+ if (canonicalInput.startsWith(path)) {
+ return outputDir + "/" + FileInfo.relativePath(path, canonicalInput);
+ }
+ }
+ }
+ return outputDir;
+}
+
+function artifactC(module, input, tag, suffix) {
+ var outputDir = module._outputDir;
+ return {
+ fileTags: [tag],
+ filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix,
+ cpp: { warningLevel: "none"}
+ };
+}
+
+function doPrepareC(module, input)
+{
+ var args = [];
+ args.push("-a") // write all
+ args.push("-o", input.flatbuf.c._outputDir) // output dir
+
+ var importPaths = module.importPaths;
+ importPaths.forEach(function(path) {
+ args.push("-I", path);
+ });
+
+ args.push(input.filePath);
+
+ var cmd = new Command(module.compilerPath, args);
+ cmd.workingDirectory = FileInfo.path(module._outputDir)
+ cmd.highlight = "codegen";
+ cmd.description = "generating C files for " + input.fileName;
+ return [cmd];
+}
+
+function artifact(module, input, tag, suffix) {
+ var outputDir = getOutputDir(module, input);
+ return {
+ fileTags: [tag],
+ filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix,
+ cpp: { warningLevel: "none" }
+ };
+}
+
+function doPrepareCpp(module, input, output)
+{
+ var outputDir = FileInfo.path(output.filePath);
+ var result = [];
+
+ var args = [];
+ args.push("--cpp")
+
+ var importPaths = module.importPaths;
+ importPaths.forEach(function(path) {
+ args.push("-I", path);
+ });
+
+ args.push("--filename-ext", module.filenameExtension);
+ args.push("--filename-suffix", module.filenameSuffix);
+
+ if (module.includePrefix)
+ args.push("--include-prefix", module.includePrefix);
+
+ if (module.keepPrefix)
+ args.push("--keep-prefix");
+
+ args.push(input.filePath);
+ var cmd = new Command(input.flatbuf.cpp.compilerPath, args);
+ cmd.workingDirectory = outputDir;
+ cmd.highlight = "codegen";
+ cmd.description = "generating C++ files for " + input.fileName;
+ result.push(cmd);
+
+ return result;
+}
diff --git a/share/qbs/modules/flatbuf/flatbuffersbase.qbs b/share/qbs/modules/flatbuf/flatbuffersbase.qbs
new file mode 100644
index 000000000..98eb2f344
--- /dev/null
+++ b/share/qbs/modules/flatbuf/flatbuffersbase.qbs
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs
+import qbs.File
+import qbs.FileInfo
+import qbs.Probes
+
+import "flatbuffers.js" as HelperFunctions
+
+Module {
+ property string compilerName: "flatc"
+ property string compilerPath: compilerProbe.filePath
+
+ property pathList importPaths: []
+
+ property string _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf")
+
+ property stringList _searchPaths
+
+ FileTagger {
+ patterns: ["*.fbs"]
+ fileTags: ["flatbuf.input"];
+ }
+
+ Probes.BinaryProbe {
+ id: compilerProbe
+ names: [compilerName]
+ searchPaths: _searchPaths
+ }
+}
diff --git a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
index b5dab2372..bd4a08557 100644
--- a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
+++ b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
@@ -13,6 +13,9 @@ ProtobufBase {
property string _cxxLanguageVersion: "c++17"
+ _searchPaths: protobuflib.present ? protobuflib.hostBinDirs : undefined
+ property stringList _grpcSearchPaths: grpcpp.present ? grpcpp.hostBinDirs : undefined
+
cpp.includePaths: outputDir
Depends { name: "cpp" }
@@ -34,6 +37,7 @@ ProtobufBase {
condition: useGrpc
id: grpcPluginProbe
names: "grpc_cpp_plugin"
+ searchPaths: _grpcSearchPaths
}
cpp.cxxLanguageVersion: _cxxLanguageVersion
diff --git a/share/qbs/modules/protobuf/protobufbase.qbs b/share/qbs/modules/protobuf/protobufbase.qbs
index e302d3758..e32ee30b9 100644
--- a/share/qbs/modules/protobuf/protobufbase.qbs
+++ b/share/qbs/modules/protobuf/protobufbase.qbs
@@ -6,6 +6,7 @@ import "protobuf.js" as HelperFunctions
Module {
property string compilerName: "protoc"
property string compilerPath: compilerProbe.filePath
+ property var _searchPaths
property pathList importPaths: []
@@ -19,5 +20,6 @@ Module {
Probes.BinaryProbe {
id: compilerProbe
names: [compilerName]
+ searchPaths: _searchPaths
}
}
diff --git a/share/qbs/modules/xcode/xcode.qbs b/share/qbs/modules/xcode/xcode.qbs
index c052da44c..2c0cd001a 100644
--- a/share/qbs/modules/xcode/xcode.qbs
+++ b/share/qbs/modules/xcode/xcode.qbs
@@ -9,21 +9,19 @@ import qbs.PropertyList
import qbs.Utilities
Module {
- id: xcodeModule
-
Probes.XcodeLocationProbe {
id: xcodeLocationProbe
- condition: !xcodeModule.developerPath
+ condition: !developerPath
}
Probes.XcodeProbe {
id: xcodeProbe
- developerPath: xcodeModule.developerPath
- platformType: xcodeModule.platformType
- platformPath: xcodeModule.platformPath
- devicePlatformPath: xcodeModule.devicePlatformPath
- xcodebuildPath: xcodeModule.xcodebuildPath
- sdksPath: xcodeModule.sdksPath
+ developerPath: parent.developerPath
+ platformType: parent.platformType
+ platformPath: parent.platformPath
+ devicePlatformPath: parent.devicePlatformPath
+ xcodebuildPath: parent.xcodebuildPath
+ sdksPath: parent.sdksPath
}
condition: qbs.targetOS.includes("darwin") &&
diff --git a/src/app/qbs/commandlinefrontend.cpp b/src/app/qbs/commandlinefrontend.cpp
index 4248f55a7..200740145 100644
--- a/src/app/qbs/commandlinefrontend.cpp
+++ b/src/app/qbs/commandlinefrontend.cpp
@@ -152,7 +152,6 @@ void CommandLineFrontend::start()
params.setDryRun(m_parser.dryRun());
params.setForceProbeExecution(m_parser.forceProbesExecution());
params.setWaitLockBuildGraph(m_parser.waitLockBuildGraph());
- params.setFallbackProviderEnabled(!m_parser.disableFallbackProvider());
params.setLogElapsedTime(m_parser.logTime());
params.setSettingsDirectory(m_settings->baseDirectory());
params.setOverrideBuildGraphData(m_parser.command() == ResolveCommandType);
@@ -491,9 +490,22 @@ QString CommandLineFrontend::buildDirectory(const QString &profileName) const
}
QString projectName(QFileInfo(m_parser.projectFilePath()).baseName());
+ QString originalBuildDir = buildDir;
buildDir.replace(BuildDirectoryOption::magicProjectString(), projectName);
+ const QString buildDirPlaceHolderMsgTemplate = Tr::tr(
+ "You must provide the path to the project file when using build directory "
+ "placeholder '%1'.");
+ if (buildDir != originalBuildDir && projectName.isEmpty()) {
+ throw ErrorInfo(
+ buildDirPlaceHolderMsgTemplate.arg(BuildDirectoryOption::magicProjectString()));
+ }
QString projectDir(QFileInfo(m_parser.projectFilePath()).path());
+ originalBuildDir = buildDir;
buildDir.replace(BuildDirectoryOption::magicProjectDirString(), projectDir);
+ if (buildDir != originalBuildDir && projectDir.isEmpty()) {
+ throw ErrorInfo(
+ buildDirPlaceHolderMsgTemplate.arg(BuildDirectoryOption::magicProjectDirString()));
+ }
if (!QFileInfo(buildDir).isAbsolute())
buildDir = QDir::currentPath() + QLatin1Char('/') + buildDir;
buildDir = QDir::cleanPath(buildDir);
diff --git a/src/app/qbs/parser/commandlineoption.cpp b/src/app/qbs/parser/commandlineoption.cpp
index 389b304f0..7572b4e66 100644
--- a/src/app/qbs/parser/commandlineoption.cpp
+++ b/src/app/qbs/parser/commandlineoption.cpp
@@ -710,17 +710,6 @@ QString WaitLockOption::longRepresentation() const
return QStringLiteral("--wait-lock");
}
-QString DisableFallbackProviderOption::description(CommandType) const
-{
- return Tr::tr("%1\n\tDo not fall back to pkg-config if a dependency is not found.\n")
- .arg(longRepresentation());
-}
-
-QString DisableFallbackProviderOption::longRepresentation() const
-{
- return QStringLiteral("--no-fallback-module-provider");
-}
-
QString RunEnvConfigOption::description(CommandType command) const
{
Q_UNUSED(command);
diff --git a/src/app/qbs/parser/commandlineoption.h b/src/app/qbs/parser/commandlineoption.h
index d51d5f765..7b8baeae2 100644
--- a/src/app/qbs/parser/commandlineoption.h
+++ b/src/app/qbs/parser/commandlineoption.h
@@ -55,7 +55,9 @@ public:
enum Type {
FileOptionType,
BuildDirectoryOptionType,
- LogLevelOptionType, VerboseOptionType, QuietOptionType,
+ LogLevelOptionType,
+ VerboseOptionType,
+ QuietOptionType,
JobsOptionType,
KeepGoingOptionType,
DryRunOptionType,
@@ -64,7 +66,9 @@ public:
ChangedFilesOptionType,
ProductsOptionType,
NoInstallOptionType,
- InstallRootOptionType, RemoveFirstOptionType, NoBuildOptionType,
+ InstallRootOptionType,
+ RemoveFirstOptionType,
+ NoBuildOptionType,
ForceTimestampCheckOptionType,
ForceOutputCheckOptionType,
BuildNonDefaultOptionType,
@@ -76,7 +80,6 @@ public:
GeneratorOptionType,
WaitLockOptionType,
RunEnvConfigOptionType,
- DisableFallbackProviderType,
DeprecationWarningsOptionType,
};
@@ -431,14 +434,6 @@ public:
QString longRepresentation() const override;
};
-class DisableFallbackProviderOption : public OnOffOption
-{
-public:
- QString description(CommandType command) const override;
- QString shortRepresentation() const override { return {}; }
- QString longRepresentation() const override;
-};
-
} // namespace qbs
#endif // QBS_COMMANDLINEOPTION_H
diff --git a/src/app/qbs/parser/commandlineoptionpool.cpp b/src/app/qbs/parser/commandlineoptionpool.cpp
index 3908f262c..692c9c737 100644
--- a/src/app/qbs/parser/commandlineoptionpool.cpp
+++ b/src/app/qbs/parser/commandlineoptionpool.cpp
@@ -128,9 +128,6 @@ CommandLineOption *CommandLineOptionPool::getOption(CommandLineOption::Type type
case CommandLineOption::WaitLockOptionType:
option = new WaitLockOption;
break;
- case CommandLineOption::DisableFallbackProviderType:
- option = new DisableFallbackProviderOption;
- break;
case CommandLineOption::RunEnvConfigOptionType:
option = new RunEnvConfigOption;
break;
@@ -279,12 +276,6 @@ WaitLockOption *CommandLineOptionPool::waitLockOption() const
return static_cast<WaitLockOption *>(getOption(CommandLineOption::WaitLockOptionType));
}
-DisableFallbackProviderOption *CommandLineOptionPool::disableFallbackProviderOption() const
-{
- return static_cast<DisableFallbackProviderOption *>(
- getOption(CommandLineOption::DisableFallbackProviderType));
-}
-
RunEnvConfigOption *CommandLineOptionPool::runEnvConfigOption() const
{
return static_cast<RunEnvConfigOption *>(getOption(CommandLineOption::RunEnvConfigOptionType));
diff --git a/src/app/qbs/parser/commandlineoptionpool.h b/src/app/qbs/parser/commandlineoptionpool.h
index 5f3c1d87c..022e9fd09 100644
--- a/src/app/qbs/parser/commandlineoptionpool.h
+++ b/src/app/qbs/parser/commandlineoptionpool.h
@@ -77,7 +77,6 @@ public:
RespectProjectJobLimitsOption *respectProjectJobLimitsOption() const;
GeneratorOption *generatorOption() const;
WaitLockOption *waitLockOption() const;
- DisableFallbackProviderOption *disableFallbackProviderOption() const;
RunEnvConfigOption *runEnvConfigOption() const;
DeprecationWarningsOption *deprecationWarningsOption() const;
diff --git a/src/app/qbs/parser/commandlineparser.cpp b/src/app/qbs/parser/commandlineparser.cpp
index 7fbfa28f1..c548cf2b5 100644
--- a/src/app/qbs/parser/commandlineparser.cpp
+++ b/src/app/qbs/parser/commandlineparser.cpp
@@ -231,11 +231,6 @@ bool CommandLineParser::waitLockBuildGraph() const
return d->optionPool.waitLockOption()->enabled();
}
-bool CommandLineParser::disableFallbackProvider() const
-{
- return d->optionPool.disableFallbackProviderOption()->enabled();
-}
-
bool CommandLineParser::logTime() const
{
return d->logTime;
diff --git a/src/app/qbs/parser/commandlineparser.h b/src/app/qbs/parser/commandlineparser.h
index 4ce7756ef..4df8829a2 100644
--- a/src/app/qbs/parser/commandlineparser.h
+++ b/src/app/qbs/parser/commandlineparser.h
@@ -81,7 +81,6 @@ public:
bool dryRun() const;
bool forceProbesExecution() const;
bool waitLockBuildGraph() const;
- bool disableFallbackProvider() const;
bool logTime() const;
bool withNonDefaultProducts() const;
bool buildBeforeInstalling() const;
diff --git a/src/app/qbs/parser/parsercommand.cpp b/src/app/qbs/parser/parsercommand.cpp
index f11a7b6ac..ef8da9551 100644
--- a/src/app/qbs/parser/parsercommand.cpp
+++ b/src/app/qbs/parser/parsercommand.cpp
@@ -199,18 +199,18 @@ QString ResolveCommand::representation() const
static QList<CommandLineOption::Type> resolveOptions()
{
- return {CommandLineOption::FileOptionType,
- CommandLineOption::BuildDirectoryOptionType,
- CommandLineOption::LogLevelOptionType,
- CommandLineOption::VerboseOptionType,
- CommandLineOption::QuietOptionType,
- CommandLineOption::ShowProgressOptionType,
- CommandLineOption::DryRunOptionType,
- CommandLineOption::ForceProbesOptionType,
- CommandLineOption::LogTimeOptionType,
- CommandLineOption::DeprecationWarningsOptionType,
- CommandLineOption::JobsOptionType,
- CommandLineOption::DisableFallbackProviderType};
+ return {
+ CommandLineOption::FileOptionType,
+ CommandLineOption::BuildDirectoryOptionType,
+ CommandLineOption::LogLevelOptionType,
+ CommandLineOption::VerboseOptionType,
+ CommandLineOption::QuietOptionType,
+ CommandLineOption::ShowProgressOptionType,
+ CommandLineOption::DryRunOptionType,
+ CommandLineOption::ForceProbesOptionType,
+ CommandLineOption::LogTimeOptionType,
+ CommandLineOption::DeprecationWarningsOptionType,
+ CommandLineOption::JobsOptionType};
}
QList<CommandLineOption::Type> ResolveCommand::supportedOptions() const
diff --git a/src/conan/extensions/generators/qbsdeps.py b/src/conan/extensions/generators/qbsdeps.py
new file mode 100644
index 000000000..77d875aa8
--- /dev/null
+++ b/src/conan/extensions/generators/qbsdeps.py
@@ -0,0 +1,218 @@
+############################################################################
+##
+## Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com).
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qbs.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+from conan.tools.files import save
+from conan.errors import ConanException
+from conans.model.dependencies import get_transitive_requires
+import json
+import os
+
+
+class _QbsDepsModuleFile():
+ def __init__(self, qbsdeps, dep, component, deps, module_name):
+ self._qbsdeps = qbsdeps
+ self._dep = dep
+ self._component = component
+ self._deps = deps
+ self._module_name = module_name
+ self._build_bindirs = qbsdeps._build_bindirs
+
+ def _get_component_version(dep, component):
+ return (component.get_property("component_version") or
+ component.get_property("system_package_version") or
+ dep.ref.version)
+ self._version = _get_component_version(self._dep, self._component)
+
+ @property
+ def filename(self):
+ return self._module_name + '.json'
+
+ @property
+ def version(self):
+ return self._version
+
+ def get_content(self):
+ return {
+ 'package_name': self._dep.ref.name,
+ 'package_dir': self._get_package_dir(),
+ 'version': str(self._version),
+ 'cpp_info': self._component.serialize(),
+ 'build_bindirs': self._build_bindirs,
+ 'dependencies': [{'name': n, "version": str(v)} for n, v in self._deps],
+ 'settings': {k: v for k, v in self._dep.settings.items()},
+ 'options': {k: v for k, v in self._dep.options.items()}
+ }
+
+ def _get_package_dir(self):
+ # If editable, package_folder can be None
+ return self._dep.recipe_folder if self._dep.package_folder is None \
+ else self._dep.package_folder
+
+ def render(self):
+ return json.dumps(self.get_content(), indent=4)
+
+
+class _QbsDepGenerator:
+ ''' Handles a single package, can create multiple modules in case of several components '''
+ def __init__(self, conanfile, dep, build_bindirs):
+ self._conanfile = conanfile
+ self._dep = dep
+ self._build_bindirs = build_bindirs
+
+ @property
+ def content(self):
+ qbs_files = {}
+ transitive_reqs = get_transitive_requires(self._conanfile, self._dep)
+
+ def _get_package_name(dep):
+ # TODO: pkgconfig uses suffix, do we need it? see:
+ # https://github.com/conan-io/conan/blob/develop2/conan/tools/gnu/pkgconfigdeps.py#L319
+ return dep.cpp_info.get_property("pkg_config_name") or dep.ref.name
+
+ def _get_component_name(dep, comp_name):
+ if comp_name not in dep.cpp_info.components:
+ if dep.ref.name == comp_name:
+ return _get_package_name(dep)
+ raise ConanException("Component '{name}::{cname}' not found in '{name}' "
+ "package requirement".format(name=dep.ref.name,
+ cname=comp_name))
+
+ # TODO: pkgconfig uses suffix, do we need it?
+ # We re-use pkg_config_name for compatiblitity with the Qbs pkg-config provider:
+ # in that case, Qbs/its users do not need to do additional mapping on their side
+ pkg_config_name = dep.cpp_info.components[comp_name].get_property("pkg_config_name")
+ return pkg_config_name or comp_name
+
+ def _get_name_with_namespace(namespace, name):
+ """
+ Build a name with a namespace, e.g., openssl-crypto
+ """
+ return f"{namespace}-{name}"
+
+ def get_components(dep):
+ ret = {}
+ for comp_ref_name, info in dep.cpp_info.get_sorted_components().items():
+ comp_name = _get_component_name(dep, comp_ref_name)
+ ret[comp_name] = info
+ return ret
+
+ # copy & paste from pkgconfig deps
+ def get_cpp_info_requires_names(dep, cpp_info):
+ ret = []
+ dep_ref_name = dep.ref.name
+ for req in cpp_info.requires:
+ pkg_ref_name, comp_ref_name = (
+ req.split("::") if "::" in req else (dep_ref_name, req)
+ )
+
+ if dep_ref_name != pkg_ref_name:
+ try:
+ req_conanfile = transitive_reqs[pkg_ref_name]
+ except KeyError:
+ # If the dependency is not in the transitive, might be skipped
+ continue
+ # For instance, dep == "hello/1.0" and req == "hello::cmp1" -> hello == hello
+ else:
+ req_conanfile = dep
+
+ comp_name = _get_component_name(req_conanfile, comp_ref_name)
+ if not comp_name:
+ pkg_name = _get_package_name(req_conanfile)
+ # Creating a component name with namespace, e.g., dep-comp1
+ comp_name = _get_name_with_namespace(pkg_name, comp_ref_name)
+ ret.append((comp_name, req_conanfile.ref.version))
+ return ret
+
+ if not self._dep.cpp_info.has_components:
+ module_name = _get_package_name(self._dep)
+ requires = get_cpp_info_requires_names(self._dep, self._dep.cpp_info._package)
+ if not requires:
+ # If no requires were found, let's try to get all the direct visible
+ # dependencies, e.g., requires = "other_pkg/1.0"
+ for deprequire, _ in self._dep.dependencies.direct_host.items():
+ requires.append((deprequire.ref.name, deprequire.ref.version))
+ file = _QbsDepsModuleFile(
+ self, self._dep, self._dep.cpp_info._package, requires, module_name
+ )
+ qbs_files[file.filename] = file
+ else:
+ full_requires = []
+ for module_name, component in get_components(self._dep).items():
+ requires = get_cpp_info_requires_names(self._dep, component)
+ file = _QbsDepsModuleFile(self, self._dep, component, requires, module_name)
+ qbs_files[file.filename] = file
+ full_requires.append((module_name, file.version))
+ module_name = _get_package_name(self._dep)
+ file = _QbsDepsModuleFile(
+ self, self._dep, self._dep.cpp_info._package, full_requires, module_name)
+ # We create the root package's module file ONLY
+ # if it does not already exist in components
+ # An example is a grpc package where they have a "grpc" component
+ if file.filename not in qbs_files:
+ qbs_files[file.filename] = file
+
+ return qbs_files
+
+
+class QbsDeps:
+ ''' Handles multiple packages '''
+ def __init__(self, conanfile):
+ self._conanfile = conanfile
+
+ @property
+ def content(self):
+ qbs_files = {}
+
+ build_bindirs = {
+ dep.ref.name: dep.cpp_info.bindirs
+ for _, dep in self._conanfile.dependencies.build.items()}
+
+ for require, dep in self._conanfile.dependencies.items():
+
+ # skip build deps for now
+ if require.build:
+ continue
+
+ dep_build_bindirs = build_bindirs.get(dep.ref.name, [])
+ qbs_files.update(_QbsDepGenerator(self._conanfile, dep, dep_build_bindirs).content)
+ return qbs_files
+
+ def generate(self):
+ for file_name, qbs_deps_file in self.content.items():
+ save(self._conanfile, os.path.join('conan-qbs-deps', file_name), qbs_deps_file.render())
diff --git a/src/lib/corelib/CMakeLists.txt b/src/lib/corelib/CMakeLists.txt
index 97b5e6fad..ff9d9e428 100644
--- a/src/lib/corelib/CMakeLists.txt
+++ b/src/lib/corelib/CMakeLists.txt
@@ -456,6 +456,7 @@ add_qbs_library(qbscore
qbsquickjs
PUBLIC_DEPENDS
Qt${QT_VERSION_MAJOR}::Core
+ span
${EXTERNAL_DEPENDS}
INCLUDES
"${CMAKE_CURRENT_SOURCE_DIR}/../.."
diff --git a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
index 16c3621b6..ee82de43d 100644
--- a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
+++ b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
@@ -60,13 +60,12 @@ AbstractCommandExecutor::AbstractCommandExecutor(Logger logger, QObject *parent)
, m_logger(std::move(logger))
{
m_watchdog.setSingleShot(true);
- connect(&m_watchdog, &QTimer::timeout,
- this, [this]() {
- cancel(ErrorInfo{Tr::tr("Command cancelled because it exceeded the timeout.")});
+ connect(&m_watchdog, &QTimer::timeout, this, [this]() {
+ cancel(ErrorInfo{Tr::tr("Command cancelled because it exceeded the timeout: %1")
+ .arg(m_command->descriptionForCancelMessage(
+ m_transformer->product()->fullDisplayName()))});
});
- connect(this, &AbstractCommandExecutor::finished,
- &m_watchdog, &QTimer::stop);
-
+ connect(this, &AbstractCommandExecutor::finished, &m_watchdog, &QTimer::stop);
}
void AbstractCommandExecutor::start(Transformer *transformer, AbstractCommand *cmd)
diff --git a/src/lib/corelib/buildgraph/buildgraph.cpp b/src/lib/corelib/buildgraph/buildgraph.cpp
index 10aae5991..d8a7cfa64 100644
--- a/src/lib/corelib/buildgraph/buildgraph.cpp
+++ b/src/lib/corelib/buildgraph/buildgraph.cpp
@@ -535,8 +535,8 @@ bool findPath(BuildGraphNode *u, BuildGraphNode *v, QList<BuildGraphNode *> &pat
*/
void connect(BuildGraphNode *p, BuildGraphNode *c)
{
- QBS_CHECK(p != c);
qCDebug(lcBuildGraph).noquote() << "connect" << p->toString() << "->" << c->toString();
+ QBS_CHECK(p != c);
if (c->type() == BuildGraphNode::ArtifactNodeType) {
auto const ac = static_cast<Artifact *>(c);
for (const Artifact *child : filterByType<Artifact>(p->children)) {
diff --git a/src/lib/corelib/buildgraph/qtmocscanner.cpp b/src/lib/corelib/buildgraph/qtmocscanner.cpp
index 7df84e52c..fb9f08694 100644
--- a/src/lib/corelib/buildgraph/qtmocscanner.cpp
+++ b/src/lib/corelib/buildgraph/qtmocscanner.cpp
@@ -109,7 +109,7 @@ QtMocScanner::QtMocScanner(const ResolvedProductPtr &product, ScriptEngine *engi
attachPointerTo(scannerObj, this);
setJsProperty(engine->context(), targetScriptValue, qtMocScannerJsName(), scannerObj);
JSValue applyFunction = JS_NewCFunction(engine->context(), &js_apply, "QtMocScanner", 1);
- setJsProperty(engine->context(), scannerObj, QStringLiteral("apply"), applyFunction);
+ setJsProperty(engine->context(), scannerObj, std::string_view("apply"), applyFunction);
}
QtMocScanner::~QtMocScanner()
@@ -269,10 +269,13 @@ JSValue QtMocScanner::apply(ScriptEngine *engine, const Artifact *artifact)
JSValue obj = engine->newObject();
JSContext * const ctx = m_engine->context();
- setJsProperty(ctx, obj, QStringLiteral("hasQObjectMacro"), JS_NewBool(ctx, hasQObjectMacro));
- setJsProperty(ctx, obj, QStringLiteral("mustCompile"), JS_NewBool(ctx, mustCompile));
- setJsProperty(ctx, obj, QStringLiteral("hasPluginMetaDataMacro"),
- JS_NewBool(ctx, hasPluginMetaDataMacro));
+ setJsProperty(ctx, obj, std::string_view("hasQObjectMacro"), JS_NewBool(ctx, hasQObjectMacro));
+ setJsProperty(ctx, obj, std::string_view("mustCompile"), JS_NewBool(ctx, mustCompile));
+ setJsProperty(
+ ctx,
+ obj,
+ std::string_view("hasPluginMetaDataMacro"),
+ JS_NewBool(ctx, hasPluginMetaDataMacro));
engine->setUsesIo();
return obj;
}
diff --git a/src/lib/corelib/buildgraph/rulecommands.cpp b/src/lib/corelib/buildgraph/rulecommands.cpp
index 73d05eaca..be90c2fd5 100644
--- a/src/lib/corelib/buildgraph/rulecommands.cpp
+++ b/src/lib/corelib/buildgraph/rulecommands.cpp
@@ -135,6 +135,11 @@ QString AbstractCommand::fullDescription(const QString &productName) const
return description() + QLatin1String(" [") + productName + QLatin1Char(']');
}
+QString AbstractCommand::descriptionForCancelMessage(const QString &productName) const
+{
+ return fullDescription(productName);
+}
+
void AbstractCommand::load(PersistentPool &pool)
{
serializationOp<PersistentPool::Load>(pool);
@@ -335,6 +340,12 @@ void ProcessCommand::fillFromScriptValue(JSContext *ctx, const JSValue *scriptVa
applyCommandProperties(ctx, scriptValue);
}
+QString ProcessCommand::descriptionForCancelMessage(const QString &productName) const
+{
+ return description() + QLatin1String(" (") + QDir::toNativeSeparators(m_program)
+ + QLatin1String(") [") + productName + QLatin1Char(']');
+}
+
QStringList ProcessCommand::relevantEnvVars() const
{
QStringList vars = m_relevantEnvVars;
diff --git a/src/lib/corelib/buildgraph/rulecommands.h b/src/lib/corelib/buildgraph/rulecommands.h
index 7b08d1015..4296146d2 100644
--- a/src/lib/corelib/buildgraph/rulecommands.h
+++ b/src/lib/corelib/buildgraph/rulecommands.h
@@ -78,6 +78,7 @@ public:
virtual bool equals(const AbstractCommand *other) const;
virtual void fillFromScriptValue(JSContext *ctx, const JSValue *scriptValue,
const CodeLocation &codeLocation);
+ virtual QString descriptionForCancelMessage(const QString &productName) const;
QString fullDescription(const QString &productName) const;
const QString description() const { return m_description; }
@@ -129,6 +130,7 @@ public:
bool equals(const AbstractCommand *otherAbstractCommand) const override;
void fillFromScriptValue(JSContext *ctx, const JSValue *scriptValue,
const CodeLocation &codeLocation) override;
+ QString descriptionForCancelMessage(const QString &productName) const override;
const QString program() const { return m_program; }
const QStringList arguments() const { return m_arguments; }
const QString workingDir() const { return m_workingDir; }
diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp
index e07abd74a..94cee0c62 100644
--- a/src/lib/corelib/buildgraph/rulesapplicator.cpp
+++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp
@@ -420,11 +420,7 @@ RulesApplicator::OutputArtifactInfo RulesApplicator::createOutputArtifactFromRul
RulesApplicator::OutputArtifactInfo RulesApplicator::createOutputArtifact(const QString &filePath,
const FileTags &fileTags, bool alwaysUpdated, const ArtifactSet &inputArtifacts)
{
- QString outputPath = filePath;
- // don't let the output artifact "escape" its build dir
- outputPath.replace(StringConstants::dotDot(), QStringLiteral("dotdot"));
- outputPath = resolveOutPath(outputPath);
-
+ const QString outputPath = resolveOutPath(filePath);
if (m_rule->isDynamic()) {
const Set<FileTag> undeclaredTags = fileTags - m_rule->collectedOutputFileTags();
if (!undeclaredTags.empty()) {
@@ -676,9 +672,14 @@ Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const JSValue &ob
QString RulesApplicator::resolveOutPath(const QString &path) const
{
- QString buildDir = m_product->topLevelProject()->buildDirectory;
- QString result = FileInfo::resolvePath(buildDir, path);
- result = QDir::cleanPath(result);
+ const QString buildDir = m_product->topLevelProject()->buildDirectory;
+ QString result = QDir::cleanPath(FileInfo::resolvePath(buildDir, path));
+ if (!result.startsWith(buildDir + QLatin1Char('/'))) {
+ throw ErrorInfo(
+ Tr::tr("Refusing to create artifact '%1' outside of build directory '%2'.")
+ .arg(QDir::toNativeSeparators(result), QDir::toNativeSeparators(buildDir)),
+ m_rule->prepareScript.location());
+ }
return result;
}
diff --git a/src/lib/corelib/jsextensions/domxml.cpp b/src/lib/corelib/jsextensions/domxml.cpp
index 35cff186b..e065124e6 100644
--- a/src/lib/corelib/jsextensions/domxml.cpp
+++ b/src/lib/corelib/jsextensions/domxml.cpp
@@ -549,5 +549,5 @@ void initializeJsExtensionXml(qbs::Internal::ScriptEngine *engine, JSValue exten
JSValue contextObject = engine->newObject();
XmlDomNode<QDomNode>::registerClass(engine, contextObject);
XmlDomNode<QDomDocument>::registerClass(engine, contextObject);
- setJsProperty(engine->context(), extensionObject, QLatin1String("Xml"), contextObject);
+ setJsProperty(engine->context(), extensionObject, std::string_view("Xml"), contextObject);
}
diff --git a/src/lib/corelib/jsextensions/moduleproperties.cpp b/src/lib/corelib/jsextensions/moduleproperties.cpp
index 2c73f2c53..f3583c872 100644
--- a/src/lib/corelib/jsextensions/moduleproperties.cpp
+++ b/src/lib/corelib/jsextensions/moduleproperties.cpp
@@ -234,7 +234,7 @@ static void initModuleProperties(ScriptEngine *engine, JSValue objectWithPropert
{
JSContext * const ctx = engine->context();
JSValue func = JS_NewCFunction(ctx, js_moduleProperty<ProductOrArtifact>, "moduleProperty", 2);
- setJsProperty(ctx, objectWithProperties, QStringLiteral("moduleProperty"), func);
+ setJsProperty(ctx, objectWithProperties, std::string_view("moduleProperty"), func);
}
static JSValue setupBaseModuleScriptValue(ScriptEngine *engine, const ResolvedModule *module)
diff --git a/src/lib/corelib/language/builtindeclarations.cpp b/src/lib/corelib/language/builtindeclarations.cpp
index 491b005e8..44dc8a326 100644
--- a/src/lib/corelib/language/builtindeclarations.cpp
+++ b/src/lib/corelib/language/builtindeclarations.cpp
@@ -247,17 +247,11 @@ void BuiltinDeclarations::addDependsItem()
PropertyDeclaration::StringList);
item << PropertyDeclaration(StringConstants::limitToSubProjectProperty(),
PropertyDeclaration::Boolean, StringConstants::falseValue());
- item << PropertyDeclaration(StringConstants::multiplexConfigurationIdsProperty(),
- PropertyDeclaration::StringList, QString(),
- PropertyDeclaration::ReadOnlyFlag);
- PropertyDeclaration fallbackProp(
- StringConstants::enableFallbackProperty(),
- PropertyDeclaration::Boolean,
- StringConstants::falseValue());
- fallbackProp.setDeprecationInfo(DeprecationInfo(
- Version(2, 4),
- Tr::tr("The fallback provider has been deprecated. Use qbspkgconfig instead.")));
- item << fallbackProp;
+ item << PropertyDeclaration(
+ StringConstants::multiplexConfigurationIdsProperty(),
+ PropertyDeclaration::StringList,
+ QString(),
+ PropertyDeclaration::ReadOnlyFlag);
insert(item);
}
diff --git a/src/lib/corelib/language/evaluator.cpp b/src/lib/corelib/language/evaluator.cpp
index 084f2f4a9..288816bb6 100644
--- a/src/lib/corelib/language/evaluator.cpp
+++ b/src/lib/corelib/language/evaluator.cpp
@@ -464,10 +464,15 @@ static int getEvalPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, uint32_t
class PropertyStackManager
{
public:
- PropertyStackManager(const Item *itemOfProperty, const QString &name, const Value *value,
- std::stack<QualifiedId> &requestedProperties,
- PropertyDependencies &propertyDependencies)
+ PropertyStackManager(
+ const Item *itemOfProperty,
+ const QString &name,
+ const Value *value,
+ std::stack<QualifiedId> &requestedProperties,
+ PropertyDependencies &propertyDependencies,
+ Evaluator::EvalStack &evalStack)
: m_requestedProperties(requestedProperties)
+ , m_evalStack(evalStack)
{
if (value->type() == Value::JSSourceValueType
&& (itemOfProperty->type() == ItemType::ModuleInstance
@@ -484,16 +489,31 @@ public:
propertyDependencies[fullPropName].insert(requestedProperties.top());
m_requestedProperties.push(fullPropName);
}
+ const auto matcher = [value](const std::pair<QString, const Value *> &prop) {
+ return prop.second == value;
+ };
+ if (auto it = std::find_if(m_evalStack.cbegin(), m_evalStack.cend(), matcher);
+ it != m_evalStack.cend()) {
+ ErrorInfo error(Tr::tr("Property '%1' refers to itself.").arg(name), value->location());
+ for (auto it2 = std::next(it); it2 != m_evalStack.cend(); ++it2) {
+ error.append(
+ QString::fromLatin1(" via '%1'").arg(it2->first), it2->second->location());
+ }
+ throw ErrorInfo(error);
+ }
+ m_evalStack.emplace_back(name, value);
}
~PropertyStackManager()
{
if (m_stackUpdate)
m_requestedProperties.pop();
+ m_evalStack.pop_back();
}
private:
std::stack<QualifiedId> &m_requestedProperties;
+ Evaluator::EvalStack &m_evalStack;
bool m_stackUpdate = false;
};
@@ -904,9 +924,13 @@ static EvalResult getEvalProperty(ScriptEngine *engine, JSValue obj, const Item
if (!value)
continue;
const Item * const itemOfProperty = item; // The item that owns the property.
- PropertyStackManager propStackmanager(itemOfProperty, name, value.get(),
- evaluator->requestedProperties(),
- evaluator->propertyDependencies());
+ PropertyStackManager propStackmanager(
+ itemOfProperty,
+ name,
+ value.get(),
+ evaluator->requestedProperties(),
+ evaluator->propertyDependencies(),
+ evaluator->evalStack());
JSValue result;
if (evaluator->cachingEnabled()) {
data->evaluator->clearCacheIfInvalidated(*data);
diff --git a/src/lib/corelib/language/evaluator.h b/src/lib/corelib/language/evaluator.h
index d86e08eb1..b27b2e4c6 100644
--- a/src/lib/corelib/language/evaluator.h
+++ b/src/lib/corelib/language/evaluator.h
@@ -48,10 +48,12 @@
#include <QtCore/qhash.h>
+#include <deque>
#include <functional>
#include <mutex>
#include <optional>
#include <stack>
+#include <utility>
namespace qbs {
namespace Internal {
@@ -111,6 +113,9 @@ public:
std::stack<QualifiedId> &requestedProperties() { return m_requestedProperties; }
+ using EvalStack = std::deque<std::pair<QString, const Value *>>;
+ EvalStack &evalStack() { return m_evalStack; }
+
void handleEvaluationError(const Item *item, const QString &name);
QString pathPropertiesBaseDir() const { return m_pathPropertiesBaseDir; }
@@ -131,6 +136,7 @@ private:
QString m_pathPropertiesBaseDir;
PropertyDependencies m_propertyDependencies;
std::stack<QualifiedId> m_requestedProperties;
+ EvalStack m_evalStack;
std::mutex m_cacheInvalidationMutex;
Set<const Item *> m_invalidatedCaches;
bool m_valueCacheEnabled = false;
diff --git a/src/lib/corelib/language/scriptengine.cpp b/src/lib/corelib/language/scriptengine.cpp
index 9131db7f5..6c0e4d770 100644
--- a/src/lib/corelib/language/scriptengine.cpp
+++ b/src/lib/corelib/language/scriptengine.cpp
@@ -137,18 +137,25 @@ LookupResult ScriptEngine::doExtraScopeLookup(JSContext *ctx, JSAtom prop)
ScriptEngine * const engine = engineForContext(ctx);
engine->m_lastLookupWasSuccess = false;
- JSValueList scopes;
- if (!engine->m_scopeChains.isEmpty())
- scopes = engine->m_scopeChains.last();
- if (JS_IsObject(engine->m_globalObject))
- scopes.insert(scopes.begin(), engine->m_globalObject);
- for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
- const JSValue v = JS_GetProperty(ctx, *it, prop);
+ auto handleScope = [ctx, prop, engine](const JSValue &scope) -> LookupResult {
+ const JSValue v = JS_GetProperty(ctx, scope, prop);
if (!JS_IsUndefined(v) || engine->m_lastLookupWasSuccess) {
engine->m_lastLookupWasSuccess = false;
- return {v, *it, true};
+ return {v, scope, true};
+ }
+ return fail;
+ };
+
+ if (!engine->m_scopeChains.empty()) {
+ const JSValueList &scopes = engine->m_scopeChains.back().get();
+ for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
+ const auto res = handleScope(*it);
+ if (res.useResult)
+ return res;
}
}
+ if (JS_IsObject(engine->m_globalObject))
+ return handleScope(engine->m_globalObject);
return fail;
}
@@ -510,8 +517,7 @@ JSValue ScriptEngine::asJsValue(const QVariant &v, quintptr id, bool frozen)
case QMetaType::Bool:
return JS_NewBool(m_context, v.toBool());
case QMetaType::QDateTime:
- return JS_NewDate(
- m_context, v.toDateTime().toString(Qt::ISODateWithMs).toUtf8().constData());
+ return JS_NewDate(m_context, v.toDateTime().toMSecsSinceEpoch());
case QMetaType::QVariantMap:
return asJsValue(v.toMap(), id, frozen);
default:
@@ -538,7 +544,7 @@ JSValue ScriptEngine::asJsValue(const QString &s)
JSValue ScriptEngine::asJsValue(const QStringList &l)
{
JSValue array = JS_NewArray(m_context);
- setJsProperty(m_context, array, QLatin1String("length"), JS_NewInt32(m_context, l.size()));
+ setJsProperty(m_context, array, std::string_view("length"), JS_NewInt32(m_context, l.size()));
for (int i = 0; i < l.size(); ++i)
JS_SetPropertyUint32(m_context, array, i, asJsValue(l.at(i)));
return array;
@@ -574,7 +580,7 @@ JSValue ScriptEngine::asJsValue(const QVariantList &l, quintptr id, bool frozen)
return JS_DupValue(m_context, it.value());
frozen = id || frozen;
JSValue array = JS_NewArray(m_context);
- setJsProperty(m_context, array, QLatin1String("length"), JS_NewInt32(m_context, l.size()));
+ setJsProperty(m_context, array, std::string_view("length"), JS_NewInt32(m_context, l.size()));
for (int i = 0; i < l.size(); ++i)
JS_SetPropertyUint32(m_context, array, i, asJsValue(l.at(i), 0, frozen));
if (frozen)
@@ -805,14 +811,14 @@ JSValue ScriptEngine::newArray(int length, JsValueOwner owner)
JSValue ScriptEngine::evaluate(JsValueOwner resultOwner, const QString &code,
const QString &filePath, int line, const JSValueList &scopeChain)
{
- m_scopeChains << scopeChain;
+ m_scopeChains.emplace_back(scopeChain);
const QByteArray &codeStr = code.toUtf8();
m_evalPositions.emplace(filePath, line);
const JSValue v = JS_EvalThis(m_context, globalObject(), codeStr.constData(), codeStr.length(),
filePath.toUtf8().constData(), line, JS_EVAL_TYPE_GLOBAL);
m_evalPositions.pop();
- m_scopeChains.removeLast();
+ m_scopeChains.pop_back();
if (resultOwner == JsValueOwner::ScriptEngine && JS_VALUE_HAS_REF_COUNT(v))
++m_evalResults[v];
return v;
diff --git a/src/lib/corelib/language/scriptengine.h b/src/lib/corelib/language/scriptengine.h
index 4a55392e3..8efa2d482 100644
--- a/src/lib/corelib/language/scriptengine.h
+++ b/src/lib/corelib/language/scriptengine.h
@@ -392,7 +392,7 @@ private:
std::unordered_map<const ResolvedModule *, JSValue> m_moduleArtifactsMapScriptValues;
std::unordered_map<const ResolvedProject *, JSValue> m_projectScriptValues;
std::unordered_map<const ResolvedModule *, JSValue> m_baseModuleScriptValues;
- QList<JSValueList> m_scopeChains;
+ std::vector<std::reference_wrapper<const JSValueList>> m_scopeChains;
JSValueList m_contextStack;
QHash<JSClassID, JSClassExoticMethods> m_exoticMethods;
QHash<QString, JSClassID> m_classes;
diff --git a/src/lib/corelib/loader/dependenciesresolver.cpp b/src/lib/corelib/loader/dependenciesresolver.cpp
index 479318e73..059592e9c 100644
--- a/src/lib/corelib/loader/dependenciesresolver.cpp
+++ b/src/lib/corelib/loader/dependenciesresolver.cpp
@@ -89,7 +89,6 @@ public:
VersionRange versionRange;
QVariantMap parameters;
bool limitToSubProject = false;
- FallbackMode fallbackMode = FallbackMode::Enabled;
bool requiredLocally = true;
bool requiredGlobally = true;
};
@@ -123,7 +122,6 @@ public:
VersionRange versionRange;
QVariantMap parameters;
bool limitToSubProject = false;
- FallbackMode fallbackMode = FallbackMode::Enabled;
bool requiredLocally = true;
bool requiredGlobally = true;
bool checkProduct = true;
@@ -592,8 +590,8 @@ Item *DependenciesResolver::findMatchingModule(
return nullptr;
}
- if (Item *moduleItem = searchAndLoadModuleFile(m_loaderState, m_product, dependency.location(),
- dependency.name, dependency.fallbackMode)) {
+ if (Item *moduleItem = searchAndLoadModuleFile(
+ m_loaderState, m_product, dependency.location(), dependency.name)) {
QBS_CHECK(moduleItem->type() == ItemType::Module);
Item * const proto = moduleItem;
ModuleItemLocker locker(*moduleItem);
@@ -849,11 +847,6 @@ std::optional<EvaluatedDependsItem> DependenciesResolver::evaluateDependsItem(It
item->location());
}
- const FallbackMode fallbackMode
- = m_loaderState.parameters().fallbackProviderEnabled()
- && evaluator.boolValue(item, StringConstants::enableFallbackProperty())
- ? FallbackMode::Enabled : FallbackMode::Disabled;
-
bool profilesPropertyWasSet = false;
std::optional<QStringList> profiles;
bool required = true;
@@ -880,9 +873,16 @@ std::optional<EvaluatedDependsItem> DependenciesResolver::evaluateDependsItem(It
if (!productTypeTags.empty())
m_product.bulkDependencies.emplace_back(productTypeTags, item->location());
return EvaluatedDependsItem{
- item, QualifiedId::fromString(name), submodules, productTypeTags,
- multiplexIds, profiles, {minVersion, maxVersion}, parameters, limitToSubProject,
- fallbackMode, required};
+ item,
+ QualifiedId::fromString(name),
+ submodules,
+ productTypeTags,
+ multiplexIds,
+ profiles,
+ {minVersion, maxVersion},
+ parameters,
+ limitToSubProject,
+ required};
}
// Potentially multiplexes a dependency along Depends.productTypes, Depends.subModules and
@@ -1036,28 +1036,33 @@ Item::Module DependenciesResolver::createModule(
FullyResolvedDependsItem::FullyResolvedDependsItem(
ProductContext *product, const EvaluatedDependsItem &dependency)
- : product(product), item(dependency.item), name(product->name),
- versionRange(dependency.versionRange), parameters(dependency.parameters),
- fallbackMode(FallbackMode::Disabled), checkProduct(false) {}
+ : product(product)
+ , item(dependency.item)
+ , name(product->name)
+ , versionRange(dependency.versionRange)
+ , parameters(dependency.parameters)
+ , checkProduct(false)
+{}
FullyResolvedDependsItem FullyResolvedDependsItem::makeBaseDependency()
{
FullyResolvedDependsItem item;
- item.fallbackMode = FallbackMode::Disabled;
item.name = StringConstants::qbsModule();
return item;
}
FullyResolvedDependsItem::FullyResolvedDependsItem(
const EvaluatedDependsItem &dependency, QualifiedId name, QString profile, QString multiplexId)
- : item(dependency.item), name(std::move(name)),
- profile(std::move(profile)), multiplexId(std::move(multiplexId)),
- versionRange(dependency.versionRange),
- parameters(dependency.parameters),
- limitToSubProject(dependency.limitToSubProject),
- fallbackMode(dependency.fallbackMode),
- requiredLocally(dependency.requiredLocally),
- requiredGlobally(dependency.requiredGlobally) {}
+ : item(dependency.item)
+ , name(std::move(name))
+ , profile(std::move(profile))
+ , multiplexId(std::move(multiplexId))
+ , versionRange(dependency.versionRange)
+ , parameters(dependency.parameters)
+ , limitToSubProject(dependency.limitToSubProject)
+ , requiredLocally(dependency.requiredLocally)
+ , requiredGlobally(dependency.requiredGlobally)
+{}
QString FullyResolvedDependsItem::id() const
{
diff --git a/src/lib/corelib/loader/itemreaderastvisitor.cpp b/src/lib/corelib/loader/itemreaderastvisitor.cpp
index fe0d6c190..c3e6b9b89 100644
--- a/src/lib/corelib/loader/itemreaderastvisitor.cpp
+++ b/src/lib/corelib/loader/itemreaderastvisitor.cpp
@@ -248,6 +248,8 @@ bool ItemReaderASTVisitor::visit(AST::UiScriptBinding *ast)
const auto * const idExp = AST::cast<AST::IdentifierExpression *>(expStmt->expression);
if (Q_UNLIKELY(!idExp || idExp->name.isEmpty()))
throw ErrorInfo(Tr::tr("id: must be followed by identifier"));
+ if (m_item->type() == ItemType::Module)
+ throw ErrorInfo(Tr::tr("Module items cannot have an id property."));
m_item->m_id = idExp->name.toString();
m_file->ensureIdScope(m_itemPool);
ItemValueConstPtr existingId = m_file->idScope()->itemProperty(m_item->id(), *m_itemPool);
diff --git a/src/lib/corelib/loader/loaderutils.h b/src/lib/corelib/loader/loaderutils.h
index 3f967ba08..4a4aadfb8 100644
--- a/src/lib/corelib/loader/loaderutils.h
+++ b/src/lib/corelib/loader/loaderutils.h
@@ -83,7 +83,6 @@ class ScriptEngine;
using ModulePropertiesPerGroup = std::unordered_map<const Item *, QualifiedIdSet>;
using FileLocations = QHash<std::pair<QString, QString>, CodeLocation>;
-enum class FallbackMode { Enabled, Disabled };
enum class Deferral { Allowed, NotAllowed };
enum class ProductDependency { None, Single, Bulk };
diff --git a/src/lib/corelib/loader/moduleloader.cpp b/src/lib/corelib/loader/moduleloader.cpp
index 80aa3f17c..d26849655 100644
--- a/src/lib/corelib/loader/moduleloader.cpp
+++ b/src/lib/corelib/loader/moduleloader.cpp
@@ -68,12 +68,15 @@ namespace qbs::Internal {
class ModuleLoader
{
public:
- ModuleLoader(LoaderState &loaderState, ProductContext &product,
- const CodeLocation &dependsItemLocation, const QualifiedId &moduleName,
- FallbackMode fallbackMode)
- : m_loaderState(loaderState), m_product(product),
- m_dependsItemLocation(dependsItemLocation), m_moduleName(moduleName),
- m_fallbackMode(fallbackMode)
+ ModuleLoader(
+ LoaderState &loaderState,
+ ProductContext &product,
+ const CodeLocation &dependsItemLocation,
+ const QualifiedId &moduleName)
+ : m_loaderState(loaderState)
+ , m_product(product)
+ , m_dependsItemLocation(dependsItemLocation)
+ , m_moduleName(moduleName)
{}
Item *load();
@@ -92,7 +95,6 @@ private:
ProductContext &m_product;
const CodeLocation &m_dependsItemLocation;
const QualifiedId &m_moduleName;
- const FallbackMode m_fallbackMode;
};
struct PrioritizedItem
@@ -142,11 +144,13 @@ static Item *chooseModuleCandidate(const std::vector<PrioritizedItem> &candidate
return maxIt->item;
}
-Item *searchAndLoadModuleFile(LoaderState &loaderState, ProductContext &product,
- const CodeLocation &dependsItemLocation, const QualifiedId &moduleName,
- FallbackMode fallbackMode)
+Item *searchAndLoadModuleFile(
+ LoaderState &loaderState,
+ ProductContext &product,
+ const CodeLocation &dependsItemLocation,
+ const QualifiedId &moduleName)
{
- return ModuleLoader(loaderState, product, dependsItemLocation, moduleName, fallbackMode).load();
+ return ModuleLoader(loaderState, product, dependsItemLocation, moduleName).load();
}
Item *ModuleLoader::load()
@@ -157,8 +161,8 @@ Item *ModuleLoader::load()
if (existingPaths.isEmpty()) { // no suitable names found, try to use providers
AccumulatingTimer providersTimer(m_loaderState.parameters().logElapsedTime()
? &m_product.timingData.moduleProviders : nullptr);
- auto result = ModuleProviderLoader(m_loaderState).executeModuleProviders(
- m_product, m_dependsItemLocation, m_moduleName, m_fallbackMode);
+ auto result = ModuleProviderLoader(m_loaderState)
+ .executeModuleProviders(m_product, m_dependsItemLocation, m_moduleName);
if (result.searchPaths) {
qCDebug(lcModuleLoader) << "Re-checking for module" << m_moduleName.toString()
<< "with newly added search paths from module provider";
diff --git a/src/lib/corelib/loader/moduleloader.h b/src/lib/corelib/loader/moduleloader.h
index 60567e60e..b07f01836 100644
--- a/src/lib/corelib/loader/moduleloader.h
+++ b/src/lib/corelib/loader/moduleloader.h
@@ -42,15 +42,16 @@
namespace qbs {
class CodeLocation;
namespace Internal {
-enum class FallbackMode;
class Item;
class LoaderState;
class ProductContext;
class QualifiedId;
-Item *searchAndLoadModuleFile(LoaderState &loaderState, ProductContext &product,
- const CodeLocation &dependsItemLocation,
- const QualifiedId &moduleName, FallbackMode fallbackMode);
+Item *searchAndLoadModuleFile(
+ LoaderState &loaderState,
+ ProductContext &product,
+ const CodeLocation &dependsItemLocation,
+ const QualifiedId &moduleName);
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/loader/moduleproviderloader.cpp b/src/lib/corelib/loader/moduleproviderloader.cpp
index 212ad75b3..d0789facd 100644
--- a/src/lib/corelib/loader/moduleproviderloader.cpp
+++ b/src/lib/corelib/loader/moduleproviderloader.cpp
@@ -76,10 +76,9 @@ ModuleProviderLoader::ModuleProviderLoader(LoaderState &loaderState)
: m_loaderState(loaderState) {}
ModuleProviderLoader::ModuleProviderResult ModuleProviderLoader::executeModuleProviders(
- ProductContext &productContext,
- const CodeLocation &dependsItemLocation,
- const QualifiedId &moduleName,
- FallbackMode fallbackMode)
+ ProductContext &productContext,
+ const CodeLocation &dependsItemLocation,
+ const QualifiedId &moduleName)
{
ModuleProviderLoader::ModuleProviderResult result;
try {
@@ -98,18 +97,6 @@ ModuleProviderLoader::ModuleProviderResult ModuleProviderLoader::executeModulePr
}
result = executeModuleProvidersHelper(
productContext, dependsItemLocation, moduleName, providersToRun);
-
- if (fallbackMode == FallbackMode::Enabled
- && !result.providerFound
- && !providerNames) {
- qCDebug(lcModuleLoader) << "Specific module provider not found for"
- << moduleName.toString() << ", setting up fallback.";
- result = executeModuleProvidersHelper(
- productContext,
- dependsItemLocation,
- moduleName,
- {{moduleName, ModuleProviderLookup::Fallback}});
- }
} catch (const ErrorInfo &error) {
auto ei = error;
ei.prepend(
@@ -291,9 +278,6 @@ QString ModuleProviderLoader::findModuleProviderFile(
fullPath = FileInfo::resolvePath(fullPath, component);
fullPath = FileInfo::resolvePath(fullPath, QStringLiteral("provider.qbs"));
break;
- case ModuleProviderLookup::Fallback:
- fullPath = FileInfo::resolvePath(fullPath, QStringLiteral("__fallback/provider.qbs"));
- break;
}
if (!FileInfo::exists(fullPath)) {
qCDebug(lcModuleLoader) << "No module provider found at" << fullPath;
diff --git a/src/lib/corelib/loader/moduleproviderloader.h b/src/lib/corelib/loader/moduleproviderloader.h
index 0b1145db5..471cfbb02 100644
--- a/src/lib/corelib/loader/moduleproviderloader.h
+++ b/src/lib/corelib/loader/moduleproviderloader.h
@@ -67,13 +67,12 @@ public:
std::optional<QStringList> searchPaths;
};
ModuleProviderResult executeModuleProviders(
- ProductContext &productContext,
- const CodeLocation &dependsItemLocation,
- const QualifiedId &moduleName,
- FallbackMode fallbackMode);
+ ProductContext &productContext,
+ const CodeLocation &dependsItemLocation,
+ const QualifiedId &moduleName);
private:
- enum class ModuleProviderLookup { Scoped, Named, Fallback };
+ enum class ModuleProviderLookup { Scoped, Named };
struct Provider {
QualifiedId name;
ModuleProviderLookup lookup;
diff --git a/src/lib/corelib/tools/codelocation.cpp b/src/lib/corelib/tools/codelocation.cpp
index f04041e14..7ab1deb13 100644
--- a/src/lib/corelib/tools/codelocation.cpp
+++ b/src/lib/corelib/tools/codelocation.cpp
@@ -53,64 +53,12 @@
namespace qbs {
-class CodeLocation::CodeLocationPrivate : public QSharedData
-{
-public:
- void load(Internal::PersistentPool &pool)
- {
- pool.load(filePath);
- pool.load(line);
- pool.load(column);
- }
-
- void store(Internal::PersistentPool &pool) const
- {
- pool.store(filePath);
- pool.store(line);
- pool.store(column);
- }
-
- QString filePath;
- int line = 0;
- int column = 0;
-};
-
-CodeLocation::CodeLocation() = default;
-
CodeLocation::CodeLocation(const QString &aFilePath, int aLine, int aColumn, bool checkPath)
- : d(new CodeLocationPrivate)
{
QBS_ASSERT(!checkPath || Internal::FileInfo::isAbsolute(aFilePath), qDebug() << aFilePath);
- d->filePath = aFilePath;
- d->line = aLine;
- d->column = aColumn;
-}
-
-CodeLocation::CodeLocation(const CodeLocation &other) = default;
-CodeLocation::CodeLocation(CodeLocation &&other) noexcept = default;
-CodeLocation &CodeLocation::operator=(const CodeLocation &other) = default;
-CodeLocation &CodeLocation::operator=(CodeLocation &&other) noexcept = default;
-
-CodeLocation::~CodeLocation() = default;
-
-QString CodeLocation::filePath() const
-{
- return d ? d->filePath : QString();
-}
-
-int CodeLocation::line() const
-{
- return d ? d->line : -1;
-}
-
-int CodeLocation::column() const
-{
- return d ? d->column : -1;
-}
-
-bool CodeLocation::isValid() const
-{
- return !filePath().isEmpty();
+ m_filePath = aFilePath;
+ m_line = aLine;
+ m_column = aColumn;
}
QString CodeLocation::toString() const
@@ -145,15 +93,18 @@ void CodeLocation::load(Internal::PersistentPool &pool)
const bool isValid = pool.load<bool>();
if (!isValid)
return;
- d = new CodeLocationPrivate;
- pool.load(*d);
+ pool.load(m_filePath);
+ pool.load(m_line);
+ pool.load(m_column);
}
void CodeLocation::store(Internal::PersistentPool &pool) const
{
- if (d) {
+ if (isValid()) {
pool.store(true);
- pool.store(*d);
+ pool.store(m_filePath);
+ pool.store(m_line);
+ pool.store(m_column);
} else {
pool.store(false);
}
@@ -161,10 +112,8 @@ void CodeLocation::store(Internal::PersistentPool &pool) const
bool operator==(const CodeLocation &cl1, const CodeLocation &cl2)
{
- if (cl1.d == cl2.d)
- return true;
return cl1.filePath() == cl2.filePath() && cl1.line() == cl2.line()
- && cl1.column() == cl2.column();
+ && cl1.column() == cl2.column();
}
bool operator!=(const CodeLocation &cl1, const CodeLocation &cl2)
diff --git a/src/lib/corelib/tools/codelocation.h b/src/lib/corelib/tools/codelocation.h
index afcd2e075..aa82ab4e1 100644
--- a/src/lib/corelib/tools/codelocation.h
+++ b/src/lib/corelib/tools/codelocation.h
@@ -57,21 +57,17 @@ namespace Internal { class PersistentPool; }
class QBS_EXPORT CodeLocation
{
friend QBS_EXPORT bool operator==(const CodeLocation &cl1, const CodeLocation &cl2);
+
public:
- CodeLocation();
- explicit CodeLocation(const QString &aFilePath, int aLine = -1, int aColumn = -1,
- bool checkPath = true);
- CodeLocation(const CodeLocation &other);
- CodeLocation(CodeLocation &&other) noexcept;
- CodeLocation &operator=(const CodeLocation &other);
- CodeLocation &operator=(CodeLocation &&other) noexcept;
- ~CodeLocation();
-
- QString filePath() const;
- int line() const;
- int column() const;
-
- bool isValid() const;
+ CodeLocation() = default;
+ explicit CodeLocation(
+ const QString &aFilePath, int aLine = -1, int aColumn = -1, bool checkPath = true);
+
+ const QString &filePath() const noexcept { return m_filePath; }
+ int line() const noexcept { return m_line; }
+ int column() const noexcept { return m_column; }
+
+ bool isValid() const noexcept { return !m_filePath.isEmpty(); }
QString toString() const;
QJsonObject toJson() const;
@@ -79,8 +75,9 @@ public:
void store(Internal::PersistentPool &pool) const;
private:
- class CodeLocationPrivate;
- QExplicitlySharedDataPointer<CodeLocationPrivate> d;
+ QString m_filePath;
+ int m_line = 0;
+ int m_column = 0;
};
QBS_EXPORT bool operator==(const CodeLocation &cl1, const CodeLocation &cl2);
diff --git a/src/lib/corelib/tools/scripttools.cpp b/src/lib/corelib/tools/scripttools.cpp
index e89e4a0ad..6aa44adbb 100644
--- a/src/lib/corelib/tools/scripttools.cpp
+++ b/src/lib/corelib/tools/scripttools.cpp
@@ -136,10 +136,15 @@ JSValue getJsProperty(JSContext *ctx, JSValue obj, const QString &prop)
return JS_GetPropertyStr(ctx, obj, prop.toUtf8().constData());
}
+void setJsProperty(JSContext *ctx, JSValueConst obj, std::string_view prop, JSValue val)
+{
+ JS_SetPropertyStr(ctx, obj, prop.data(), val);
+}
+
void setJsProperty(JSContext *ctx, JSValue obj, const QString &prop, JSValue val)
{
- if (JS_SetPropertyStr(ctx, obj, prop.toUtf8().constData(), val) <= 0)
- qDebug() << "Oje!";
+ const auto propUtf8 = prop.toUtf8();
+ setJsProperty(ctx, obj, std::string_view{propUtf8.data(), size_t(propUtf8.size())}, val);
}
void setJsProperty(JSContext *ctx, JSValue obj, const QString &prop, const QString &val)
diff --git a/src/lib/corelib/tools/scripttools.h b/src/lib/corelib/tools/scripttools.h
index ac7ed9928..20964cae5 100644
--- a/src/lib/corelib/tools/scripttools.h
+++ b/src/lib/corelib/tools/scripttools.h
@@ -50,6 +50,7 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qvariant.h>
+#include <string_view>
#include <utility>
#include <vector>
@@ -62,6 +63,7 @@ using JSValueList = std::vector<JSValue>;
void defineJsProperty(JSContext *ctx, JSValueConst obj, const QString &prop, JSValue val);
JSValue getJsProperty(JSContext *ctx, JSValueConst obj, const QString &prop);
+void setJsProperty(JSContext *ctx, JSValueConst obj, std::string_view prop, JSValue val);
void setJsProperty(JSContext *ctx, JSValueConst obj, const QString &prop, JSValue val);
void setJsProperty(JSContext *ctx, JSValueConst obj, const QString &prop, const QString &val);
QString getJsStringProperty(JSContext *ctx, JSValueConst obj, const QString &prop);
diff --git a/src/lib/corelib/tools/setupprojectparameters.cpp b/src/lib/corelib/tools/setupprojectparameters.cpp
index 185323c09..e9212c165 100644
--- a/src/lib/corelib/tools/setupprojectparameters.cpp
+++ b/src/lib/corelib/tools/setupprojectparameters.cpp
@@ -99,7 +99,6 @@ public:
bool logElapsedTime;
bool forceProbeExecution;
bool waitLockBuildGraph;
- bool fallbackProviderEnabled = true;
SetupProjectParameters::RestoreBehavior restoreBehavior;
ErrorHandlingMode propertyCheckingMode;
ErrorHandlingMode productErrorMode;
@@ -166,7 +165,6 @@ SetupProjectParameters SetupProjectParameters::fromJson(const QJsonObject &data)
setValueFromJson(params.d->logElapsedTime, data, "log-time");
setValueFromJson(params.d->forceProbeExecution, data, "force-probe-execution");
setValueFromJson(params.d->waitLockBuildGraph, data, "wait-lock-build-graph");
- setValueFromJson(params.d->fallbackProviderEnabled, data, "fallback-provider-enabled");
setValueFromJson(params.d->environment, data, "environment");
setValueFromJson(params.d->restoreBehavior, data, "restore-behavior");
setValueFromJson(params.d->propertyCheckingMode, data, "error-handling-mode");
@@ -623,22 +621,6 @@ void SetupProjectParameters::setWaitLockBuildGraph(bool wait)
}
/*!
- * \brief Returns true if qbs should fall back to pkg-config if a dependency is not found.
- */
-bool SetupProjectParameters::fallbackProviderEnabled() const
-{
- return d->fallbackProviderEnabled;
-}
-
-/*!
- * Controls whether to fall back to pkg-config if a dependency is not found.
- */
-void SetupProjectParameters::setFallbackProviderEnabled(bool enable)
-{
- d->fallbackProviderEnabled = enable;
-}
-
-/*!
* \brief Gets the environment used while resolving the project.
*/
QProcessEnvironment SetupProjectParameters::environment() const
diff --git a/src/lib/corelib/tools/setupprojectparameters.h b/src/lib/corelib/tools/setupprojectparameters.h
index 76b038752..5cd9700a9 100644
--- a/src/lib/corelib/tools/setupprojectparameters.h
+++ b/src/lib/corelib/tools/setupprojectparameters.h
@@ -132,9 +132,6 @@ public:
bool waitLockBuildGraph() const;
void setWaitLockBuildGraph(bool wait);
- bool fallbackProviderEnabled() const;
- void setFallbackProviderEnabled(bool enable);
-
QProcessEnvironment environment() const;
void setEnvironment(const QProcessEnvironment &env);
QProcessEnvironment adjustedEnvironment() const;
diff --git a/src/lib/corelib/tools/span.h b/src/lib/corelib/tools/span.h
new file mode 100644
index 000000000..e5553115c
--- /dev/null
+++ b/src/lib/corelib/tools/span.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QBS_SPAN_H
+#define QBS_SPAN_H
+
+#include <qcompilerdetection.h>
+
+// The (Apple) Clang implementation of span is incomplete until LLVM 15 / Xcode 14.3 / macOS 13
+#if __cplusplus >= 202002L \
+ && !(defined(__apple_build_version__) && __apple_build_version__ < 14030022)
+#include <span>
+
+namespace qbs {
+namespace Internal {
+using std::as_bytes;
+using std::as_writable_bytes;
+using std::get;
+using std::span;
+} // namespace Internal
+} // namespace qbs
+
+#else
+QT_WARNING_PUSH
+
+#if defined(Q_CC_MSVC)
+#pragma system_header
+#elif defined(Q_CC_GNU) || defined(Q_CC_CLANG)
+#pragma GCC system_header
+#endif
+
+// disable automatic usage of std::span in span-lite
+// since we make that decision ourselves at the top of this header
+#define span_CONFIG_SELECT_SPAN span_SPAN_NONSTD
+
+#include <span.hpp>
+namespace qbs {
+namespace Internal {
+using namespace nonstd;
+} // namespace Internal
+} // namespace qbs
+
+QT_WARNING_POP
+#endif
+
+#endif // QBS_SPAN_H \ No newline at end of file
diff --git a/src/lib/corelib/tools/stringutils.h b/src/lib/corelib/tools/stringutils.h
index 59acdccbd..93b419b00 100644
--- a/src/lib/corelib/tools/stringutils.h
+++ b/src/lib/corelib/tools/stringutils.h
@@ -97,34 +97,6 @@ static inline std::string trimmed(const std::string &s)
return trim(copy);
}
-static inline bool startsWith(const std::string &subject, const std::string &s)
-{
- if (s.size() <= subject.size())
- return std::equal(s.begin(), s.end(), subject.begin());
- return false;
-}
-
-static inline bool startsWith(const std::string &subject, char c)
-{
- std::string s;
- s.push_back(c);
- return startsWith(subject, s);
-}
-
-static inline bool endsWith(const std::string &subject, const std::string &s)
-{
- if (s.size() <= subject.size())
- return std::equal(s.rbegin(), s.rend(), subject.rbegin());
- return false;
-}
-
-static inline bool endsWith(const std::string &subject, char c)
-{
- std::string s;
- s.push_back(c);
- return endsWith(subject, s);
-}
-
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/pkgconfig/CMakeLists.txt b/src/lib/pkgconfig/CMakeLists.txt
index c82edac16..8db179354 100644
--- a/src/lib/pkgconfig/CMakeLists.txt
+++ b/src/lib/pkgconfig/CMakeLists.txt
@@ -8,12 +8,6 @@ set(SOURCES
)
list_transform_prepend(SOLUTION_SOURCES solution/)
-if(APPLE OR MINGW)
- set(HAS_STD_FILESYSTEM "0")
-else()
- set(HAS_STD_FILESYSTEM "1")
-endif()
-
set(QBS_PKGCONFIG_PUBLIC_DEPENDS "")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
set(QBS_PKGCONFIG_PUBLIC_DEPENDS "stdc++fs")
@@ -24,9 +18,8 @@ add_qbs_library(qbspkgconfig
DEFINES
"PKG_CONFIG_PC_PATH=\"${CMAKE_INSTALL_PREFIX}/${QBS_LIBDIR_NAME}/pkgconfig:${CMAKE_INSTALL_PREFIX}/share/pkgconfig:/usr/${QBS_LIBDIR_NAME}/pkgconfig/:/usr/share/pkgconfig/\""
"PKG_CONFIG_SYSTEM_LIBRARY_PATH=\"/usr/${QBS_LIBDIR_NAME}\""
- "HAS_STD_FILESYSTEM=${HAS_STD_FILESYSTEM}"
PUBLIC_DEFINES
"QBS_PC_WITH_QT_SUPPORT=1"
- PUBLIC_DEPENDS Qt${QT_VERSION_MAJOR}::Core ${QBS_PKGCONFIG_PUBLIC_DEPENDS} qbsvariant
+ PUBLIC_DEPENDS ${QBS_PKGCONFIG_PUBLIC_DEPENDS}
SOURCES ${SOURCES}
)
diff --git a/src/lib/pkgconfig/pcpackage.h b/src/lib/pkgconfig/pcpackage.h
index 794e2fc40..7e40b7c09 100644
--- a/src/lib/pkgconfig/pcpackage.h
+++ b/src/lib/pkgconfig/pcpackage.h
@@ -40,8 +40,6 @@
#ifndef PC_PACKAGE_H
#define PC_PACKAGE_H
-#include <variant.h>
-
#include <map>
#include <optional>
#include <stdexcept>
@@ -49,6 +47,7 @@
#include <unordered_map>
#include <unordered_set>
#include <utility>
+#include <variant>
#include <vector>
namespace qbs {
@@ -132,31 +131,31 @@ public:
std::string errorText;
};
-class PcPackageVariant: public Variant::variant<PcPackage, PcBrokenPackage>
+class PcPackageVariant : public std::variant<PcPackage, PcBrokenPackage>
{
public:
- using Base = Variant::variant<PcPackage, PcBrokenPackage>;
+ using Base = std::variant<PcPackage, PcBrokenPackage>;
using Base::Base;
bool isValid() const noexcept { return index() == 0; }
bool isBroken() const noexcept { return index() == 1; }
- const PcPackage &asPackage() const { return Variant::get<PcPackage>(*this); }
- PcPackage &asPackage() { return Variant::get<PcPackage>(*this); }
+ const PcPackage &asPackage() const { return std::get<PcPackage>(*this); }
+ PcPackage &asPackage() { return std::get<PcPackage>(*this); }
- const PcBrokenPackage &asBrokenPackage() const { return Variant::get<PcBrokenPackage>(*this); }
- PcBrokenPackage &asBrokenPackage() { return Variant::get<PcBrokenPackage>(*this); }
+ const PcBrokenPackage &asBrokenPackage() const { return std::get<PcBrokenPackage>(*this); }
+ PcBrokenPackage &asBrokenPackage() { return std::get<PcBrokenPackage>(*this); }
template<typename F>
decltype(auto) visit(F &&f) const
{
- return Variant::visit(std::forward<F>(f), static_cast<const Base &>(*this));
+ return std::visit(std::forward<F>(f), static_cast<const Base &>(*this));
}
template<typename F>
decltype(auto) visit(F &&f)
{
- return Variant::visit(std::forward<F>(f), static_cast<Base &>(*this));
+ return std::visit(std::forward<F>(f), static_cast<Base &>(*this));
}
const std::string &getBaseFileName() const
diff --git a/src/lib/pkgconfig/pcparser.cpp b/src/lib/pkgconfig/pcparser.cpp
index eb07aa5ef..1649ead9d 100644
--- a/src/lib/pkgconfig/pcparser.cpp
+++ b/src/lib/pkgconfig/pcparser.cpp
@@ -41,22 +41,9 @@
#include "pkgconfig.h"
-#if HAS_STD_FILESYSTEM
-# if __has_include(<filesystem>)
-# include <filesystem>
-# else
-# include <experimental/filesystem>
-// We need the alias from std::experimental::filesystem to std::filesystem
-namespace std {
- namespace filesystem = experimental::filesystem;
-}
-# endif
-#else
-#include <QFileInfo>
-#endif
-
#include <algorithm>
#include <cctype>
+#include <filesystem>
#include <fstream>
#include <stdexcept>
@@ -413,15 +400,9 @@ try
throw PcException(std::string("Can't open file ") + path);
package.baseFileName = std::string{completeBaseName(path)};
-#if HAS_STD_FILESYSTEM
const auto fsPath = std::filesystem::path(path);
package.filePath = fsPath.generic_string();
package.variables["pcfiledir"] = fsPath.parent_path().generic_string();
-#else
- QFileInfo fileInfo(QString::fromStdString(path));
- package.filePath = fileInfo.absoluteFilePath().toStdString();
- package.variables["pcfiledir"] = fileInfo.absolutePath().toStdString();
-#endif
std::string line;
while (readOneLine(file, line))
diff --git a/src/lib/pkgconfig/pkgconfig.cpp b/src/lib/pkgconfig/pkgconfig.cpp
index 6b3bde46c..672aa56f1 100644
--- a/src/lib/pkgconfig/pkgconfig.cpp
+++ b/src/lib/pkgconfig/pkgconfig.cpp
@@ -40,22 +40,8 @@
#include "pkgconfig.h"
#include "pcparser.h"
-#if HAS_STD_FILESYSTEM
-# if __has_include(<filesystem>)
-# include <filesystem>
-# else
-# include <experimental/filesystem>
-// We need the alias from std::experimental::filesystem to std::filesystem
-namespace std {
- namespace filesystem = experimental::filesystem;
-}
-# endif
-#else
-# include <QtCore/QDir>
-# include <QtCore/QFileInfo>
-#endif
-
#include <algorithm>
+#include <filesystem>
#include <iostream>
namespace qbs {
@@ -202,7 +188,6 @@ std::optional<std::string_view> PkgConfig::packageGetVariable(
return result;
}
-#if HAS_STD_FILESYSTEM
std::vector<std::string> getPcFilePaths(const std::vector<std::string> &searchPaths)
{
std::vector<std::filesystem::path> paths;
@@ -227,23 +212,6 @@ std::vector<std::string> getPcFilePaths(const std::vector<std::string> &searchPa
);
return result;
}
-#else
-std::vector<std::string> getPcFilePaths(const std::vector<std::string> &searchPaths)
-{
- std::vector<std::string> result;
- for (const auto &path : searchPaths) {
- QDir dir(QString::fromStdString(path));
- const auto paths = dir.entryList({QStringLiteral("*.pc")});
- std::transform(
- std::begin(paths),
- std::end(paths),
- std::back_inserter(result),
- [&dir](const auto &path) { return dir.filePath(path).toStdString(); }
- );
- }
- return result;
-}
-#endif
PcBrokenPackage makeMissingDependency(
const PcPackage &package, const PcPackage::RequiredVersion &depVersion)
diff --git a/src/lib/pkgconfig/pkgconfig.qbs b/src/lib/pkgconfig/pkgconfig.qbs
index a32eb775b..1434953f7 100644
--- a/src/lib/pkgconfig/pkgconfig.qbs
+++ b/src/lib/pkgconfig/pkgconfig.qbs
@@ -1,10 +1,10 @@
import qbs.FileInfo
import qbs.Utilities
-QbsStaticLibrary {
+QbsProduct {
+ type: "staticlibrary"
Depends { name: "cpp" }
Depends { name: "qbsbuildconfig" }
- Depends { name: "qbsvariant" }
property stringList pcPaths: {
var result = [];
@@ -45,20 +45,14 @@ QbsStaticLibrary {
"PKG_CONFIG_PC_PATH=\"" + pcPathsString + "\"",
"PKG_CONFIG_SYSTEM_LIBRARY_PATH=\"/usr/" + qbsbuildconfig.libDirName + "\"",
]
- if ((qbs.targetOS.contains("darwin")
- && Utilities.versionCompare(cpp.minimumMacosVersion, "10.15") < 0)
- || qbs.toolchain.contains("mingw"))
- result.push("HAS_STD_FILESYSTEM=0")
- else
- result.push("HAS_STD_FILESYSTEM=1")
result = result.concat(publicDefines);
return result
}
Export {
Depends { name: "cpp" }
- Depends { name: "qbsvariant" }
cpp.defines: exportingProduct.publicDefines
+ cpp.includePaths: [exportingProduct.sourceDirectory]
cpp.staticLibraries: {
if (qbs.toolchainType === "gcc" && cpp.compilerVersionMajor < 9)
return ["stdc++fs"];
diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt
index 226dd77ec..f01642b15 100644
--- a/src/shared/CMakeLists.txt
+++ b/src/shared/CMakeLists.txt
@@ -1,4 +1,4 @@
add_subdirectory(json)
add_subdirectory(lsp)
add_subdirectory(quickjs)
-add_subdirectory(variant)
+add_subdirectory(span)
diff --git a/src/shared/quickjs/.clang-format b/src/shared/quickjs/.clang-format
new file mode 100644
index 000000000..47a38a93f
--- /dev/null
+++ b/src/shared/quickjs/.clang-format
@@ -0,0 +1,2 @@
+DisableFormat: true
+SortIncludes: Never
diff --git a/src/shared/quickjs/CMakeLists.txt b/src/shared/quickjs/CMakeLists.txt
index a0af03c79..d88739ab0 100644
--- a/src/shared/quickjs/CMakeLists.txt
+++ b/src/shared/quickjs/CMakeLists.txt
@@ -2,6 +2,7 @@ add_qbs_library(qbsquickjs
STATIC
SOURCES
cutils.c cutils.h
+ libbf.c libbf.h
libregexp-opcode.h
libregexp.c libregexp.h
libunicode-table.h
diff --git a/src/shared/quickjs/LICENSE b/src/shared/quickjs/LICENSE
index 2c8fdebaf..2cf449dd3 100644
--- a/src/shared/quickjs/LICENSE
+++ b/src/shared/quickjs/LICENSE
@@ -1,5 +1,5 @@
QuickJS Javascript Engine
-
+
Copyright (c) 2017-2021 Fabrice Bellard
Copyright (c) 2017-2021 Charlie Gordon
diff --git a/src/shared/quickjs/cutils.c b/src/shared/quickjs/cutils.c
index 1f66fff3f..95ae5688d 100644
--- a/src/shared/quickjs/cutils.c
+++ b/src/shared/quickjs/cutils.c
@@ -1,6 +1,6 @@
/*
* C utilities
- *
+ *
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
@@ -140,7 +140,7 @@ int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
if (dbuf_realloc(s, s->size + len))
return -1;
}
- memcpy(s->buf + s->size, data, len);
+ memcpy_no_ub(s->buf + s->size, data, len);
s->size += len;
return 0;
}
@@ -171,7 +171,7 @@ int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...)
va_list ap;
char buf[128];
int len;
-
+
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
diff --git a/src/shared/quickjs/cutils.h b/src/shared/quickjs/cutils.h
index ee0ce4a2e..265fd0aee 100644
--- a/src/shared/quickjs/cutils.h
+++ b/src/shared/quickjs/cutils.h
@@ -26,6 +26,7 @@
#define CUTILS_H
#include <stdlib.h>
+#include <string.h>
#include <inttypes.h>
#if defined(_MSC_VER)
@@ -35,21 +36,18 @@ typedef SSIZE_T ssize_t;
#include <sys/types.h>
#endif
-/* set if CPU is big endian */
-#undef WORDS_BIGENDIAN
-
#ifdef __GNUC__
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline inline __attribute__((always_inline))
#define no_inline __attribute__((noinline))
-#define maybe_unused __attribute__((unused))
+#define __maybe_unused __attribute__((unused))
#else
#define likely(x) (x)
#define unlikely(x) (x)
#define force_inline
#define no_inline
-#define maybe_unused
+#define __maybe_unused
#endif
#ifdef _MSC_VER
@@ -67,6 +65,16 @@ typedef SSIZE_T ssize_t;
#ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0]))
#endif
+#ifndef container_of
+/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
+#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
+#endif
+
+#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define minimum_length(n) static n
+#else
+#define minimum_length(n) n
+#endif
typedef int BOOL;
@@ -82,6 +90,12 @@ char *pstrcat(char *buf, int buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
int has_suffix(const char *str, const char *suffix);
+/* Prevent UB when n == 0 and (src == NULL or dest == NULL) */
+static inline void memcpy_no_ub(void *dest, const void *src, size_t n) {
+ if (n)
+ memcpy(dest, src, n);
+}
+
static inline int max_int(int a, int b)
{
if (a > b)
@@ -140,6 +154,36 @@ static inline int clz32(unsigned int a)
#endif
}
+/* WARNING: undefined if a = 0 */
+static inline int clz64(uint64_t a)
+{
+#ifdef _MSC_VER
+ return (int) __lzcnt64(a);
+#else
+ return __builtin_clzll(a);
+#endif
+}
+
+/* WARNING: undefined if a = 0 */
+static inline int ctz32(unsigned int a)
+{
+#ifdef _MSC_VER
+ return (int) _tzcnt_u32(a);
+#else
+ return __builtin_ctz(a);
+#endif
+}
+
+/* WARNING: undefined if a = 0 */
+static inline int ctz64(uint64_t a)
+{
+#ifdef _MSC_VER
+ return (int) _tzcnt_u64(a);
+#else
+ return __builtin_ctzll(a);
+#endif
+}
+
#pragma pack(push, 1)
struct packed_u64 {
uint64_t v;
@@ -212,17 +256,22 @@ static inline void put_u8(uint8_t *tab, uint8_t val)
*tab = val;
}
+#ifndef bswap16
static inline uint16_t bswap16(uint16_t x)
{
return (x >> 8) | (x << 8);
}
+#endif
+#ifndef bswap32
static inline uint32_t bswap32(uint32_t v)
{
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
}
+#endif
+#ifndef bswap64
static inline uint64_t bswap64(uint64_t v)
{
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
@@ -234,6 +283,7 @@ static inline uint64_t bswap64(uint64_t v)
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
}
+#endif
/* XXX: should take an extra argument to pass slack information to the caller */
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
@@ -290,6 +340,36 @@ static inline void dbuf_set_error(DynBuf *s)
int unicode_to_utf8(uint8_t *buf, unsigned int c);
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
+static inline BOOL is_surrogate(uint32_t c)
+{
+ return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
+}
+
+static inline BOOL is_hi_surrogate(uint32_t c)
+{
+ return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
+}
+
+static inline BOOL is_lo_surrogate(uint32_t c)
+{
+ return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
+}
+
+static inline uint32_t get_hi_surrogate(uint32_t c)
+{
+ return (c >> 10) - (0x10000 >> 10) + 0xD800;
+}
+
+static inline uint32_t get_lo_surrogate(uint32_t c)
+{
+ return (c & 0x3FF) | 0xDC00;
+}
+
+static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
+{
+ return 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00);
+}
+
static inline int from_hex(int c)
{
if (c >= '0' && c <= '9')
diff --git a/src/shared/quickjs/libbf.c b/src/shared/quickjs/libbf.c
new file mode 100644
index 000000000..56b2be861
--- /dev/null
+++ b/src/shared/quickjs/libbf.c
@@ -0,0 +1,8475 @@
+/*
+ * Tiny arbitrary precision floating point library
+ *
+ * Copyright (c) 2017-2021 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef __AVX2__
+#include <immintrin.h>
+#endif
+
+#include "cutils.h"
+#include "libbf.h"
+
+/* enable it to check the multiplication result */
+//#define USE_MUL_CHECK
+/* enable it to use FFT/NTT multiplication */
+#define USE_FFT_MUL
+/* enable decimal floating point support */
+#define USE_BF_DEC
+
+//#define inline __attribute__((always_inline))
+
+#ifdef __AVX2__
+#define FFT_MUL_THRESHOLD 100 /* in limbs of the smallest factor */
+#else
+#define FFT_MUL_THRESHOLD 100 /* in limbs of the smallest factor */
+#endif
+
+/* XXX: adjust */
+#define DIVNORM_LARGE_THRESHOLD 50
+#define UDIV1NORM_THRESHOLD 3
+
+#if LIMB_BITS == 64
+#define FMT_LIMB1 "%" PRIx64
+#define FMT_LIMB "%016" PRIx64
+#define PRId_LIMB PRId64
+#define PRIu_LIMB PRIu64
+
+#else
+
+#define FMT_LIMB1 "%x"
+#define FMT_LIMB "%08x"
+#define PRId_LIMB "d"
+#define PRIu_LIMB "u"
+
+#endif
+
+typedef intptr_t mp_size_t;
+
+typedef int bf_op2_func_t(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags);
+
+#ifdef USE_FFT_MUL
+
+#define FFT_MUL_R_OVERLAP_A (1 << 0)
+#define FFT_MUL_R_OVERLAP_B (1 << 1)
+#define FFT_MUL_R_NORESIZE (1 << 2)
+
+static no_inline int fft_mul(bf_context_t *s,
+ bf_t *res, limb_t *a_tab, limb_t a_len,
+ limb_t *b_tab, limb_t b_len, int mul_flags);
+static void fft_clear_cache(bf_context_t *s);
+#endif
+#ifdef USE_BF_DEC
+static limb_t get_digit(const limb_t *tab, limb_t len, slimb_t pos);
+#endif
+
+
+/* could leading zeros */
+static inline int clz(limb_t a)
+{
+ if (a == 0) {
+ return LIMB_BITS;
+ } else {
+#if LIMB_BITS == 64
+ return clz64(a);
+#else
+ return clz32(a);
+#endif
+ }
+}
+
+static inline int ctz(limb_t a)
+{
+ if (a == 0) {
+ return LIMB_BITS;
+ } else {
+#if LIMB_BITS == 64
+ return ctz64(a);
+#else
+ return ctz32(a);
+#endif
+ }
+}
+
+static inline int ceil_log2(limb_t a)
+{
+ if (a <= 1)
+ return 0;
+ else
+ return LIMB_BITS - clz(a - 1);
+}
+
+/* b must be >= 1 */
+static inline slimb_t ceil_div(slimb_t a, slimb_t b)
+{
+ if (a >= 0)
+ return (a + b - 1) / b;
+ else
+ return a / b;
+}
+
+#ifdef USE_BF_DEC
+/* b must be >= 1 */
+static inline slimb_t floor_div(slimb_t a, slimb_t b)
+{
+ if (a >= 0) {
+ return a / b;
+ } else {
+ return (a - b + 1) / b;
+ }
+}
+#endif
+
+/* return r = a modulo b (0 <= r <= b - 1. b must be >= 1 */
+static inline limb_t smod(slimb_t a, slimb_t b)
+{
+ a = a % (slimb_t)b;
+ if (a < 0)
+ a += b;
+ return a;
+}
+
+/* signed addition with saturation */
+static inline slimb_t sat_add(slimb_t a, slimb_t b)
+{
+ slimb_t r;
+ r = a + b;
+ /* overflow ? */
+ if (((a ^ r) & (b ^ r)) < 0)
+ r = (a >> (LIMB_BITS - 1)) ^ (((limb_t)1 << (LIMB_BITS - 1)) - 1);
+ return r;
+}
+
+static inline __maybe_unused limb_t shrd(limb_t low, limb_t high, long shift)
+{
+ if (shift != 0)
+ low = (low >> shift) | (high << (LIMB_BITS - shift));
+ return low;
+}
+
+static inline __maybe_unused limb_t shld(limb_t a1, limb_t a0, long shift)
+{
+ if (shift != 0)
+ return (a1 << shift) | (a0 >> (LIMB_BITS - shift));
+ else
+ return a1;
+}
+
+#define malloc(s) malloc_is_forbidden(s)
+#define free(p) free_is_forbidden(p)
+#define realloc(p, s) realloc_is_forbidden(p, s)
+
+void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
+ void *realloc_opaque)
+{
+ memset(s, 0, sizeof(*s));
+ s->realloc_func = realloc_func;
+ s->realloc_opaque = realloc_opaque;
+}
+
+void bf_context_end(bf_context_t *s)
+{
+ bf_clear_cache(s);
+}
+
+void bf_init(bf_context_t *s, bf_t *r)
+{
+ r->ctx = s;
+ r->sign = 0;
+ r->expn = BF_EXP_ZERO;
+ r->len = 0;
+ r->tab = NULL;
+}
+
+/* return 0 if OK, -1 if alloc error */
+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)
+ return -1;
+ r->tab = tab;
+ r->len = len;
+ }
+ return 0;
+}
+
+/* return 0 or BF_ST_MEM_ERROR */
+int bf_set_ui(bf_t *r, uint64_t a)
+{
+ r->sign = 0;
+ if (a == 0) {
+ r->expn = BF_EXP_ZERO;
+ bf_resize(r, 0); /* cannot fail */
+ }
+#if LIMB_BITS == 32
+ else if (a <= 0xffffffff)
+#else
+ else
+#endif
+ {
+ int shift;
+ if (bf_resize(r, 1))
+ goto fail;
+ shift = clz(a);
+ r->tab[0] = a << shift;
+ r->expn = LIMB_BITS - shift;
+ }
+#if LIMB_BITS == 32
+ else {
+ uint32_t a1, a0;
+ int shift;
+ if (bf_resize(r, 2))
+ goto fail;
+ a0 = a;
+ a1 = a >> 32;
+ shift = clz(a1);
+ r->tab[0] = a0 << shift;
+ r->tab[1] = shld(a1, a0, shift);
+ r->expn = 2 * LIMB_BITS - shift;
+ }
+#endif
+ return 0;
+ fail:
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+/* return 0 or BF_ST_MEM_ERROR */
+int bf_set_si(bf_t *r, int64_t a)
+{
+ int ret;
+
+ if (a < 0) {
+ ret = bf_set_ui(r, -a);
+ r->sign = 1;
+ } else {
+ ret = bf_set_ui(r, a);
+ }
+ return ret;
+}
+
+void bf_set_nan(bf_t *r)
+{
+ bf_resize(r, 0); /* cannot fail */
+ r->expn = BF_EXP_NAN;
+ r->sign = 0;
+}
+
+void bf_set_zero(bf_t *r, int is_neg)
+{
+ bf_resize(r, 0); /* cannot fail */
+ r->expn = BF_EXP_ZERO;
+ r->sign = is_neg;
+}
+
+void bf_set_inf(bf_t *r, int is_neg)
+{
+ bf_resize(r, 0); /* cannot fail */
+ r->expn = BF_EXP_INF;
+ r->sign = is_neg;
+}
+
+/* return 0 or BF_ST_MEM_ERROR */
+int bf_set(bf_t *r, const bf_t *a)
+{
+ if (r == a)
+ return 0;
+ if (bf_resize(r, a->len)) {
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+ }
+ r->sign = a->sign;
+ r->expn = a->expn;
+ memcpy_no_ub(r->tab, a->tab, a->len * sizeof(limb_t));
+ return 0;
+}
+
+/* equivalent to bf_set(r, a); bf_delete(a) */
+void bf_move(bf_t *r, bf_t *a)
+{
+ bf_context_t *s = r->ctx;
+ if (r == a)
+ return;
+ bf_free(s, r->tab);
+ *r = *a;
+}
+
+static limb_t get_limbz(const bf_t *a, limb_t idx)
+{
+ if (idx >= a->len)
+ return 0;
+ else
+ return a->tab[idx];
+}
+
+/* get LIMB_BITS at bit position 'pos' in tab */
+static inline limb_t get_bits(const limb_t *tab, limb_t len, slimb_t pos)
+{
+ limb_t i, a0, a1;
+ int p;
+
+ i = pos >> LIMB_LOG2_BITS;
+ p = pos & (LIMB_BITS - 1);
+ if (i < len)
+ a0 = tab[i];
+ else
+ a0 = 0;
+ if (p == 0) {
+ return a0;
+ } else {
+ i++;
+ if (i < len)
+ a1 = tab[i];
+ else
+ a1 = 0;
+ return (a0 >> p) | (a1 << (LIMB_BITS - p));
+ }
+}
+
+static inline limb_t get_bit(const limb_t *tab, limb_t len, slimb_t pos)
+{
+ slimb_t i;
+ i = pos >> LIMB_LOG2_BITS;
+ if (i < 0 || i >= len)
+ return 0;
+ return (tab[i] >> (pos & (LIMB_BITS - 1))) & 1;
+}
+
+static inline limb_t limb_mask(int start, int last)
+{
+ limb_t v;
+ int n;
+ n = last - start + 1;
+ if (n == LIMB_BITS)
+ v = -1;
+ else
+ v = (((limb_t)1 << n) - 1) << start;
+ return v;
+}
+
+static limb_t mp_scan_nz(const limb_t *tab, mp_size_t n)
+{
+ mp_size_t i;
+ for(i = 0; i < n; i++) {
+ if (tab[i] != 0)
+ return 1;
+ }
+ return 0;
+}
+
+/* return != 0 if one bit between 0 and bit_pos inclusive is not zero. */
+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;
+ v = r->tab[pos] & limb_mask(0, bit_pos & (LIMB_BITS - 1));
+ if (v != 0)
+ return 1;
+ pos--;
+ while (pos >= 0) {
+ if (r->tab[pos] != 0)
+ return 1;
+ pos--;
+ }
+ return 0;
+}
+
+/* return the addend for rounding. Note that prec can be <= 0 (for
+ BF_FLAG_RADPNT_PREC) */
+static int bf_get_rnd_add(int *pret, const bf_t *r, limb_t l,
+ slimb_t prec, int rnd_mode)
+{
+ int add_one, inexact;
+ limb_t bit1, bit0;
+
+ if (rnd_mode == BF_RNDF) {
+ bit0 = 1; /* faithful rounding does not honor the INEXACT flag */
+ } else {
+ /* starting limb for bit 'prec + 1' */
+ bit0 = scan_bit_nz(r, l * LIMB_BITS - 1 - bf_max(0, prec + 1));
+ }
+
+ /* 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:
+ break;
+ case BF_RNDN:
+ if (bit1) {
+ if (bit0) {
+ add_one = 1;
+ } else {
+ /* round to even */
+ add_one =
+ get_bit(r->tab, l, l * LIMB_BITS - 1 - (prec - 1));
+ }
+ }
+ break;
+ case BF_RNDD:
+ case BF_RNDU:
+ if (r->sign == (rnd_mode == BF_RNDD))
+ add_one = inexact;
+ break;
+ case BF_RNDA:
+ add_one = inexact;
+ break;
+ case BF_RNDNA:
+ case BF_RNDF:
+ add_one = bit1;
+ break;
+ default:
+ abort();
+ }
+
+ if (inexact)
+ *pret |= BF_ST_INEXACT;
+ return add_one;
+}
+
+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 ||
+ rnd_mode == BF_RNDNA ||
+ rnd_mode == BF_RNDA ||
+ (rnd_mode == BF_RNDD && sign == 1) ||
+ (rnd_mode == BF_RNDU && sign == 0)) {
+ bf_set_inf(r, sign);
+ } else {
+ /* set to maximum finite number */
+ l = (prec + LIMB_BITS - 1) / LIMB_BITS;
+ if (bf_resize(r, l)) {
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+ }
+ r->tab[0] = limb_mask((-prec) & (LIMB_BITS - 1),
+ LIMB_BITS - 1);
+ for(i = 1; i < l; i++)
+ r->tab[i] = (limb_t)-1;
+ e_max = (limb_t)1 << (bf_get_exp_bits(flags) - 1);
+ r->expn = e_max;
+ r->sign = sign;
+ }
+ return BF_ST_OVERFLOW | BF_ST_INEXACT;
+}
+
+/* round to prec1 bits assuming 'r' is non zero and finite. 'r' is
+ assumed to have length 'l' (1 <= l <= r->len). Note: 'prec1' can be
+ infinite (BF_PREC_INF). 'ret' is 0 or BF_ST_INEXACT if the result
+ is known to be inexact. Can fail with BF_ST_MEM_ERROR in case of
+ overflow not returning infinity. */
+static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l,
+ int ret)
+{
+ limb_t v, a;
+ int shift, add_one, rnd_mode;
+ slimb_t i, bit_pos, pos, e_min, e_max, e_range, prec;
+
+ /* e_min and e_max are computed to match the IEEE 754 conventions */
+ 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)
+ prec = r->expn + prec1;
+ else
+ prec = prec1;
+ } else if (unlikely(r->expn < e_min) && (flags & BF_FLAG_SUBNORMAL)) {
+ /* restrict the precision in case of potentially subnormal
+ result */
+ assert(prec1 != BF_PREC_INF);
+ prec = prec1 - (e_min - r->expn);
+ } else {
+ prec = prec1;
+ }
+
+ /* 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 */
+ r->tab[0] = (limb_t)1 << (LIMB_BITS - 1);
+ r->expn += 1 - prec;
+ ret |= BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ return ret;
+ } else {
+ goto underflow;
+ }
+ } 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);
+ r->tab[i] = v;
+ if (carry == 0)
+ break;
+ }
+ if (carry) {
+ /* shift right by one digit */
+ v = 1;
+ for(i = l - 1; i >= pos; i--) {
+ a = r->tab[i];
+ r->tab[i] = (a >> 1) | (v << (LIMB_BITS - 1));
+ v = a;
+ }
+ r->expn++;
+ }
+ }
+
+ /* check underflow */
+ if (unlikely(r->expn < e_min)) {
+ if (flags & BF_FLAG_SUBNORMAL) {
+ /* if inexact, also set the underflow flag */
+ if (ret & BF_ST_INEXACT)
+ ret |= BF_ST_UNDERFLOW;
+ } else {
+ underflow:
+ ret |= BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ bf_set_zero(r, r->sign);
+ 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;
+ if (i >= 0) {
+ shift = bit_pos & (LIMB_BITS - 1);
+ if (shift != 0)
+ r->tab[i] &= limb_mask(shift, LIMB_BITS - 1);
+ } else {
+ i = 0;
+ }
+ /* remove trailing zeros */
+ while (r->tab[i] == 0)
+ i++;
+ if (i > 0) {
+ l -= i;
+ memmove(r->tab, r->tab + i, l * sizeof(limb_t));
+ }
+ bf_resize(r, l); /* cannot fail */
+ return ret;
+}
+
+/* 'r' must be a finite number. */
+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)
+ l--;
+ if (l == 0) {
+ /* zero */
+ r->expn = BF_EXP_ZERO;
+ bf_resize(r, 0); /* cannot fail */
+ ret = 0;
+ } else {
+ r->expn -= (r->len - l) * LIMB_BITS;
+ /* shift to have the MSB set to '1' */
+ v = r->tab[l - 1];
+ shift = clz(v);
+ if (shift != 0) {
+ v = 0;
+ for(i = 0; i < l; i++) {
+ a = r->tab[i];
+ r->tab[i] = (a << shift) | (v >> (LIMB_BITS - shift));
+ v = a;
+ }
+ r->expn -= shift;
+ }
+ ret = __bf_round(r, prec1, flags, l, 0);
+ }
+ // bf_print_str("r_final", r);
+ return ret;
+}
+
+/* return true if rounding can be done at precision 'prec' assuming
+ the exact result r is such that |r-a| <= 2^(EXP(a)-k). */
+/* XXX: check the case where the exponent would be incremented by the
+ rounding */
+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) {
+ return (k >= (prec + 1));
+ }
+ if (a->expn == BF_EXP_ZERO)
+ return FALSE;
+ is_rndn = (rnd_mode == BF_RNDN || rnd_mode == BF_RNDNA);
+ if (k < (prec + 2))
+ return FALSE;
+ 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...
+ */
+ bit = get_bit(a->tab, a->len, bit_pos);
+ bit_pos--;
+ n--;
+ bit ^= is_rndn;
+ /* XXX: slow, but a few iterations on average */
+ while (n != 0) {
+ if (get_bit(a->tab, a->len, bit_pos) != bit)
+ return TRUE;
+ bit_pos--;
+ n--;
+ }
+ return FALSE;
+}
+
+/* Cannot fail with BF_ST_MEM_ERROR. */
+int bf_round(bf_t *r, limb_t prec, bf_flags_t flags)
+{
+ if (r->len == 0)
+ return 0;
+ return __bf_round(r, prec, flags, r->len, 0);
+}
+
+/* for debugging */
+static __maybe_unused void dump_limbs(const char *str, const limb_t *tab, limb_t n)
+{
+ limb_t i;
+ printf("%s: len=%" PRId_LIMB "\n", str, n);
+ for(i = 0; i < n; i++) {
+ printf("%" PRId_LIMB ": " FMT_LIMB "\n",
+ i, tab[i]);
+ }
+}
+
+void mp_print_str(const char *str, const limb_t *tab, limb_t n)
+{
+ slimb_t i;
+ printf("%s= 0x", str);
+ for(i = n - 1; i >= 0; i--) {
+ if (i != (n - 1))
+ printf("_");
+ printf(FMT_LIMB, tab[i]);
+ }
+ printf("\n");
+}
+
+static __maybe_unused void mp_print_str_h(const char *str,
+ const limb_t *tab, limb_t n,
+ limb_t high)
+{
+ slimb_t i;
+ printf("%s= 0x", str);
+ printf(FMT_LIMB, high);
+ for(i = n - 1; i >= 0; i--) {
+ printf("_");
+ printf(FMT_LIMB, tab[i]);
+ }
+ printf("\n");
+}
+
+/* for debugging */
+void bf_print_str(const char *str, const bf_t *a)
+{
+ slimb_t i;
+ printf("%s=", str);
+
+ if (a->expn == BF_EXP_NAN) {
+ printf("NaN");
+ } else {
+ if (a->sign)
+ putchar('-');
+ if (a->expn == BF_EXP_ZERO) {
+ putchar('0');
+ } else if (a->expn == BF_EXP_INF) {
+ printf("Inf");
+ } else {
+ printf("0x0.");
+ for(i = a->len - 1; i >= 0; i--)
+ printf(FMT_LIMB, a->tab[i]);
+ printf("p%" PRId_LIMB, a->expn);
+ }
+ }
+ printf("\n");
+}
+
+/* compare the absolute value of 'a' and 'b'. Return < 0 if a < b, 0
+ if a = b and > 0 otherwise. */
+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;
+ else
+ return 1;
+ }
+ len = bf_max(a->len, b->len);
+ for(i = len - 1; i >= 0; i--) {
+ v1 = get_limbz(a, a->len - len + i);
+ v2 = get_limbz(b, b->len - len + i);
+ if (v1 != v2) {
+ if (v1 < v2)
+ return -1;
+ else
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Full order: -0 < 0, NaN == NaN and NaN is larger than all other numbers */
+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;
+ else if (a->expn == BF_EXP_NAN)
+ res = 1;
+ else
+ res = -1;
+ } else if (a->sign != b->sign) {
+ res = 1 - 2 * a->sign;
+ } else {
+ res = bf_cmpu(a, b);
+ if (a->sign)
+ res = -res;
+ }
+ return res;
+}
+
+/* Standard floating point comparison: return 2 if one of the operands
+ is NaN (unordered) or -1, 0, 1 depending on the ordering assuming
+ -0 == +0 */
+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) {
+ if (a->expn == BF_EXP_ZERO && b->expn == BF_EXP_ZERO)
+ res = 0;
+ else
+ res = 1 - 2 * a->sign;
+ } else {
+ res = bf_cmpu(a, b);
+ if (a->sign)
+ res = -res;
+ }
+ return res;
+}
+
+/* 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.
+
+ Precondition: a > b and a.expn - b.expn = 0 or 1
+*/
+static limb_t count_cancelled_bits(const bf_t *a, const bf_t *b)
+{
+ slimb_t bit_offset, b_offset, n;
+ int p, p1;
+ limb_t v1, v2, mask;
+
+ bit_offset = a->len * LIMB_BITS - 1;
+ b_offset = (b->len - a->len) * LIMB_BITS - (LIMB_BITS - 1) +
+ a->expn - b->expn;
+ n = 0;
+
+ /* first search the equals bits */
+ for(;;) {
+ v1 = get_limbz(a, bit_offset >> LIMB_LOG2_BITS);
+ v2 = get_bits(b->tab, b->len, bit_offset + b_offset);
+ // printf("v1=" FMT_LIMB " v2=" FMT_LIMB "\n", v1, v2);
+ if (v1 != v2)
+ break;
+ n += LIMB_BITS;
+ bit_offset -= LIMB_BITS;
+ }
+ /* find the position of the first different bit */
+ p = clz(v1 ^ v2) + 1;
+ n += p;
+ /* then search for '0' in a and '1' in b */
+ p = LIMB_BITS - p;
+ if (p > 0) {
+ /* search in the trailing p bits of v1 and v2 */
+ mask = limb_mask(0, p - 1);
+ p1 = bf_min(clz(v1 & mask), clz((~v2) & mask)) - (LIMB_BITS - p);
+ n += p1;
+ if (p1 != p)
+ goto done;
+ }
+ bit_offset -= LIMB_BITS;
+ for(;;) {
+ v1 = get_limbz(a, bit_offset >> LIMB_LOG2_BITS);
+ v2 = get_bits(b->tab, b->len, bit_offset + b_offset);
+ // printf("v1=" FMT_LIMB " v2=" FMT_LIMB "\n", v1, v2);
+ if (v1 != 0 || v2 != -1) {
+ /* different: count the matching bits */
+ p1 = bf_min(clz(v1), clz(~v2));
+ n += p1;
+ break;
+ }
+ n += LIMB_BITS;
+ bit_offset -= LIMB_BITS;
+ }
+ done:
+ return n;
+}
+
+static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int b_neg)
+{
+ const bf_t *tmp;
+ int is_sub, ret, cmp_res, a_sign, b_sign;
+
+ a_sign = a->sign;
+ b_sign = b->sign ^ b_neg;
+ is_sub = a_sign ^ b_sign;
+ cmp_res = bf_cmpu(a, b);
+ if (cmp_res < 0) {
+ tmp = a;
+ a = b;
+ b = tmp;
+ a_sign = b_sign; /* b_sign is never used later */
+ }
+ /* abs(a) >= abs(b) */
+ if (cmp_res == 0 && is_sub && a->expn < BF_EXP_INF) {
+ /* zero result */
+ bf_set_zero(r, (flags & BF_RND_MASK) == BF_RNDD);
+ ret = 0;
+ } else if (a->len == 0 || b->len == 0) {
+ ret = 0;
+ if (a->expn >= BF_EXP_INF) {
+ if (a->expn == BF_EXP_NAN) {
+ /* at least one operand is NaN */
+ bf_set_nan(r);
+ } else if (b->expn == BF_EXP_INF && is_sub) {
+ /* infinities with different signs */
+ bf_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bf_set_inf(r, a_sign);
+ }
+ } else {
+ /* at least one zero and not subtract */
+ bf_set(r, a);
+ r->sign = a_sign;
+ goto renorm;
+ }
+ } else {
+ slimb_t d, a_offset, b_bit_offset, i, cancelled_bits;
+ limb_t carry, v1, v2, u, r_len, carry1, precl, tot_len, z, sub_mask;
+
+ r->sign = a_sign;
+ r->expn = a->expn;
+ d = a->expn - b->expn;
+ /* must add more precision for the leading cancelled bits in
+ subtraction */
+ if (is_sub) {
+ if (d <= 1)
+ cancelled_bits = count_cancelled_bits(a, b);
+ else
+ cancelled_bits = 1;
+ } 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);
+ r_len = bf_min(precl, tot_len);
+ if (bf_resize(r, r_len))
+ goto fail;
+ a_offset = a->len - r_len;
+ b_bit_offset = (b->len - r_len) * LIMB_BITS + d;
+
+ /* compute the bits before for the rounding */
+ carry = is_sub;
+ z = 0;
+ sub_mask = -is_sub;
+ i = r_len - tot_len;
+ while (i < 0) {
+ slimb_t ap, bp;
+ BOOL inflag;
+
+ ap = a_offset + i;
+ bp = b_bit_offset + i * LIMB_BITS;
+ inflag = FALSE;
+ if (ap >= 0 && ap < a->len) {
+ v1 = a->tab[ap];
+ inflag = TRUE;
+ } else {
+ v1 = 0;
+ }
+ if (bp + LIMB_BITS > 0 && bp < (slimb_t)(b->len * LIMB_BITS)) {
+ v2 = get_bits(b->tab, b->len, bp);
+ inflag = TRUE;
+ } else {
+ v2 = 0;
+ }
+ if (!inflag) {
+ /* outside 'a' and 'b': go directly to the next value
+ inside a or b so that the running time does not
+ depend on the exponent difference */
+ i = 0;
+ if (ap < 0)
+ i = bf_min(i, -a_offset);
+ /* b_bit_offset + i * LIMB_BITS + LIMB_BITS >= 1
+ equivalent to
+ i >= ceil(-b_bit_offset + 1 - LIMB_BITS) / LIMB_BITS)
+ */
+ if (bp + LIMB_BITS <= 0)
+ i = bf_min(i, (-b_bit_offset) >> LIMB_LOG2_BITS);
+ } else {
+ i++;
+ }
+ v2 ^= sub_mask;
+ u = v1 + v2;
+ carry1 = u < v1;
+ u += carry;
+ carry = (u < carry) | carry1;
+ z |= u;
+ }
+ /* and the result */
+ for(i = 0; i < r_len; i++) {
+ v1 = get_limbz(a, a_offset + i);
+ v2 = get_bits(b->tab, b->len, b_bit_offset + i * LIMB_BITS);
+ v2 ^= sub_mask;
+ u = v1 + v2;
+ carry1 = u < v1;
+ u += carry;
+ carry = (u < carry) | carry1;
+ r->tab[i] = u;
+ }
+ /* set the extra bits for the rounding */
+ r->tab[0] |= (z != 0);
+
+ /* carry is only possible in add case */
+ if (!is_sub && carry) {
+ if (bf_resize(r, r_len + 1))
+ goto fail;
+ r->tab[r_len] = 1;
+ r->expn += LIMB_BITS;
+ }
+ renorm:
+ ret = bf_normalize_and_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+static int __bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_add_internal(r, a, b, prec, flags, 0);
+}
+
+static int __bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ 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 n, limb_t carry)
+{
+ slimb_t i;
+ limb_t k, a, v, k1;
+
+ k = carry;
+ for(i=0;i<n;i++) {
+ v = op1[i];
+ a = v + op2[i];
+ k1 = a < v;
+ a = a + k;
+ k = (a < k) | k1;
+ res[i] = a;
+ }
+ return k;
+}
+
+limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n)
+{
+ size_t i;
+ limb_t k, a;
+
+ k=b;
+ for(i=0;i<n;i++) {
+ if (k == 0)
+ break;
+ a = tab[i] + k;
+ k = (a < k);
+ tab[i] = a;
+ }
+ return k;
+}
+
+limb_t mp_sub(limb_t *res, const limb_t *op1, const limb_t *op2,
+ mp_size_t n, limb_t carry)
+{
+ int i;
+ limb_t k, a, v, k1;
+
+ k = carry;
+ for(i=0;i<n;i++) {
+ v = op1[i];
+ a = v - op2[i];
+ k1 = a > v;
+ v = a - k;
+ k = (v > a) | k1;
+ res[i] = v;
+ }
+ return k;
+}
+
+/* compute 0 - op2 */
+static limb_t mp_neg(limb_t *res, const limb_t *op2, mp_size_t n, limb_t carry)
+{
+ int i;
+ limb_t k, a, v, k1;
+
+ k = carry;
+ for(i=0;i<n;i++) {
+ v = 0;
+ a = v - op2[i];
+ k1 = a > v;
+ v = a - k;
+ k = (v > a) | k1;
+ res[i] = v;
+ }
+ return k;
+}
+
+limb_t mp_sub_ui(limb_t *tab, limb_t b, mp_size_t n)
+{
+ mp_size_t i;
+ limb_t k, a, v;
+
+ k=b;
+ for(i=0;i<n;i++) {
+ v = tab[i];
+ a = v - k;
+ k = a > v;
+ tab[i] = a;
+ if (k == 0)
+ break;
+ }
+ return k;
+}
+
+/* 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,
+ int shift, limb_t high)
+{
+ mp_size_t i;
+ limb_t l, a;
+
+ assert(shift >= 1 && shift < LIMB_BITS);
+ l = high;
+ for(i = n - 1; i >= 0; i--) {
+ a = tab[i];
+ tab_r[i] = (a >> shift) | (l << (LIMB_BITS - shift));
+ l = a;
+ }
+ return l & (((limb_t)1 << shift) - 1);
+}
+
+/* tabr[] = taba[] * b + l. Return the high carry */
+static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n,
+ limb_t b, limb_t l)
+{
+ limb_t i;
+ dlimb_t t;
+
+ for(i = 0; i < n; i++) {
+ t = (dlimb_t)taba[i] * (dlimb_t)b + l;
+ tabr[i] = t;
+ l = t >> LIMB_BITS;
+ }
+ return l;
+}
+
+/* tabr[] += taba[] * b, return the high word. */
+static limb_t mp_add_mul1(limb_t *tabr, const limb_t *taba, limb_t n,
+ limb_t b)
+{
+ 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];
+ tabr[i] = t;
+ l = t >> LIMB_BITS;
+ }
+ return l;
+}
+
+/* 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)
+{
+ limb_t i, r;
+
+ result[op1_size] = mp_mul1(result, op1, op1_size, op2[0], 0);
+ for(i=1;i<op2_size;i++) {
+ r = mp_add_mul1(result + i, op1, op1_size, op2[i]);
+ result[i + op1_size] = r;
+ }
+}
+
+/* return 0 if OK, -1 if memory error */
+/* XXX: change API so that result can be allocated */
+int mp_mul(bf_context_t *s, limb_t *result,
+ const limb_t *op1, limb_t op1_size,
+ const limb_t *op2, limb_t op2_size)
+{
+#ifdef USE_FFT_MUL
+ if (unlikely(bf_min(op1_size, op2_size) >= FFT_MUL_THRESHOLD)) {
+ bf_t r_s, *r = &r_s;
+ r->tab = result;
+ /* XXX: optimize memory usage in API */
+ if (fft_mul(s, r, (limb_t *)op1, op1_size,
+ (limb_t *)op2, op2_size, FFT_MUL_R_NORESIZE))
+ return -1;
+ } else
+#endif
+ {
+ mp_mul_basecase(result, op1, op1_size, op2, op2_size);
+ }
+ return 0;
+}
+
+/* tabr[] -= taba[] * b. Return the value to substract to the high
+ word. */
+static limb_t mp_sub_mul1(limb_t *tabr, const limb_t *taba, limb_t n,
+ limb_t b)
+{
+ 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;
+ tabr[i] = t;
+ l = -(t >> LIMB_BITS);
+ }
+ return l;
+}
+
+/* WARNING: d must be >= 2^(LIMB_BITS-1) */
+static inline limb_t udiv1norm_init(limb_t d)
+{
+ limb_t a0, a1;
+ a1 = -d - 1;
+ a0 = -1;
+ return (((dlimb_t)a1 << LIMB_BITS) | a0) / d;
+}
+
+/* return the quotient and the remainder in '*pr'of 'a1*2^LIMB_BITS+a0
+ / d' with 0 <= a1 < d. */
+static inline limb_t udiv1norm(limb_t *pr, limb_t a1, limb_t a0,
+ limb_t d, limb_t d_inv)
+{
+ limb_t n1m, n_adj, q, r, ah;
+ dlimb_t a;
+ n1m = ((slimb_t)a0 >> (LIMB_BITS - 1));
+ n_adj = a0 + (n1m & d);
+ a = (dlimb_t)d_inv * (a1 - n1m) + n_adj;
+ q = (a >> LIMB_BITS) + a1;
+ /* compute a - q * r and update q so that the remainder is\
+ between 0 and d - 1 */
+ a = ((dlimb_t)a1 << LIMB_BITS) | a0;
+ a = a - (dlimb_t)q * d - d;
+ ah = a >> LIMB_BITS;
+ q += 1 + ah;
+ r = (limb_t)a + (ah & d);
+ *pr = r;
+ return q;
+}
+
+/* b must be >= 1 << (LIMB_BITS - 1) */
+static limb_t mp_div1norm(limb_t *tabr, const limb_t *taba, limb_t n,
+ limb_t b, limb_t r)
+{
+ slimb_t i;
+
+ if (n >= UDIV1NORM_THRESHOLD) {
+ limb_t b_inv;
+ b_inv = udiv1norm_init(b);
+ for(i = n - 1; i >= 0; i--) {
+ tabr[i] = udiv1norm(&r, r, taba[i], b, b_inv);
+ }
+ } else {
+ dlimb_t a1;
+ for(i = n - 1; i >= 0; i--) {
+ a1 = ((dlimb_t)r << LIMB_BITS) | taba[i];
+ tabr[i] = a1 / b;
+ r = a1 % b;
+ }
+ }
+ return r;
+}
+
+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,
+ const limb_t *tabb, limb_t nb)
+{
+ limb_t r, a, c, q, v, b1, b1_inv, n, dummy_r;
+ slimb_t i, j;
+
+ b1 = tabb[nb - 1];
+ if (nb == 1) {
+ taba[0] = mp_div1norm(tabq, taba, na, b1, 0);
+ return 0;
+ }
+ n = na - nb;
+ 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
+ b1_inv = 0;
+
+ /* first iteration: the quotient is only 0 or 1 */
+ q = 1;
+ for(j = nb - 1; j >= 0; j--) {
+ if (taba[n + j] != tabb[j]) {
+ if (taba[n + j] < tabb[j])
+ q = 0;
+ break;
+ }
+ }
+ tabq[n] = q;
+ 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;
+ } else if (b1_inv) {
+ q = udiv1norm(&dummy_r, taba[i + nb], taba[i + nb - 1], b1, b1_inv);
+ } else {
+ dlimb_t al;
+ al = ((dlimb_t)taba[i + nb] << LIMB_BITS) | taba[i + nb - 1];
+ q = al / b1;
+ r = al % b1;
+ }
+ r = mp_sub_mul1(taba + i, tabb, nb, q);
+
+ v = taba[i + nb];
+ a = v - r;
+ c = (a > v);
+ taba[i + nb] = a;
+
+ if (c != 0) {
+ /* negative result */
+ for(;;) {
+ q--;
+ c = mp_add(taba + i, taba + i, tabb, nb, 0);
+ /* propagate carry and test if positive result */
+ if (c != 0) {
+ if (++taba[i + nb] == 0) {
+ break;
+ }
+ }
+ }
+ }
+ tabq[i] = q;
+ }
+ return 0;
+}
+
+/* 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 */
+ tabu = bf_malloc(s, sizeof(limb_t) * (2 * n + 1));
+ tabt = bf_malloc(s, sizeof(limb_t) * (n + 2));
+ if (!tabt || !tabu)
+ goto fail;
+ for(i = 0; i < 2 * n; i++)
+ tabu[i] = 0;
+ tabu[2 * n] = 1;
+ if (mp_divnorm(s, tabt, tabu, 2 * n + 1, taba, n))
+ goto fail;
+ for(i = 0; i < n + 1; i++)
+ tabr[i] = tabt[i];
+ if (mp_scan_nz(tabu, n) == 0) {
+ /* only happens for a=B^n/2 */
+ mp_sub_ui(tabr, 1, n + 1);
+ }
+ } else {
+ l = (n - 1) / 2;
+ h = n - l;
+ /* n=2p -> l=p-1, h = p + 1, k = p + 3
+ n=2p+1-> l=p, h = p + 1; k = p + 2
+ */
+ tabt = bf_malloc(s, sizeof(limb_t) * (n + h + 1));
+ tabu = bf_malloc(s, sizeof(limb_t) * (n + 2 * h - l + 2));
+ if (!tabt || !tabu)
+ goto fail;
+ tabxh = tabr + l;
+ if (mp_recip(s, tabxh, taba + l, h))
+ goto fail;
+ if (mp_mul(s, tabt, taba, n, tabxh, h + 1)) /* n + h + 1 limbs */
+ goto fail;
+ while (tabt[n + h] != 0) {
+ mp_sub_ui(tabxh, 1, h + 1);
+ c = mp_sub(tabt, tabt, taba, n, 0);
+ mp_sub_ui(tabt + n, c, h + 1);
+ }
+ /* T = B^(n+h) - T */
+ mp_neg(tabt, tabt, n + h + 1, 0);
+ tabt[n + h]++;
+ if (mp_mul(s, tabu, tabt + l, n + h + 1 - l, tabxh, h + 1))
+ goto fail;
+ /* n + 2*h - l + 2 limbs */
+ k = 2 * h - l;
+ for(i = 0; i < l; i++)
+ tabr[i] = tabu[i + k];
+ mp_add(tabr + l, tabr + l, tabu + 2 * h, h, 0);
+ }
+ bf_free(s, tabt);
+ bf_free(s, tabu);
+ return 0;
+ fail:
+ bf_free(s, tabt);
+ bf_free(s, tabu);
+ return -1;
+}
+
+/* return -1, 0 or 1 */
+static int mp_cmp(const limb_t *taba, const limb_t *tabb, mp_size_t n)
+{
+ mp_size_t i;
+ for(i = n - 1; i >= 0; i--) {
+ if (taba[i] != tabb[i]) {
+ if (taba[i] < tabb[i])
+ return -1;
+ else
+ return 1;
+ }
+ }
+ return 0;
+}
+
+//#define DEBUG_DIVNORM_LARGE
+//#define DEBUG_DIVNORM_LARGE2
+
+/* subquadratic divnorm */
+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;
+ nq = na - nb;
+#ifdef DEBUG_DIVNORM_LARGE
+ printf("na=%d nb=%d nq=%d\n", (int)na, (int)nb, (int)nq);
+ mp_print_str("a", taba, na);
+ mp_print_str("b", tabb, nb);
+#endif
+ assert(nq >= 1);
+ n = nq;
+ if (nq < nb)
+ 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)
+ goto fail;
+
+ if (n >= nb) {
+ for(i = 0; i < n - nb; i++)
+ tabt[i] = 0;
+ for(i = 0; i < nb; i++)
+ tabt[i + n - nb] = tabb[i];
+ } else {
+ /* truncate B: need to increment it so that the approximate
+ inverse is smaller that the exact inverse */
+ for(i = 0; i < n; i++)
+ tabt[i] = tabb[i + nb - n];
+ if (mp_add_ui(tabt, 1, n)) {
+ /* tabt = B^n : tabb_inv = B^n */
+ memset(tabb_inv, 0, n * sizeof(limb_t));
+ tabb_inv[n] = 1;
+ goto recip_done;
+ }
+ }
+ if (mp_recip(s, tabb_inv, tabt, n))
+ goto fail;
+ recip_done:
+ /* 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
+ mp_print_str("q", tabq, nq + 1);
+#endif
+
+ 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)
+ goto fail;
+ if (mp_mul(s, tabt, tabq, nq + 1, tabb, nb))
+ goto fail;
+ /* we add one more limb for the result */
+ mp_sub(taba, taba, tabt, nb + 1, 0);
+ bf_free(s, tabt);
+ /* the approximated quotient is smaller than than the exact one,
+ hence we may have to increment it */
+#ifdef DEBUG_DIVNORM_LARGE2
+ int cnt = 0;
+ static int cnt_max;
+#endif
+ for(;;) {
+ if (taba[nb] == 0 && mp_cmp(taba, tabb, nb) < 0)
+ break;
+ taba[nb] -= mp_sub(taba, taba, tabb, nb, 0);
+ mp_add_ui(tabq, 1, nq + 1);
+#ifdef DEBUG_DIVNORM_LARGE2
+ cnt++;
+#endif
+ }
+#ifdef DEBUG_DIVNORM_LARGE2
+ if (cnt > cnt_max) {
+ cnt_max = cnt;
+ printf("\ncnt=%d nq=%d nb=%d\n", cnt_max, (int)nq, (int)nb);
+ }
+#endif
+ return 0;
+ fail:
+ bf_free(s, tabb_inv);
+ bf_free(s, tabt);
+ return -1;
+}
+
+int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ int ret, r_sign;
+
+ if (a->len < b->len) {
+ const bf_t *tmp = a;
+ a = b;
+ b = tmp;
+ }
+ r_sign = a->sign ^ b->sign;
+ /* here b->len <= a->len */
+ if (b->len == 0) {
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ ret = 0;
+ } else if (a->expn == BF_EXP_INF || b->expn == BF_EXP_INF) {
+ if ((a->expn == BF_EXP_INF && b->expn == BF_EXP_ZERO) ||
+ (a->expn == BF_EXP_ZERO && b->expn == BF_EXP_INF)) {
+ bf_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bf_set_inf(r, r_sign);
+ ret = 0;
+ }
+ } else {
+ bf_set_zero(r, r_sign);
+ ret = 0;
+ }
+ } else {
+ 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;
+ a_len = bf_min(a_len, precl);
+ b_len = bf_min(b_len, precl);
+ }
+ 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;
+ if (r == a)
+ mul_flags |= FFT_MUL_R_OVERLAP_A;
+ if (r == b)
+ mul_flags |= FFT_MUL_R_OVERLAP_B;
+ if (fft_mul(r->ctx, r, a_tab, a_len, b_tab, b_len, mul_flags))
+ goto fail;
+ } else
+#endif
+ {
+ if (r == a || r == b) {
+ bf_init(r->ctx, &tmp);
+ r1 = r;
+ r = &tmp;
+ }
+ if (bf_resize(r, a_len + b_len)) {
+#ifdef USE_FFT_MUL
+ fail:
+#endif
+ bf_set_nan(r);
+ ret = BF_ST_MEM_ERROR;
+ goto done;
+ }
+ mp_mul_basecase(r->tab, a_tab, a_len, b_tab, b_len);
+ }
+ r->sign = r_sign;
+ r->expn = a->expn + b->expn;
+ ret = bf_normalize_and_round(r, prec, flags);
+ done:
+ if (r == &tmp)
+ bf_move(r1, &tmp);
+ }
+ return ret;
+}
+
+/* multiply 'r' by 2^e */
+int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags)
+{
+ slimb_t e_max;
+ if (r->len == 0)
+ return 0;
+ e_max = ((limb_t)1 << BF_EXT_EXP_BITS_MAX) - 1;
+ e = bf_max(e, -e_max);
+ e = bf_min(e, e_max);
+ r->expn += e;
+ return __bf_round(r, prec, flags, r->len, 0);
+}
+
+/* Return e such as a=m*2^e with m odd integer. return 0 if a is zero,
+ Infinite or Nan. */
+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) {
+ k = ctz(v);
+ return a->expn - (a->len - i) * LIMB_BITS + k;
+ }
+ }
+ return 0;
+}
+
+/* a and b must be finite numbers with a >= 0 and b > 0. 'q' is the
+ integer defined as floor(a/b) and r = a - q * b. */
+static void bf_tdivremu(bf_t *q, bf_t *r,
+ const bf_t *a, const bf_t *b)
+{
+ if (bf_cmpu(a, b) < 0) {
+ bf_set_ui(q, 0);
+ bf_set(r, a);
+ } else {
+ bf_div(q, a, b, bf_max(a->expn - b->expn + 1, 2), BF_RNDZ);
+ bf_rint(q, BF_RNDZ);
+ bf_mul(r, q, b, BF_PREC_INF, BF_RNDZ);
+ bf_sub(r, a, r, BF_PREC_INF, BF_RNDZ);
+ }
+}
+
+static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ 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) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF && b->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_inf(r, r_sign);
+ return 0;
+ } else {
+ bf_set_zero(r, r_sign);
+ return 0;
+ }
+ } else if (a->expn == BF_EXP_ZERO) {
+ if (b->expn == BF_EXP_ZERO) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_zero(r, r_sign);
+ return 0;
+ }
+ } else if (b->expn == BF_EXP_ZERO) {
+ bf_set_inf(r, r_sign);
+ return BF_ST_DIVIDE_ZERO;
+ }
+
+ /* number of limbs of the quotient (2 extra bits for rounding) */
+ 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)
+ goto fail;
+ d = na - a->len;
+ memset(taba, 0, d * sizeof(limb_t));
+ memcpy(taba + d, a->tab, a->len * sizeof(limb_t));
+ if (bf_resize(r, n + 1))
+ goto fail1;
+ if (mp_divnorm(s, r->tab, taba, na, b->tab, nb)) {
+ fail1:
+ bf_free(s, taba);
+ goto fail;
+ }
+ /* see if non zero remainder */
+ if (mp_scan_nz(taba, nb))
+ r->tab[0] |= 1;
+ bf_free(r->ctx, taba);
+ r->expn = a->expn - b->expn + LIMB_BITS;
+ r->sign = r_sign;
+ ret = bf_normalize_and_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+/* division and remainder.
+
+ rnd_mode is the rounding mode for the quotient. The additional
+ rounding mode BF_RND_EUCLIDIAN is supported.
+
+ 'q' is an integer. 'r' is rounded with prec and flags (prec can be
+ BF_PREC_INF).
+*/
+int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
+ limb_t prec, bf_flags_t flags, int rnd_mode)
+{
+ bf_t a1_s, *a1 = &a1_s;
+ 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) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF || b->expn == BF_EXP_ZERO) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set(r, a);
+ return bf_round(r, prec, flags);
+ }
+ }
+
+ q_sign = a->sign ^ b->sign;
+ is_rndn = (rnd_mode == BF_RNDN || rnd_mode == BF_RNDNA);
+ switch(rnd_mode) {
+ default:
+ case BF_RNDZ:
+ case BF_RNDN:
+ case BF_RNDNA:
+ is_ceil = FALSE;
+ break;
+ case BF_RNDD:
+ is_ceil = q_sign;
+ break;
+ case BF_RNDU:
+ is_ceil = q_sign ^ 1;
+ break;
+ case BF_RNDA:
+ is_ceil = TRUE;
+ break;
+ case BF_DIVREM_EUCLIDIAN:
+ is_ceil = a->sign;
+ break;
+ }
+
+ a1->expn = a->expn;
+ a1->tab = a->tab;
+ a1->len = a->len;
+ a1->sign = 0;
+
+ b1->expn = b->expn;
+ b1->tab = b->tab;
+ b1->len = b->len;
+ b1->sign = 0;
+
+ /* XXX: could improve to avoid having a large 'q' */
+ bf_tdivremu(q, r, a1, b1);
+ if (bf_is_nan(q) || bf_is_nan(r))
+ goto fail;
+
+ if (r->len != 0) {
+ if (is_rndn) {
+ int res;
+ b1->expn--;
+ res = bf_cmpu(r, b1);
+ b1->expn++;
+ if (res > 0 ||
+ (res == 0 &&
+ (rnd_mode == BF_RNDNA ||
+ get_bit(q->tab, q->len, q->len * LIMB_BITS - q->expn)))) {
+ goto do_sub_r;
+ }
+ } else if (is_ceil) {
+ do_sub_r:
+ ret = bf_add_si(q, q, 1, BF_PREC_INF, BF_RNDZ);
+ ret |= bf_sub(r, r, b1, BF_PREC_INF, BF_RNDZ);
+ if (ret & BF_ST_MEM_ERROR)
+ goto fail;
+ }
+ }
+
+ r->sign ^= a->sign;
+ q->sign = q_sign;
+ return bf_round(r, prec, flags);
+ fail:
+ bf_set_nan(q);
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode)
+{
+ 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);
+ return ret;
+}
+
+static inline int bf_get_limb(slimb_t *pres, const bf_t *a, int flags)
+{
+#if LIMB_BITS == 32
+ return bf_get_int32(pres, a, flags);
+#else
+ return bf_get_int64(pres, a, flags);
+#endif
+}
+
+int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode)
+{
+ 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);
+ bf_delete(q);
+ return ret;
+}
+
+static __maybe_unused inline limb_t mul_mod(limb_t a, limb_t b, limb_t m)
+{
+ dlimb_t t;
+ t = (dlimb_t)a * (dlimb_t)b;
+ return t % m;
+}
+
+#if defined(USE_MUL_CHECK)
+static limb_t mp_mod1(const limb_t *tab, limb_t n, limb_t m, limb_t r)
+{
+ slimb_t i;
+ dlimb_t t;
+
+ for(i = n - 1; i >= 0; i--) {
+ t = ((dlimb_t)r << LIMB_BITS) | tab[i];
+ r = t % m;
+ }
+ return r;
+}
+#endif
+
+static const uint16_t sqrt_table[192] = {
+128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156,157,158,159,160,160,161,162,163,163,164,165,166,167,167,168,169,170,170,171,172,173,173,174,175,176,176,177,178,178,179,180,181,181,182,183,183,184,185,185,186,187,187,188,189,189,190,191,192,192,193,193,194,195,195,196,197,197,198,199,199,200,201,201,202,203,203,204,204,205,206,206,207,208,208,209,209,210,211,211,212,212,213,214,214,215,215,216,217,217,218,218,219,219,220,221,221,222,222,223,224,224,225,225,226,226,227,227,228,229,229,230,230,231,231,232,232,233,234,234,235,235,236,236,237,237,238,238,239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255,
+};
+
+/* a >= 2^(LIMB_BITS - 2). Return (s, r) with s=floor(sqrt(a)) and
+ r=a-s^2. 0 <= r <= 2 * s */
+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;
+ if (r1 > 2 * s1) {
+ 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 */
+ u = num % (2 * s1);
+ s = (s1 << 8) + q;
+ r = (u << 8) | ((a >> (LIMB_BITS - 32)) & 0xff);
+ r -= q * q;
+ if ((slimb_t)r < 0) {
+ s--;
+ r += 2 * s + 1;
+ }
+
+#if LIMB_BITS == 64
+ s1 = s;
+ r1 = r;
+ /* one more iteration for 64 -> 32 bit sqrt */
+ num = (r1 << 16) | ((a >> (LIMB_BITS - 64 + 16)) & 0xffff);
+ q = num / (2 * s1); /* q <= 2^16 */
+ u = num % (2 * s1);
+ s = (s1 << 16) + q;
+ r = (u << 16) | ((a >> (LIMB_BITS - 64)) & 0xffff);
+ r -= q * q;
+ if ((slimb_t)r < 0) {
+ s--;
+ r += 2 * s + 1;
+ }
+#endif
+ *pr = r;
+ return s;
+}
+
+/* return floor(sqrt(a)) */
+limb_t bf_isqrt(limb_t a)
+{
+ limb_t s, r;
+ int k;
+
+ if (a == 0)
+ return 0;
+ k = clz(a) & ~1;
+ s = mp_sqrtrem1(&r, a << k);
+ s >>= (k >> 1);
+ return s;
+}
+
+static limb_t mp_sqrtrem2(limb_t *tabs, limb_t *taba)
+{
+ limb_t s1, r1, s, q, u, a0, a1;
+ dlimb_t r, num;
+ int l;
+
+ a0 = taba[0];
+ a1 = taba[1];
+ s1 = mp_sqrtrem1(&r1, a1);
+ l = LIMB_BITS / 2;
+ num = ((dlimb_t)r1 << l) | (a0 >> l);
+ q = num / (2 * s1);
+ u = num % (2 * s1);
+ s = (s1 << l) + q;
+ r = ((dlimb_t)u << l) | (a0 & (((limb_t)1 << l) - 1));
+ if (unlikely((q >> l) != 0))
+ r -= (dlimb_t)1 << LIMB_BITS; /* special case when q=2^l */
+ else
+ r -= q * q;
+ if ((slimb_t)(r >> LIMB_BITS) < 0) {
+ s--;
+ r += 2 * (dlimb_t)s + 1;
+ }
+ tabs[0] = s;
+ taba[0] = r;
+ return r >> LIMB_BITS;
+}
+
+//#define DEBUG_SQRTREM
+
+/* tmp_buf must contain (n / 2 + 1 limbs). *prh contains the highest
+ limb of the remainder. */
+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;
+ }
+#ifdef DEBUG_SQRTREM
+ mp_print_str("a", taba, 2 * n);
+#endif
+ l = n / 2;
+ h = n - l;
+ if (mp_sqrtrem_rec(s, tabs + l, taba + 2 * l, h, tmp_buf, &qh))
+ return -1;
+#ifdef DEBUG_SQRTREM
+ mp_print_str("s1", tabs + l, h);
+ 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);
+ }
+ /* instead of dividing by 2*s, divide by s (which is normalized)
+ and update q and r */
+ if (mp_divnorm(s, tmp_buf, taba + l, n, tabs + l, h))
+ return -1;
+ qh += tmp_buf[l];
+ for(i = 0; i < l; i++)
+ tabs[i] = tmp_buf[i];
+ ql = mp_shr(tabs, tabs, l, 1, qh & 1);
+ qh = qh >> 1; /* 0 or 1 */
+ if (ql)
+ rh = mp_add(taba + l, taba + l, tabs + l, h, 0);
+ else
+ rh = 0;
+#ifdef DEBUG_SQRTREM
+ 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) {
+ c = qh;
+ } else {
+ if (mp_mul(s, taba + n, tabs, l, tabs, l))
+ return -1;
+ c = mp_sub(taba, taba, taba + n, 2 * l, 0);
+ }
+ rh -= mp_sub_ui(taba + 2 * l, c, n - 2 * l);
+ if ((slimb_t)rh < 0) {
+ mp_sub_ui(tabs, 1, n);
+ rh += mp_add_mul1(taba, tabs, n, 2);
+ rh += mp_add_ui(taba, 1, n);
+ }
+ *prh = rh;
+ return 0;
+}
+
+/* 'taba' has 2*n limbs with n >= 1 and taba[2*n-1] >= 2 ^ (LIMB_BITS
+ - 2). Return (s, r) with s=floor(sqrt(a)) and r=a-s^2. 0 <= r <= 2
+ * s. tabs has n limbs. r is returned in the lower n limbs of
+ taba. Its r[n] is the returned value of the function. */
+/* Algorithm from the article "Karatsuba Square Root" by Paul Zimmermann and
+ inspirated from its GMP implementation */
+int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n)
+{
+ limb_t tmp_buf1[8];
+ limb_t *tmp_buf;
+ mp_size_t n2;
+ int ret;
+ n2 = n / 2 + 1;
+ if (n2 <= countof(tmp_buf1)) {
+ tmp_buf = tmp_buf1;
+ } else {
+ tmp_buf = bf_malloc(s, sizeof(limb_t) * n2);
+ if (!tmp_buf)
+ return -1;
+ }
+ ret = mp_sqrtrem_rec(s, tabs, taba, n, tmp_buf, taba + n);
+ if (tmp_buf != tmp_buf1)
+ bf_free(s, tmp_buf);
+ return ret;
+}
+
+/* Integer square root with remainder. 'a' must be an integer. r =
+ floor(sqrt(a)) and rem = a - r^2. BF_ST_INEXACT is set if the result
+ is inexact. 'rem' can be NULL if the remainder is not needed. */
+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);
+ } else if (a->expn == BF_EXP_INF && a->sign) {
+ goto invalid_op;
+ } else {
+ bf_set(r, a);
+ }
+ if (rem1)
+ bf_set_ui(rem1, 0);
+ ret = 0;
+ } else if (a->sign) {
+ invalid_op:
+ bf_set_nan(r);
+ if (rem1)
+ bf_set_ui(rem1, 0);
+ 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 */
+ if (rem1) {
+ rem = rem1;
+ } else {
+ rem = &rem_s;
+ bf_init(r->ctx, rem);
+ }
+ /* XXX: could avoid recomputing the remainder */
+ bf_mul(rem, r, r, BF_PREC_INF, BF_RNDZ);
+ bf_neg(rem);
+ bf_add(rem, rem, a, BF_PREC_INF, BF_RNDZ);
+ if (bf_is_nan(rem)) {
+ ret = BF_ST_MEM_ERROR;
+ goto done;
+ }
+ if (rem->len != 0) {
+ ret = BF_ST_INEXACT;
+ } else {
+ ret = 0;
+ }
+ done:
+ if (!rem1)
+ bf_delete(rem);
+ }
+ return ret;
+}
+
+int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = a->ctx;
+ int ret;
+
+ assert(r != a);
+
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else if (a->expn == BF_EXP_INF && a->sign) {
+ goto invalid_op;
+ } else {
+ bf_set(r, a);
+ }
+ ret = 0;
+ } else if (a->sign) {
+ invalid_op:
+ bf_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ 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);
+ if (bf_resize(r, n))
+ goto fail;
+ a1 = bf_malloc(s, sizeof(limb_t) * 2 * n);
+ if (!a1)
+ goto fail;
+ n1 = bf_min(2 * n, a->len);
+ memset(a1, 0, (2 * n - n1) * sizeof(limb_t));
+ memcpy(a1 + 2 * n - n1, a->tab + a->len - n1, n1 * sizeof(limb_t));
+ if (a->expn & 1) {
+ res = mp_shr(a1, a1, 2 * n, 1, 0);
+ } else {
+ res = 0;
+ }
+ if (mp_sqrtrem(s, r->tab, a1, n)) {
+ bf_free(s, a1);
+ goto fail;
+ }
+ if (!res) {
+ res = mp_scan_nz(a1, n + 1);
+ }
+ bf_free(s, a1);
+ if (!res) {
+ res = mp_scan_nz(a->tab, a->len - n1);
+ }
+ if (res != 0)
+ r->tab[0] |= 1;
+ r->sign = 0;
+ r->expn = (a->expn + 1) >> 1;
+ ret = bf_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+static no_inline int bf_op2(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, bf_op2_func_t *func)
+{
+ bf_t tmp;
+ int ret;
+
+ if (r == a || r == b) {
+ bf_init(r->ctx, &tmp);
+ ret = func(&tmp, a, b, prec, flags);
+ bf_move(r, &tmp);
+ } else {
+ ret = func(r, a, b, prec, flags);
+ }
+ return ret;
+}
+
+int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2(r, a, b, prec, flags, __bf_add);
+}
+
+int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2(r, a, b, prec, flags, __bf_sub);
+}
+
+int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2(r, a, b, prec, flags, __bf_div);
+}
+
+int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bf_t b;
+ int ret;
+ bf_init(r->ctx, &b);
+ ret = bf_set_ui(&b, b1);
+ ret |= bf_mul(r, a, &b, prec, flags);
+ bf_delete(&b);
+ return ret;
+}
+
+int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bf_t b;
+ int ret;
+ bf_init(r->ctx, &b);
+ ret = bf_set_si(&b, b1);
+ ret |= bf_mul(r, a, &b, prec, flags);
+ bf_delete(&b);
+ return ret;
+}
+
+int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bf_t b;
+ int ret;
+
+ bf_init(r->ctx, &b);
+ ret = bf_set_si(&b, b1);
+ ret |= bf_add(r, a, &b, prec, flags);
+ bf_delete(&b);
+ return ret;
+}
+
+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);
+ ret = bf_set(r, a);
+ n_bits = LIMB_BITS - clz(b);
+ for(i = n_bits - 2; i >= 0; i--) {
+ ret |= bf_mul(r, r, r, prec, flags);
+ if ((b >> i) & 1)
+ ret |= bf_mul(r, r, a, prec, flags);
+ }
+ return ret;
+}
+
+static int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b,
+ limb_t prec, bf_flags_t flags)
+{
+ bf_t a;
+ int ret;
+
+#ifdef USE_BF_DEC
+ if (a1 == 10 && b <= LIMB_DIGITS) {
+ /* use precomputed powers. We do not round at this point
+ because we expect the caller to do it */
+ ret = bf_set_ui(r, mp_pow_dec[b]);
+ } else
+#endif
+ {
+ bf_init(r->ctx, &a);
+ ret = bf_set_ui(&a, a1);
+ ret |= bf_pow_ui(r, &a, b, prec, flags);
+ bf_delete(&a);
+ }
+ return ret;
+}
+
+/* convert to integer (infinite precision) */
+int bf_rint(bf_t *r, int rnd_mode)
+{
+ return bf_round(r, 0, rnd_mode | BF_FLAG_RADPNT_PREC);
+}
+
+/* logical operations */
+#define BF_LOGIC_OR 0
+#define BF_LOGIC_XOR 1
+#define BF_LOGIC_AND 2
+
+static inline limb_t bf_logic_op1(limb_t a, limb_t b, int op)
+{
+ switch(op) {
+ case BF_LOGIC_OR:
+ return a | b;
+ case BF_LOGIC_XOR:
+ return a ^ b;
+ default:
+ case BF_LOGIC_AND:
+ return a & b;
+ }
+}
+
+static int bf_logic_op(bf_t *r, const bf_t *a1, const bf_t *b1, int op)
+{
+ bf_t b1_s, a1_s, *a, *b;
+ limb_t a_sign, b_sign, r_sign;
+ 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)
+ a_sign = 0; /* minus zero is considered as positive */
+ else
+ a_sign = a1->sign;
+
+ if (b1->expn <= 0)
+ 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);
+ if (bf_add_si(a, a1, 1, BF_PREC_INF, BF_RNDZ)) {
+ b = NULL;
+ goto fail;
+ }
+ } else {
+ a = (bf_t *)a1;
+ }
+
+ if (b_sign) {
+ b = &b1_s;
+ bf_init(r->ctx, b);
+ if (bf_add_si(b, b1, 1, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ } 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 */
+ if (a_sign == 0 && b_sign == 0)
+ l = bf_min(a->expn, b->expn);
+ else if (a_sign == 0)
+ l = a->expn;
+ else
+ l = b->expn;
+ } else {
+ l = bf_max(a->expn, b->expn);
+ }
+ /* Note: a or b can be zero */
+ l = (bf_max(l, 1) + LIMB_BITS - 1) / LIMB_BITS;
+ if (bf_resize(r, l))
+ goto fail;
+ a_bit_offset = a->len * LIMB_BITS - a->expn;
+ b_bit_offset = b->len * LIMB_BITS - b->expn;
+ v1_mask = -a_sign;
+ v2_mask = -b_sign;
+ r_mask = -r_sign;
+ for(i = 0; i < l; i++) {
+ v1 = get_bits(a->tab, a->len, a_bit_offset + i * LIMB_BITS) ^ v1_mask;
+ v2 = get_bits(b->tab, b->len, b_bit_offset + i * LIMB_BITS) ^ v2_mask;
+ r->tab[i] = bf_logic_op1(v1, v2, op) ^ r_mask;
+ }
+ r->expn = l * LIMB_BITS;
+ r->sign = r_sign;
+ bf_normalize_and_round(r, BF_PREC_INF, BF_RNDZ); /* cannot fail */
+ if (r_sign) {
+ if (bf_add_si(r, r, -1, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ }
+ ret = 0;
+ done:
+ if (a == &a1_s)
+ bf_delete(a);
+ if (b == &b1_s)
+ bf_delete(b);
+ return ret;
+ fail:
+ bf_set_nan(r);
+ ret = BF_ST_MEM_ERROR;
+ goto done;
+}
+
+/* 'a' and 'b' must be integers. Return 0 or BF_ST_MEM_ERROR. */
+int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b)
+{
+ return bf_logic_op(r, a, b, BF_LOGIC_OR);
+}
+
+/* 'a' and 'b' must be integers. Return 0 or BF_ST_MEM_ERROR. */
+int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b)
+{
+ return bf_logic_op(r, a, b, BF_LOGIC_XOR);
+}
+
+/* 'a' and 'b' must be integers. Return 0 or BF_ST_MEM_ERROR. */
+int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b)
+{
+ return bf_logic_op(r, a, b, BF_LOGIC_AND);
+}
+
+/* conversion between fixed size types */
+
+typedef union {
+ double d;
+ uint64_t u;
+} Float64Union;
+
+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)) {
+ ret = bf_round(b, 53, rnd_mode | BF_FLAG_SUBNORMAL | bf_set_exp_bits(11));
+ }
+ if (b->expn == BF_EXP_INF) {
+ e = (1 << 11) - 1;
+ m = 0;
+ } else if (b->expn == BF_EXP_ZERO) {
+ e = 0;
+ m = 0;
+ } else {
+ e = b->expn + 1023 - 1;
+#if LIMB_BITS == 32
+ if (b->len == 2) {
+ m = ((uint64_t)b->tab[1] << 32) | b->tab[0];
+ } else {
+ m = ((uint64_t)b->tab[0] << 32);
+ }
+#else
+ m = b->tab[0];
+#endif
+ if (e <= 0) {
+ /* subnormal */
+ m = m >> (12 - e);
+ e = 0;
+ } else {
+ m = (m << 1) >> 12;
+ }
+ }
+ u.u = m | ((uint64_t)e << 52) | ((uint64_t)b->sign << 63);
+ bf_delete(b);
+ }
+ *pres = u.d;
+ return ret;
+}
+
+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);
+ m = u.u & (((uint64_t)1 << 52) - 1);
+ if (e == ((1 << 11) - 1)) {
+ if (m != 0) {
+ bf_set_nan(a);
+ } else {
+ bf_set_inf(a, sgn);
+ }
+ } else if (e == 0) {
+ if (m == 0) {
+ bf_set_zero(a, sgn);
+ } else {
+ /* subnormal number */
+ m <<= 12;
+ shift = clz64(m);
+ m <<= shift;
+ e = -shift;
+ goto norm;
+ }
+ } else {
+ m = (m << 11) | ((uint64_t)1 << 63);
+ norm:
+ a->expn = e - 1023 + 1;
+#if LIMB_BITS == 32
+ if (bf_resize(a, 2))
+ goto fail;
+ a->tab[0] = m;
+ a->tab[1] = m >> 32;
+#else
+ if (bf_resize(a, 1))
+ goto fail;
+ a->tab[0] = m;
+#endif
+ a->sign = sgn;
+ }
+ return 0;
+fail:
+ bf_set_nan(a);
+ return BF_ST_MEM_ERROR;
+}
+
+/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
+ is an overflow and 0 otherwise. */
+int bf_get_int32(int *pres, const bf_t *a, int flags)
+{
+ uint32_t v;
+ int ret;
+ if (a->expn >= BF_EXP_INF) {
+ ret = BF_ST_INVALID_OP;
+ if (flags & BF_GET_INT_MOD) {
+ v = 0;
+ } else if (a->expn == BF_EXP_INF) {
+ v = (uint32_t)INT32_MAX + a->sign;
+ } else {
+ v = INT32_MAX;
+ }
+ } else if (a->expn <= 0) {
+ v = 0;
+ ret = 0;
+ } else if (a->expn <= 31) {
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ } else if (!(flags & BF_GET_INT_MOD)) {
+ ret = BF_ST_INVALID_OP;
+ if (a->sign) {
+ v = (uint32_t)INT32_MAX + 1;
+ if (a->expn == 32 &&
+ (a->tab[a->len - 1] >> (LIMB_BITS - 32)) == v) {
+ ret = 0;
+ }
+ } else {
+ v = INT32_MAX;
+ }
+ } else {
+ v = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn);
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ }
+ *pres = v;
+ return ret;
+}
+
+/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
+ is an overflow and 0 otherwise. */
+int bf_get_int64(int64_t *pres, const bf_t *a, int flags)
+{
+ uint64_t v;
+ int ret;
+ if (a->expn >= BF_EXP_INF) {
+ ret = BF_ST_INVALID_OP;
+ if (flags & BF_GET_INT_MOD) {
+ v = 0;
+ } else if (a->expn == BF_EXP_INF) {
+ v = (uint64_t)INT64_MAX + a->sign;
+ } else {
+ v = INT64_MAX;
+ }
+ } else if (a->expn <= 0) {
+ v = 0;
+ ret = 0;
+ } else if (a->expn <= 63) {
+#if LIMB_BITS == 32
+ if (a->expn <= 32)
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+ else
+ v = (((uint64_t)a->tab[a->len - 1] << 32) |
+ get_limbz(a, a->len - 2)) >> (64 - a->expn);
+#else
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+#endif
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ } else if (!(flags & BF_GET_INT_MOD)) {
+ ret = BF_ST_INVALID_OP;
+ if (a->sign) {
+ uint64_t v1;
+ v = (uint64_t)INT64_MAX + 1;
+ if (a->expn == 64) {
+ v1 = a->tab[a->len - 1];
+#if LIMB_BITS == 32
+ v1 = (v1 << 32) | get_limbz(a, a->len - 2);
+#endif
+ if (v1 == v)
+ ret = 0;
+ }
+ } else {
+ v = INT64_MAX;
+ }
+ } else {
+ slimb_t bit_pos = a->len * LIMB_BITS - a->expn;
+ 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
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ }
+ *pres = v;
+ return ret;
+}
+
+/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
+ is an overflow and 0 otherwise. */
+int bf_get_uint64(uint64_t *pres, const bf_t *a)
+{
+ uint64_t v;
+ int ret;
+ if (a->expn == BF_EXP_NAN) {
+ goto overflow;
+ } else if (a->expn <= 0) {
+ v = 0;
+ ret = 0;
+ } else if (a->sign) {
+ v = 0;
+ ret = BF_ST_INVALID_OP;
+ } else if (a->expn <= 64) {
+#if LIMB_BITS == 32
+ if (a->expn <= 32)
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+ else
+ v = (((uint64_t)a->tab[a->len - 1] << 32) |
+ get_limbz(a, a->len - 2)) >> (64 - a->expn);
+#else
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+#endif
+ ret = 0;
+ } else {
+ overflow:
+ v = UINT64_MAX;
+ ret = BF_ST_INVALID_OP;
+ }
+ *pres = v;
+ return ret;
+}
+
+/* base conversion from radix */
+
+static const uint8_t digits_per_limb_table[BF_RADIX_MAX - 1] = {
+#if LIMB_BITS == 32
+32,20,16,13,12,11,10,10, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+#else
+64,40,32,27,24,22,21,20,19,18,17,17,16,16,16,15,15,15,14,14,14,14,13,13,13,13,13,13,13,12,12,12,12,12,12,
+#endif
+};
+
+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++)
+ radixl *= radix;
+ return radixl;
+}
+
+/* return != 0 if error */
+static int bf_integer_from_radix_rec(bf_t *r, const limb_t *tab,
+ limb_t n, int level, limb_t n0,
+ limb_t radix, bf_t *pow_tab)
+{
+ int ret;
+ if (n == 1) {
+ ret = bf_set_ui(r, tab[0]);
+ } 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);
+ B = &pow_tab[level];
+ if (B->len == 0) {
+ ret = bf_pow_ui_ui(B, radix, n2, BF_PREC_INF, BF_RNDZ);
+ if (ret)
+ return ret;
+ }
+ ret = bf_integer_from_radix_rec(r, tab + n2, n1, level + 1, n0,
+ radix, pow_tab);
+ if (ret)
+ return ret;
+ ret = bf_mul(r, r, B, BF_PREC_INF, BF_RNDZ);
+ if (ret)
+ return ret;
+ bf_init(r->ctx, T);
+ ret = bf_integer_from_radix_rec(T, tab, n2, level + 1, n0,
+ radix, pow_tab);
+ if (!ret)
+ ret = bf_add(r, r, T, BF_PREC_INF, BF_RNDZ);
+ bf_delete(T);
+ }
+ return ret;
+ // bf_print_str(" r=", r);
+}
+
+/* return 0 if OK != 0 if memory error */
+static int bf_integer_from_radix(bf_t *r, const limb_t *tab,
+ limb_t n, limb_t radix)
+{
+ bf_context_t *s = r->ctx;
+ 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);
+ if (!pow_tab)
+ return -1;
+ for(i = 0; i < pow_tab_len; i++)
+ bf_init(r->ctx, &pow_tab[i]);
+ ret = bf_integer_from_radix_rec(r, tab, n, 0, n, radixl, pow_tab);
+ for(i = 0; i < pow_tab_len; i++) {
+ bf_delete(&pow_tab[i]);
+ }
+ bf_free(s, pow_tab);
+ return ret;
+}
+
+/* compute and round T * radix^expn. */
+int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
+ slimb_t expn, limb_t prec, bf_flags_t flags)
+{
+ int ret, expn_sign, overflow;
+ slimb_t e, extra_bits, prec1, ziv_extra_bits;
+ bf_t B_s, *B = &B_s;
+
+ if (T->len == 0) {
+ return bf_set(r, T);
+ } else if (expn == 0) {
+ ret = bf_set(r, T);
+ ret |= bf_round(r, prec, flags);
+ return ret;
+ }
+
+ e = expn;
+ expn_sign = 0;
+ if (e < 0) {
+ e = -e;
+ expn_sign = 1;
+ }
+ bf_init(r->ctx, B);
+ if (prec == BF_PREC_INF) {
+ /* infinite precision: only used if the result is known to be exact */
+ ret = bf_pow_ui_ui(B, radix, e, BF_PREC_INF, BF_RNDN);
+ if (expn_sign) {
+ ret |= bf_div(r, T, B, T->len * LIMB_BITS, BF_RNDN);
+ } else {
+ ret |= bf_mul(r, T, B, BF_PREC_INF, BF_RNDN);
+ }
+ } else {
+ ziv_extra_bits = 16;
+ for(;;) {
+ prec1 = prec + ziv_extra_bits;
+ /* XXX: correct overflow/underflow handling */
+ /* XXX: rigorous error analysis needed */
+ extra_bits = ceil_log2(e) * 2 + 1;
+ ret = bf_pow_ui_ui(B, radix, e, prec1 + extra_bits, BF_RNDN | BF_FLAG_EXT_EXP);
+ overflow = !bf_is_finite(B);
+ /* XXX: if bf_pow_ui_ui returns an exact result, can stop
+ after the next operation */
+ if (expn_sign)
+ ret |= bf_div(r, T, B, prec1 + extra_bits, BF_RNDN | BF_FLAG_EXT_EXP);
+ else
+ ret |= bf_mul(r, T, B, prec1 + extra_bits, BF_RNDN | BF_FLAG_EXT_EXP);
+ if (ret & BF_ST_MEM_ERROR)
+ break;
+ if ((ret & BF_ST_INEXACT) &&
+ !bf_can_round(r, prec, flags & BF_RND_MASK, prec1) &&
+ !overflow) {
+ /* and more precision and retry */
+ ziv_extra_bits = ziv_extra_bits + (ziv_extra_bits / 2);
+ } else {
+ /* XXX: need to use __bf_round() to pass the inexact
+ flag for the subnormal case */
+ ret = bf_round(r, prec, flags) | (ret & BF_ST_INEXACT);
+ break;
+ }
+ }
+ }
+ bf_delete(B);
+ return ret;
+}
+
+static inline int to_digit(int c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ else if (c >= 'A' && c <= 'Z')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'z')
+ return c - 'a' + 10;
+ else
+ return 36;
+}
+
+/* add a limb at 'pos' and decrement pos. new space is created if
+ needed. Return 0 if OK, -1 if memory error */
+static int bf_add_limb(bf_t *a, slimb_t *ppos, limb_t v)
+{
+ slimb_t pos;
+ pos = *ppos;
+ if (unlikely(pos < 0)) {
+ limb_t new_size, d, *new_tab;
+ new_size = bf_max(a->len + 1, a->len * 3 / 2);
+ new_tab = bf_realloc(a->ctx, a->tab, sizeof(limb_t) * new_size);
+ if (!new_tab)
+ return -1;
+ a->tab = new_tab;
+ d = new_size - a->len;
+ memmove(a->tab + d, a->tab, a->len * sizeof(limb_t));
+ a->len = new_size;
+ pos += d;
+ }
+ a->tab[pos--] = v;
+ *ppos = pos;
+ return 0;
+}
+
+static int bf_tolower(int c)
+{
+ if (c >= 'A' && c <= 'Z')
+ c = c - 'A' + 'a';
+ return c;
+}
+
+static int strcasestart(const char *str, const char *val, const char **ptr)
+{
+ const char *p, *q;
+ p = str;
+ q = val;
+ while (*q != '\0') {
+ if (bf_tolower(*p) != *q)
+ return 0;
+ p++;
+ q++;
+ }
+ if (ptr)
+ *ptr = p;
+ return 1;
+}
+
+static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
+ const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags, BOOL is_dec)
+{
+ const char *p, *p_start;
+ int is_neg, radix_bits, exp_is_neg, ret, digits_per_limb, shift;
+ limb_t cur_limb;
+ 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 &&
+ strcasestart(p, "nan", &p)) {
+ bf_set_nan(r);
+ ret = 0;
+ goto done;
+ }
+ is_neg = 0;
+
+ if (p[0] == '+') {
+ p++;
+ p_start = p;
+ } else if (p[0] == '-') {
+ is_neg = 1;
+ p++;
+ p_start = p;
+ } else {
+ p_start = p;
+ }
+ if (p[0] == '0') {
+ if ((p[1] == 'x' || p[1] == 'X') &&
+ (radix == 0 || radix == 16) &&
+ !(flags & BF_ATOF_NO_HEX)) {
+ radix = 16;
+ p += 2;
+ } else if ((p[1] == 'o' || p[1] == 'O') &&
+ radix == 0 && (flags & BF_ATOF_BIN_OCT)) {
+ p += 2;
+ radix = 8;
+ } else if ((p[1] == 'b' || p[1] == 'B') &&
+ radix == 0 && (flags & BF_ATOF_BIN_OCT)) {
+ p += 2;
+ radix = 2;
+ } else {
+ goto no_prefix;
+ }
+ /* there must be a digit after the prefix */
+ if (to_digit((uint8_t)*p) >= radix) {
+ bf_set_nan(r);
+ ret = 0;
+ goto done;
+ }
+ no_prefix: ;
+ } else {
+ if (!(flags & BF_ATOF_NO_NAN_INF) && radix <= 16 &&
+ strcasestart(p, "inf", &p)) {
+ bf_set_inf(r, is_neg);
+ ret = 0;
+ goto done;
+ }
+ }
+
+ if (radix == 0)
+ radix = 10;
+ if (is_dec) {
+ assert(radix == 10);
+ radix_bits = 0;
+ a = r;
+ } else if ((radix & (radix - 1)) != 0) {
+ radix_bits = 0; /* base is not a power of two */
+ a = &a_s;
+ bf_init(r->ctx, a);
+ } else {
+ radix_bits = ceil_log2(radix);
+ a = r;
+ }
+
+ /* skip leading zeros */
+ /* XXX: could also skip zeros after the decimal point */
+ while (*p == '0')
+ p++;
+
+ if (radix_bits) {
+ shift = digits_per_limb = LIMB_BITS;
+ } else {
+ radix_bits = 0;
+ shift = digits_per_limb = digits_per_limb_table[radix - 2];
+ }
+ cur_limb = 0;
+ bf_resize(a, 1);
+ pos = 0;
+ has_decpt = FALSE;
+ int_len = digit_count = 0;
+ for(;;) {
+ limb_t c;
+ if (*p == '.' && (p > p_start || to_digit(p[1]) < radix)) {
+ if (has_decpt)
+ break;
+ has_decpt = TRUE;
+ int_len = digit_count;
+ p++;
+ }
+ c = to_digit(*p);
+ if (c >= radix)
+ break;
+ digit_count++;
+ p++;
+ if (radix_bits) {
+ shift -= radix_bits;
+ if (shift <= 0) {
+ cur_limb |= c >> (-shift);
+ if (bf_add_limb(a, &pos, cur_limb))
+ goto mem_error;
+ if (shift < 0)
+ cur_limb = c << (LIMB_BITS + shift);
+ else
+ cur_limb = 0;
+ shift += LIMB_BITS;
+ } else {
+ cur_limb |= c << shift;
+ }
+ } else {
+ cur_limb = cur_limb * radix + c;
+ shift--;
+ if (shift == 0) {
+ if (bf_add_limb(a, &pos, cur_limb))
+ goto mem_error;
+ shift = digits_per_limb;
+ cur_limb = 0;
+ }
+ }
+ }
+ if (!has_decpt)
+ int_len = digit_count;
+
+ /* add the last limb and pad with zeros */
+ if (shift != digits_per_limb) {
+ if (radix_bits == 0) {
+ while (shift != 0) {
+ cur_limb *= radix;
+ shift--;
+ }
+ }
+ if (bf_add_limb(a, &pos, cur_limb)) {
+ mem_error:
+ ret = BF_ST_MEM_ERROR;
+ if (!radix_bits)
+ bf_delete(a);
+ bf_set_nan(r);
+ goto done;
+ }
+ }
+
+ /* reset the next limbs to zero (we prefer to reallocate in the
+ renormalization) */
+ memset(a->tab, 0, (pos + 1) * sizeof(limb_t));
+
+ if (p == p_start) {
+ ret = 0;
+ if (!radix_bits)
+ bf_delete(a);
+ bf_set_nan(r);
+ goto done;
+ }
+
+ /* parse the exponent, if any */
+ expn = 0;
+ is_bin_exp = FALSE;
+ if (((radix == 10 && (*p == 'e' || *p == 'E')) ||
+ (radix != 10 && (*p == '@' ||
+ (radix_bits && (*p == 'p' || *p == 'P'))))) &&
+ p > p_start) {
+ is_bin_exp = (*p == 'p' || *p == 'P');
+ p++;
+ exp_is_neg = 0;
+ if (*p == '+') {
+ p++;
+ } else if (*p == '-') {
+ exp_is_neg = 1;
+ p++;
+ }
+ for(;;) {
+ int c;
+ c = to_digit(*p);
+ if (c >= 10)
+ break;
+ if (unlikely(expn > ((BF_RAW_EXP_MAX - 2 - 9) / 10))) {
+ /* exponent overflow */
+ if (exp_is_neg) {
+ bf_set_zero(r, is_neg);
+ ret = BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ } else {
+ bf_set_inf(r, is_neg);
+ ret = BF_ST_OVERFLOW | BF_ST_INEXACT;
+ }
+ goto done;
+ }
+ p++;
+ expn = expn * 10 + c;
+ }
+ if (exp_is_neg)
+ expn = -expn;
+ }
+ if (is_dec) {
+ a->expn = expn + int_len;
+ a->sign = is_neg;
+ ret = bfdec_normalize_and_round((bfdec_t *)a, prec, flags);
+ } else if (radix_bits) {
+ /* XXX: may overflow */
+ if (!is_bin_exp)
+ expn *= radix_bits;
+ a->expn = expn + (int_len * radix_bits);
+ a->sign = is_neg;
+ ret = bf_normalize_and_round(a, prec, flags);
+ } else {
+ limb_t l;
+ pos++;
+ l = a->len - pos; /* number of limbs */
+ if (l == 0) {
+ bf_set_zero(r, is_neg);
+ ret = 0;
+ } else {
+ bf_t T_s, *T = &T_s;
+
+ expn -= l * digits_per_limb - int_len;
+ bf_init(r->ctx, T);
+ if (bf_integer_from_radix(T, a->tab + pos, l, radix)) {
+ bf_set_nan(r);
+ ret = BF_ST_MEM_ERROR;
+ } else {
+ T->sign = is_neg;
+ if (flags & BF_ATOF_EXPONENT) {
+ /* return the exponent */
+ *pexponent = expn;
+ ret = bf_set(r, T);
+ } else {
+ ret = bf_mul_pow_radix(r, T, radix, expn, prec, flags);
+ }
+ }
+ bf_delete(T);
+ }
+ bf_delete(a);
+ }
+ done:
+ if (pnext)
+ *pnext = p;
+ return ret;
+}
+
+/*
+ Return (status, n, exp). 'status' is the floating point status. 'n'
+ 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 *
+ (*pexponent)^radix. Otherwise *pexponent = 0.
+*/
+int bf_atof2(bf_t *r, slimb_t *pexponent,
+ const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags)
+{
+ return bf_atof_internal(r, pexponent, str, pnext, radix, prec, flags,
+ FALSE);
+}
+
+int bf_atof(bf_t *r, const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags)
+{
+ slimb_t dummy_exp;
+ return bf_atof_internal(r, &dummy_exp, str, pnext, radix, prec, flags, FALSE);
+}
+
+/* base conversion to radix */
+
+#if LIMB_BITS == 64
+#define RADIXL_10 UINT64_C(10000000000000000000)
+#else
+#define RADIXL_10 UINT64_C(1000000000)
+#endif
+
+static const uint32_t inv_log2_radix[BF_RADIX_MAX - 1][LIMB_BITS / 32 + 1] = {
+#if LIMB_BITS == 32
+{ 0x80000000, 0x00000000,},
+{ 0x50c24e60, 0xd4d4f4a7,},
+{ 0x40000000, 0x00000000,},
+{ 0x372068d2, 0x0a1ee5ca,},
+{ 0x3184648d, 0xb8153e7a,},
+{ 0x2d983275, 0x9d5369c4,},
+{ 0x2aaaaaaa, 0xaaaaaaab,},
+{ 0x28612730, 0x6a6a7a54,},
+{ 0x268826a1, 0x3ef3fde6,},
+{ 0x25001383, 0xbac8a744,},
+{ 0x23b46706, 0x82c0c709,},
+{ 0x229729f1, 0xb2c83ded,},
+{ 0x219e7ffd, 0xa5ad572b,},
+{ 0x20c33b88, 0xda7c29ab,},
+{ 0x20000000, 0x00000000,},
+{ 0x1f50b57e, 0xac5884b3,},
+{ 0x1eb22cc6, 0x8aa6e26f,},
+{ 0x1e21e118, 0x0c5daab2,},
+{ 0x1d9dcd21, 0x439834e4,},
+{ 0x1d244c78, 0x367a0d65,},
+{ 0x1cb40589, 0xac173e0c,},
+{ 0x1c4bd95b, 0xa8d72b0d,},
+{ 0x1bead768, 0x98f8ce4c,},
+{ 0x1b903469, 0x050f72e5,},
+{ 0x1b3b433f, 0x2eb06f15,},
+{ 0x1aeb6f75, 0x9c46fc38,},
+{ 0x1aa038eb, 0x0e3bfd17,},
+{ 0x1a593062, 0xb38d8c56,},
+{ 0x1a15f4c3, 0x2b95a2e6,},
+{ 0x19d630dc, 0xcc7ddef9,},
+{ 0x19999999, 0x9999999a,},
+{ 0x195fec80, 0x8a609431,},
+{ 0x1928ee7b, 0x0b4f22f9,},
+{ 0x18f46acf, 0x8c06e318,},
+{ 0x18c23246, 0xdc0a9f3d,},
+#else
+{ 0x80000000, 0x00000000, 0x00000000,},
+{ 0x50c24e60, 0xd4d4f4a7, 0x021f57bc,},
+{ 0x40000000, 0x00000000, 0x00000000,},
+{ 0x372068d2, 0x0a1ee5ca, 0x19ea911b,},
+{ 0x3184648d, 0xb8153e7a, 0x7fc2d2e1,},
+{ 0x2d983275, 0x9d5369c4, 0x4dec1661,},
+{ 0x2aaaaaaa, 0xaaaaaaaa, 0xaaaaaaab,},
+{ 0x28612730, 0x6a6a7a53, 0x810fabde,},
+{ 0x268826a1, 0x3ef3fde6, 0x23e2566b,},
+{ 0x25001383, 0xbac8a744, 0x385a3349,},
+{ 0x23b46706, 0x82c0c709, 0x3f891718,},
+{ 0x229729f1, 0xb2c83ded, 0x15fba800,},
+{ 0x219e7ffd, 0xa5ad572a, 0xe169744b,},
+{ 0x20c33b88, 0xda7c29aa, 0x9bddee52,},
+{ 0x20000000, 0x00000000, 0x00000000,},
+{ 0x1f50b57e, 0xac5884b3, 0x70e28eee,},
+{ 0x1eb22cc6, 0x8aa6e26f, 0x06d1a2a2,},
+{ 0x1e21e118, 0x0c5daab1, 0x81b4f4bf,},
+{ 0x1d9dcd21, 0x439834e3, 0x81667575,},
+{ 0x1d244c78, 0x367a0d64, 0xc8204d6d,},
+{ 0x1cb40589, 0xac173e0c, 0x3b7b16ba,},
+{ 0x1c4bd95b, 0xa8d72b0d, 0x5879f25a,},
+{ 0x1bead768, 0x98f8ce4c, 0x66cc2858,},
+{ 0x1b903469, 0x050f72e5, 0x0cf5488e,},
+{ 0x1b3b433f, 0x2eb06f14, 0x8c89719c,},
+{ 0x1aeb6f75, 0x9c46fc37, 0xab5fc7e9,},
+{ 0x1aa038eb, 0x0e3bfd17, 0x1bd62080,},
+{ 0x1a593062, 0xb38d8c56, 0x7998ab45,},
+{ 0x1a15f4c3, 0x2b95a2e6, 0x46aed6a0,},
+{ 0x19d630dc, 0xcc7ddef9, 0x5aadd61b,},
+{ 0x19999999, 0x99999999, 0x9999999a,},
+{ 0x195fec80, 0x8a609430, 0xe1106014,},
+{ 0x1928ee7b, 0x0b4f22f9, 0x5f69791d,},
+{ 0x18f46acf, 0x8c06e318, 0x4d2aeb2c,},
+{ 0x18c23246, 0xdc0a9f3d, 0x3fe16970,},
+#endif
+};
+
+static const limb_t log2_radix[BF_RADIX_MAX - 1] = {
+#if LIMB_BITS == 32
+0x20000000,
+0x32b80347,
+0x40000000,
+0x4a4d3c26,
+0x52b80347,
+0x59d5d9fd,
+0x60000000,
+0x6570068e,
+0x6a4d3c26,
+0x6eb3a9f0,
+0x72b80347,
+0x766a008e,
+0x79d5d9fd,
+0x7d053f6d,
+0x80000000,
+0x82cc7edf,
+0x8570068e,
+0x87ef05ae,
+0x8a4d3c26,
+0x8c8ddd45,
+0x8eb3a9f0,
+0x90c10501,
+0x92b80347,
+0x949a784c,
+0x966a008e,
+0x982809d6,
+0x99d5d9fd,
+0x9b74948f,
+0x9d053f6d,
+0x9e88c6b3,
+0xa0000000,
+0xa16bad37,
+0xa2cc7edf,
+0xa4231623,
+0xa570068e,
+#else
+0x2000000000000000,
+0x32b803473f7ad0f4,
+0x4000000000000000,
+0x4a4d3c25e68dc57f,
+0x52b803473f7ad0f4,
+0x59d5d9fd5010b366,
+0x6000000000000000,
+0x6570068e7ef5a1e8,
+0x6a4d3c25e68dc57f,
+0x6eb3a9f01975077f,
+0x72b803473f7ad0f4,
+0x766a008e4788cbcd,
+0x79d5d9fd5010b366,
+0x7d053f6d26089673,
+0x8000000000000000,
+0x82cc7edf592262d0,
+0x8570068e7ef5a1e8,
+0x87ef05ae409a0289,
+0x8a4d3c25e68dc57f,
+0x8c8ddd448f8b845a,
+0x8eb3a9f01975077f,
+0x90c10500d63aa659,
+0x92b803473f7ad0f4,
+0x949a784bcd1b8afe,
+0x966a008e4788cbcd,
+0x982809d5be7072dc,
+0x99d5d9fd5010b366,
+0x9b74948f5532da4b,
+0x9d053f6d26089673,
+0x9e88c6b3626a72aa,
+0xa000000000000000,
+0xa16bad3758efd873,
+0xa2cc7edf592262d0,
+0xa4231623369e78e6,
+0xa570068e7ef5a1e8,
+#endif
+};
+
+/* compute floor(a*b) or ceil(a*b) with b = log2(radix) or
+ b=1/log2(radix). For is_inv = 0, strict accuracy is not guaranteed
+ when radix is not a power of two. */
+slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
+ int is_ceil1)
+{
+ int is_neg;
+ limb_t a;
+ BOOL is_ceil;
+
+ is_ceil = is_ceil1;
+ a = a1;
+ if (a1 < 0) {
+ a = -a;
+ is_neg = 1;
+ } else {
+ is_neg = 0;
+ }
+ is_ceil ^= is_neg;
+ if ((radix & (radix - 1)) == 0) {
+ int radix_bits;
+ /* radix is a power of two */
+ radix_bits = ceil_log2(radix);
+ if (is_inv) {
+ if (is_ceil)
+ a += radix_bits - 1;
+ a = a / radix_bits;
+ } else {
+ a = a * radix_bits;
+ }
+ } else {
+ const uint32_t *tab;
+ limb_t b0, b1;
+ dlimb_t t;
+
+ if (is_inv) {
+ tab = inv_log2_radix[radix - 2];
+#if LIMB_BITS == 32
+ b1 = tab[0];
+ b0 = tab[1];
+#else
+ b1 = ((limb_t)tab[0] << 32) | tab[1];
+ b0 = (limb_t)tab[2] << 32;
+#endif
+ t = (dlimb_t)b0 * (dlimb_t)a;
+ t = (dlimb_t)b1 * (dlimb_t)a + (t >> LIMB_BITS);
+ a = t >> (LIMB_BITS - 1);
+ } else {
+ b0 = log2_radix[radix - 2];
+ t = (dlimb_t)b0 * (dlimb_t)a;
+ a = t >> (LIMB_BITS - 3);
+ }
+ /* a = floor(result) and 'result' cannot be an integer */
+ a += is_ceil;
+ }
+ if (is_neg)
+ a = -a;
+ return a;
+}
+
+/* 'n' is the number of output limbs */
+static int bf_integer_to_radix_rec(bf_t *pow_tab,
+ limb_t *out, const bf_t *a, limb_t n,
+ int level, limb_t n0, limb_t radixl,
+ unsigned int radixl_bits)
+{
+ 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);
+ } else if (n == 2) {
+ dlimb_t t;
+ slimb_t pos;
+ pos = a->len * LIMB_BITS - a->expn;
+ t = ((dlimb_t)get_bits(a->tab, a->len, pos + LIMB_BITS) << LIMB_BITS) |
+ get_bits(a->tab, a->len, pos);
+ if (likely(radixl == RADIXL_10)) {
+ /* use division by a constant when possible */
+ out[0] = t % RADIXL_10;
+ out[1] = t / RADIXL_10;
+ } else {
+ out[0] = t % radixl;
+ out[1] = t / radixl;
+ }
+ } else {
+ bf_t Q, R, *B, *B_inv;
+ int q_add;
+ bf_init(a->ctx, &Q);
+ bf_init(a->ctx, &R);
+ n2 = (((n0 * 2) >> (level + 1)) + 1) / 2;
+ n1 = n - n2;
+ B = &pow_tab[2 * level];
+ B_inv = &pow_tab[2 * level + 1];
+ ret = 0;
+ if (B->len == 0) {
+ /* compute BASE^n2 */
+ ret |= bf_pow_ui_ui(B, radixl, n2, BF_PREC_INF, BF_RNDZ);
+ /* we use enough bits for the maximum possible 'n1' value,
+ i.e. n2 + 1 */
+ ret |= bf_set_ui(&R, 1);
+ ret |= bf_div(B_inv, &R, B, (n2 + 1) * radixl_bits + 2, BF_RNDN);
+ }
+ // printf("%d: n1=% " PRId64 " n2=%" PRId64 "\n", level, n1, n2);
+ 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);
+
+ if (ret & BF_ST_MEM_ERROR)
+ goto fail;
+ /* adjust if necessary */
+ q_add = 0;
+ while (R.sign && R.len != 0) {
+ if (bf_add(&R, &R, B, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ q_add--;
+ }
+ while (bf_cmpu(&R, B) >= 0) {
+ if (bf_sub(&R, &R, B, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ q_add++;
+ }
+ if (q_add != 0) {
+ if (bf_add_si(&Q, &Q, q_add, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ }
+ if (bf_integer_to_radix_rec(pow_tab, out + n2, &Q, n1, level + 1, n0,
+ radixl, radixl_bits))
+ goto fail;
+ if (bf_integer_to_radix_rec(pow_tab, out, &R, n2, level + 1, n0,
+ radixl, radixl_bits)) {
+ fail:
+ bf_delete(&Q);
+ bf_delete(&R);
+ return -1;
+ }
+ bf_delete(&Q);
+ bf_delete(&R);
+ }
+ return 0;
+}
+
+/* return 0 if OK != 0 if memory error */
+static int bf_integer_to_radix(bf_t *r, const bf_t *a, limb_t radixl)
+{
+ bf_context_t *s = r->ctx;
+ 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);
+ if (!pow_tab)
+ return -1;
+ for(i = 0; i < pow_tab_len; i++)
+ bf_init(r->ctx, &pow_tab[i]);
+
+ ret = bf_integer_to_radix_rec(pow_tab, r->tab, a, r_len, 0, r_len, radixl,
+ ceil_log2(radixl));
+
+ for(i = 0; i < pow_tab_len; i++) {
+ bf_delete(&pow_tab[i]);
+ }
+ bf_free(s, pow_tab);
+ return ret;
+}
+
+/* a must be >= 0. 'P' is the wanted number of digits in radix
+ 'radix'. 'r' is the mantissa represented as an integer. *pE
+ contains the exponent. Return != 0 if memory error. */
+static int bf_convert_to_radix(bf_t *r, slimb_t *pE,
+ const bf_t *a, int radix,
+ limb_t P, bf_rnd_t rnd_mode,
+ BOOL is_fixed_exponent)
+{
+ 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;
+ return bf_set(r, a);
+ }
+
+ if (is_fixed_exponent) {
+ E = *pE;
+ } else {
+ /* compute the new exponent */
+ E = 1 + bf_mul_log2_radix(a->expn - 1, radix, TRUE, FALSE);
+ }
+ // bf_print_str("a", a);
+ // printf("E=%ld P=%ld radix=%d\n", E, P, radix);
+
+ for(;;) {
+ e = P - E;
+ e_sign = 0;
+ if (e < 0) {
+ e = -e;
+ e_sign = 1;
+ }
+ /* Note: precision for log2(radix) is not critical here */
+ prec0 = bf_mul_log2_radix(P, radix, FALSE, TRUE);
+ ziv_extra_bits = 16;
+ for(;;) {
+ prec = prec0 + ziv_extra_bits;
+ /* XXX: rigorous error analysis needed */
+ extra_bits = ceil_log2(e) * 2 + 1;
+ ret = bf_pow_ui_ui(r, radix, e, prec + extra_bits,
+ BF_RNDN | BF_FLAG_EXT_EXP);
+ if (!e_sign)
+ ret |= bf_mul(r, r, a, prec + extra_bits,
+ BF_RNDN | BF_FLAG_EXT_EXP);
+ else
+ ret |= bf_div(r, a, r, prec + extra_bits,
+ BF_RNDN | BF_FLAG_EXT_EXP);
+ if (ret & BF_ST_MEM_ERROR)
+ return BF_ST_MEM_ERROR;
+ /* if the result is not exact, check that it can be safely
+ rounded to an integer */
+ if ((ret & BF_ST_INEXACT) &&
+ !bf_can_round(r, r->expn, rnd_mode, prec)) {
+ /* and more precision and retry */
+ ziv_extra_bits = ziv_extra_bits + (ziv_extra_bits / 2);
+ continue;
+ } else {
+ ret = bf_rint(r, rnd_mode);
+ if (ret & BF_ST_MEM_ERROR)
+ return BF_ST_MEM_ERROR;
+ break;
+ }
+ }
+ if (is_fixed_exponent)
+ break;
+ /* check that the result is < B^P */
+ /* XXX: do a fast approximate test first ? */
+ bf_init(r->ctx, B);
+ ret = bf_pow_ui_ui(B, radix, P, BF_PREC_INF, BF_RNDZ);
+ if (ret) {
+ bf_delete(B);
+ return ret;
+ }
+ res = bf_cmpu(r, B);
+ bf_delete(B);
+ if (res < 0)
+ break;
+ /* try a larger exponent */
+ E++;
+ }
+ *pE = E;
+ return 0;
+}
+
+static void limb_to_a(char *buf, limb_t n, unsigned int radix, int len)
+{
+ int digit, i;
+
+ if (radix == 10) {
+ /* specific case with constant divisor */
+ for(i = len - 1; i >= 0; i--) {
+ digit = (limb_t)n % 10;
+ n = (limb_t)n / 10;
+ buf[i] = digit + '0';
+ }
+ } else {
+ for(i = len - 1; i >= 0; i--) {
+ digit = (limb_t)n % radix;
+ n = (limb_t)n / radix;
+ if (digit < 10)
+ digit += '0';
+ else
+ digit += 'a' - 10;
+ buf[i] = digit;
+ }
+ }
+}
+
+/* for power of 2 radixes */
+static void limb_to_a2(char *buf, limb_t n, unsigned int radix_bits, int len)
+{
+ int digit, i;
+ unsigned int mask;
+
+ mask = (1 << radix_bits) - 1;
+ for(i = len - 1; i >= 0; i--) {
+ digit = n & mask;
+ n >>= radix_bits;
+ if (digit < 10)
+ digit += '0';
+ else
+ digit += 'a' - 10;
+ buf[i] = digit;
+ }
+}
+
+/* 'a' must be an integer if the is_dec = FALSE or if the radix is not
+ a power of two. A dot is added before the 'dot_pos' digit. dot_pos
+ = n_digits does not display the dot. 0 <= dot_pos <=
+ n_digits. n_digits >= 1. */
+static void output_digits(DynBuf *s, const bf_t *a1, int radix, limb_t n_digits,
+ limb_t dot_pos, BOOL is_dec)
+{
+ limb_t i, v, l;
+ slimb_t pos, pos_incr;
+ int digits_per_limb, buf_pos, radix_bits, first_buf_pos;
+ char buf[65];
+ bf_t a_s, *a;
+
+ if (is_dec) {
+ digits_per_limb = LIMB_DIGITS;
+ a = (bf_t *)a1;
+ radix_bits = 0;
+ pos = a->len;
+ pos_incr = 1;
+ first_buf_pos = 0;
+ } else if ((radix & (radix - 1)) == 0) {
+ a = (bf_t *)a1;
+ radix_bits = ceil_log2(radix);
+ digits_per_limb = LIMB_BITS / radix_bits;
+ pos_incr = digits_per_limb * radix_bits;
+ /* digits are aligned relative to the radix point */
+ pos = a->len * LIMB_BITS + smod(-a->expn, radix_bits);
+ first_buf_pos = 0;
+ } else {
+ limb_t n, radixl;
+
+ digits_per_limb = digits_per_limb_table[radix - 2];
+ radixl = get_limb_radix(radix);
+ a = &a_s;
+ bf_init(a1->ctx, a);
+ n = (n_digits + digits_per_limb - 1) / digits_per_limb;
+ if (bf_resize(a, n)) {
+ dbuf_set_error(s);
+ goto done;
+ }
+ if (bf_integer_to_radix(a, a1, radixl)) {
+ dbuf_set_error(s);
+ goto done;
+ }
+ radix_bits = 0;
+ pos = n;
+ pos_incr = 1;
+ first_buf_pos = pos * digits_per_limb - n_digits;
+ }
+ buf_pos = digits_per_limb;
+ i = 0;
+ while (i < n_digits) {
+ if (buf_pos == digits_per_limb) {
+ pos -= pos_incr;
+ if (radix_bits == 0) {
+ v = get_limbz(a, pos);
+ limb_to_a(buf, v, radix, digits_per_limb);
+ } else {
+ v = get_bits(a->tab, a->len, pos);
+ limb_to_a2(buf, v, radix_bits, digits_per_limb);
+ }
+ buf_pos = first_buf_pos;
+ first_buf_pos = 0;
+ }
+ if (i < dot_pos) {
+ l = dot_pos;
+ } else {
+ if (i == dot_pos)
+ dbuf_putc(s, '.');
+ l = n_digits;
+ }
+ l = bf_min(digits_per_limb - buf_pos, l - i);
+ dbuf_put(s, (uint8_t *)(buf + buf_pos), l);
+ buf_pos += l;
+ i += l;
+ }
+ done:
+ if (a != a1)
+ bf_delete(a);
+}
+
+static void *bf_dbuf_realloc(void *opaque, void *ptr, size_t size)
+{
+ bf_context_t *s = opaque;
+ return bf_realloc(s, ptr, size);
+}
+
+/* return the length in bytes. A trailing '\0' is added */
+static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
+ limb_t prec, bf_flags_t flags, BOOL is_dec)
+{
+ 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);
+ if (a2->expn == BF_EXP_NAN) {
+ dbuf_putstr(s, "NaN");
+ } else {
+ if (a2->sign)
+ dbuf_putc(s, '-');
+ if (a2->expn == BF_EXP_INF) {
+ if (flags & BF_FTOA_JS_QUIRKS)
+ dbuf_putstr(s, "Infinity");
+ else
+ dbuf_putstr(s, "Inf");
+ } else {
+ int fmt, ret;
+ slimb_t n_digits, n, i, n_max, n1;
+ bf_t a1_s, *a1 = &a1_s;
+
+ if ((radix & (radix - 1)) != 0)
+ radix_bits = 0;
+ else
+ radix_bits = ceil_log2(radix);
+
+ fmt = flags & BF_FTOA_FORMAT_MASK;
+ bf_init(ctx, a1);
+ if (fmt == BF_FTOA_FORMAT_FRAC) {
+ if (is_dec || radix_bits != 0) {
+ if (bf_set(a1, a2))
+ goto fail1;
+#ifdef USE_BF_DEC
+ if (is_dec) {
+ if (bfdec_round((bfdec_t *)a1, prec, (flags & BF_RND_MASK) | BF_FLAG_RADPNT_PREC) & BF_ST_MEM_ERROR)
+ goto fail1;
+ n = a1->expn;
+ } else
+#endif
+ {
+ if (bf_round(a1, prec * radix_bits, (flags & BF_RND_MASK) | BF_FLAG_RADPNT_PREC) & BF_ST_MEM_ERROR)
+ goto fail1;
+ n = ceil_div(a1->expn, radix_bits);
+ }
+ if (flags & BF_FTOA_ADD_PREFIX) {
+ if (radix == 16)
+ dbuf_putstr(s, "0x");
+ else if (radix == 8)
+ dbuf_putstr(s, "0o");
+ else if (radix == 2)
+ dbuf_putstr(s, "0b");
+ }
+ if (a1->expn == BF_EXP_ZERO) {
+ dbuf_putstr(s, "0");
+ if (prec > 0) {
+ dbuf_putstr(s, ".");
+ for(i = 0; i < prec; i++) {
+ dbuf_putc(s, '0');
+ }
+ }
+ } else {
+ n_digits = prec + n;
+ if (n <= 0) {
+ /* 0.x */
+ dbuf_putstr(s, "0.");
+ for(i = 0; i < -n; i++) {
+ dbuf_putc(s, '0');
+ }
+ if (n_digits > 0) {
+ output_digits(s, a1, radix, n_digits, n_digits, is_dec);
+ }
+ } else {
+ output_digits(s, a1, radix, n_digits, n, is_dec);
+ }
+ }
+ } else {
+ size_t pos, start;
+ 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;
+
+ /* one more digit for the rounding */
+ n = 1 + bf_mul_log2_radix(bf_max(a->expn, 0), radix, TRUE, TRUE);
+ n_digits = n + prec;
+ n1 = n;
+ if (bf_convert_to_radix(a1, &n1, a, radix, n_digits,
+ flags & BF_RND_MASK, TRUE))
+ goto fail1;
+ start = s->size;
+ output_digits(s, a1, radix, n_digits, n, is_dec);
+ /* remove leading zeros because we allocated one more digit */
+ pos = start;
+ while ((pos + 1) < s->size && s->buf[pos] == '0' &&
+ s->buf[pos + 1] != '.')
+ pos++;
+ if (pos > start) {
+ memmove(s->buf + start, s->buf + pos, s->size - pos);
+ s->size -= (pos - start);
+ }
+ }
+ } else {
+#ifdef USE_BF_DEC
+ if (is_dec) {
+ if (bf_set(a1, a2))
+ goto fail1;
+ if (fmt == BF_FTOA_FORMAT_FIXED) {
+ n_digits = prec;
+ n_max = n_digits;
+ if (bfdec_round((bfdec_t *)a1, prec, (flags & BF_RND_MASK)) & BF_ST_MEM_ERROR)
+ goto fail1;
+ } else {
+ /* prec is ignored */
+ prec = n_digits = a1->len * LIMB_DIGITS;
+ /* remove the trailing zero digits */
+ while (n_digits > 1 &&
+ get_digit(a1->tab, a1->len, prec - n_digits) == 0) {
+ n_digits--;
+ }
+ n_max = n_digits + 4;
+ }
+ n = a1->expn;
+ } else
+#endif
+ if (radix_bits != 0) {
+ if (bf_set(a1, a2))
+ goto fail1;
+ if (fmt == BF_FTOA_FORMAT_FIXED) {
+ slimb_t prec_bits;
+ n_digits = prec;
+ n_max = n_digits;
+ /* align to the radix point */
+ prec_bits = prec * radix_bits -
+ smod(-a1->expn, radix_bits);
+ if (bf_round(a1, prec_bits,
+ (flags & BF_RND_MASK)) & BF_ST_MEM_ERROR)
+ goto fail1;
+ } else {
+ limb_t digit_mask;
+ slimb_t pos;
+ /* position of the digit before the most
+ significant digit in bits */
+ pos = a1->len * LIMB_BITS +
+ smod(-a1->expn, radix_bits);
+ n_digits = ceil_div(pos, radix_bits);
+ /* remove the trailing zero digits */
+ digit_mask = ((limb_t)1 << radix_bits) - 1;
+ while (n_digits > 1 &&
+ (get_bits(a1->tab, a1->len, pos - n_digits * radix_bits) & digit_mask) == 0) {
+ n_digits--;
+ }
+ n_max = n_digits + 4;
+ }
+ 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
+ notation. The rational is to have the same rule
+ as JS i.e. n_max = 21 for 64 bit float in base 10. */
+ 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 */
+ n_digits_max = n_digits;
+ n_digits_min = 1;
+ bf_init(ctx, b);
+ while (n_digits_min < n_digits_max) {
+ n_digits = (n_digits_min + n_digits_max) / 2;
+ if (bf_convert_to_radix(a1, &n, a, radix, n_digits,
+ flags & BF_RND_MASK, FALSE)) {
+ bf_delete(b);
+ goto fail1;
+ }
+ /* convert back to a number and compare */
+ ret = bf_mul_pow_radix(b, a1, radix, n - n_digits,
+ prec,
+ (flags & ~BF_RND_MASK) |
+ BF_RNDN);
+ if (ret & BF_ST_MEM_ERROR) {
+ bf_delete(b);
+ goto fail1;
+ }
+ if (bf_cmpu(b, a) == 0) {
+ n_digits_max = n_digits;
+ } else {
+ n_digits_min = n_digits + 1;
+ }
+ }
+ bf_delete(b);
+ n_digits = n_digits_max;
+ }
+ }
+ if (bf_convert_to_radix(a1, &n, a, radix, n_digits,
+ flags & BF_RND_MASK, FALSE)) {
+ fail1:
+ bf_delete(a1);
+ goto fail;
+ }
+ }
+ if (a1->expn == BF_EXP_ZERO &&
+ fmt != BF_FTOA_FORMAT_FIXED &&
+ !(flags & BF_FTOA_FORCE_EXP)) {
+ /* just output zero */
+ dbuf_putstr(s, "0");
+ } else {
+ if (flags & BF_FTOA_ADD_PREFIX) {
+ if (radix == 16)
+ dbuf_putstr(s, "0x");
+ else if (radix == 8)
+ dbuf_putstr(s, "0o");
+ else if (radix == 2)
+ dbuf_putstr(s, "0b");
+ }
+ if (a1->expn == BF_EXP_ZERO)
+ n = 1;
+ if ((flags & BF_FTOA_FORCE_EXP) ||
+ n <= -6 || n > n_max) {
+ const char *fmt;
+ /* exponential notation */
+ output_digits(s, a1, radix, n_digits, 1, is_dec);
+ if (radix_bits != 0 && radix <= 16) {
+ if (flags & BF_FTOA_JS_QUIRKS)
+ fmt = "p%+" PRId_LIMB;
+ else
+ fmt = "p%" PRId_LIMB;
+ dbuf_printf(s, fmt, (n - 1) * radix_bits);
+ } else {
+ if (flags & BF_FTOA_JS_QUIRKS)
+ fmt = "%c%+" PRId_LIMB;
+ else
+ fmt = "%c%" PRId_LIMB;
+ dbuf_printf(s, fmt,
+ radix <= 10 ? 'e' : '@', n - 1);
+ }
+ } else if (n <= 0) {
+ /* 0.x */
+ dbuf_putstr(s, "0.");
+ for(i = 0; i < -n; i++) {
+ dbuf_putc(s, '0');
+ }
+ output_digits(s, a1, radix, n_digits, n_digits, is_dec);
+ } else {
+ if (n_digits <= n) {
+ /* no dot */
+ output_digits(s, a1, radix, n_digits, n_digits, is_dec);
+ for(i = 0; i < (n - n_digits); i++)
+ dbuf_putc(s, '0');
+ } else {
+ output_digits(s, a1, radix, n_digits, n, is_dec);
+ }
+ }
+ }
+ }
+ bf_delete(a1);
+ }
+ }
+ dbuf_putc(s, '\0');
+ if (dbuf_error(s))
+ goto fail;
+ if (plen)
+ *plen = s->size - 1;
+ return (char *)s->buf;
+ fail:
+ bf_free(ctx, s->buf);
+ if (plen)
+ *plen = 0;
+ return NULL;
+}
+
+char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_ftoa_internal(plen, a, radix, prec, flags, FALSE);
+}
+
+/***************************************************************/
+/* transcendental functions */
+
+/* Note: the algorithm is from MPFR */
+static void bf_const_log2_rec(bf_t *T, bf_t *P, bf_t *Q, limb_t n1,
+ limb_t n2, BOOL need_P)
+{
+ bf_context_t *s = T->ctx;
+ if ((n2 - n1) == 1) {
+ if (n1 == 0) {
+ bf_set_ui(P, 3);
+ } else {
+ bf_set_ui(P, n1);
+ P->sign = 1;
+ }
+ bf_set_ui(Q, 2 * n1 + 1);
+ Q->expn += 2;
+ bf_set(T, P);
+ } else {
+ limb_t m;
+ 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);
+ bf_init(s, P1);
+ bf_init(s, Q1);
+ bf_const_log2_rec(T1, P1, Q1, m, n2, need_P);
+ bf_mul(T, T, Q1, BF_PREC_INF, BF_RNDZ);
+ bf_mul(T1, T1, P, BF_PREC_INF, BF_RNDZ);
+ bf_add(T, T, T1, BF_PREC_INF, BF_RNDZ);
+ if (need_P)
+ bf_mul(P, P, P1, BF_PREC_INF, BF_RNDZ);
+ bf_mul(Q, Q, Q1, BF_PREC_INF, BF_RNDZ);
+ bf_delete(T1);
+ bf_delete(P1);
+ bf_delete(Q1);
+ }
+}
+
+/* compute log(2) with faithful rounding at precision 'prec' */
+static void bf_const_log2_internal(bf_t *T, limb_t prec)
+{
+ limb_t w, N;
+ bf_t P_s, *P = &P_s;
+ bf_t Q_s, *Q = &Q_s;
+
+ w = prec + 15;
+ N = w / 3 + 1;
+ bf_init(T->ctx, P);
+ bf_init(T->ctx, Q);
+ bf_const_log2_rec(T, P, Q, 0, N, FALSE);
+ bf_div(T, T, Q, prec, BF_RNDN);
+ bf_delete(P);
+ bf_delete(Q);
+}
+
+/* PI constant */
+
+#define CHUD_A 13591409
+#define CHUD_B 545140134
+#define CHUD_C 640320
+#define CHUD_BITS_PER_TERM 47
+
+static void chud_bs(bf_t *P, bf_t *Q, bf_t *G, int64_t a, int64_t b, int need_g,
+ limb_t prec)
+{
+ bf_context_t *s = P->ctx;
+ int64_t c;
+
+ if (a == (b - 1)) {
+ bf_t T0, T1;
+
+ bf_init(s, &T0);
+ bf_init(s, &T1);
+ bf_set_ui(G, 2 * b - 1);
+ bf_mul_ui(G, G, 6 * b - 1, prec, BF_RNDN);
+ bf_mul_ui(G, G, 6 * b - 5, prec, BF_RNDN);
+ bf_set_ui(&T0, CHUD_B);
+ bf_mul_ui(&T0, &T0, b, prec, BF_RNDN);
+ bf_set_ui(&T1, CHUD_A);
+ bf_add(&T0, &T0, &T1, prec, BF_RNDN);
+ bf_mul(P, G, &T0, prec, BF_RNDN);
+ P->sign = b & 1;
+
+ bf_set_ui(Q, b);
+ bf_mul_ui(Q, Q, b, prec, BF_RNDN);
+ bf_mul_ui(Q, Q, b, prec, BF_RNDN);
+ bf_mul_ui(Q, Q, (uint64_t)CHUD_C * CHUD_C * CHUD_C / 24, prec, BF_RNDN);
+ bf_delete(&T0);
+ bf_delete(&T1);
+ } else {
+ bf_t P2, Q2, G2;
+
+ bf_init(s, &P2);
+ bf_init(s, &Q2);
+ bf_init(s, &G2);
+
+ 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 */
+ bf_mul(&P2, &P2, G, prec, BF_RNDN);
+ if (!need_g)
+ bf_set_ui(G, 0);
+ bf_mul(P, P, &Q2, prec, BF_RNDN);
+ bf_add(P, P, &P2, prec, BF_RNDN);
+ bf_delete(&P2);
+
+ bf_mul(Q, Q, &Q2, prec, BF_RNDN);
+ bf_delete(&Q2);
+ if (need_g)
+ bf_mul(G, G, &G2, prec, BF_RNDN);
+ bf_delete(&G2);
+ }
+}
+
+/* compute Pi with faithful rounding at precision 'prec' using the
+ Chudnovsky formula */
+static void bf_const_pi_internal(bf_t *Q, limb_t prec)
+{
+ bf_context_t *s = Q->ctx;
+ int64_t n, prec1;
+ bf_t P, G;
+
+ /* number of serie terms */
+ n = prec / CHUD_BITS_PER_TERM + 1;
+ /* XXX: precision analysis */
+ prec1 = prec + 32;
+
+ bf_init(s, &P);
+ 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);
+ bf_mul(Q, Q, &G, prec, BF_RNDN);
+ bf_delete(&P);
+ bf_delete(&G);
+}
+
+static int bf_const_get(bf_t *T, limb_t prec, bf_flags_t flags,
+ BFConstCache *c,
+ void (*func)(bf_t *res, limb_t prec), int sign)
+{
+ limb_t ziv_extra_bits, prec1;
+
+ ziv_extra_bits = 32;
+ for(;;) {
+ prec1 = prec + ziv_extra_bits;
+ if (c->prec < prec1) {
+ if (c->val.len == 0)
+ bf_init(T->ctx, &c->val);
+ func(&c->val, prec1);
+ c->prec = prec1;
+ } else {
+ prec1 = c->prec;
+ }
+ bf_set(T, &c->val);
+ T->sign = sign;
+ if (!bf_can_round(T, prec, flags & BF_RND_MASK, prec1)) {
+ /* and more precision and retry */
+ ziv_extra_bits = ziv_extra_bits + (ziv_extra_bits / 2);
+ } else {
+ break;
+ }
+ }
+ return bf_round(T, prec, flags);
+}
+
+static void bf_const_free(BFConstCache *c)
+{
+ bf_delete(&c->val);
+ memset(c, 0, sizeof(*c));
+}
+
+int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = T->ctx;
+ return bf_const_get(T, prec, flags, &s->log2_cache, bf_const_log2_internal, 0);
+}
+
+/* return rounded pi * (1 - 2 * sign) */
+static int bf_const_pi_signed(bf_t *T, int sign, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = T->ctx;
+ return bf_const_get(T, prec, flags, &s->pi_cache, bf_const_pi_internal,
+ sign);
+}
+
+int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags)
+{
+ return bf_const_pi_signed(T, 0, prec, flags);
+}
+
+void bf_clear_cache(bf_context_t *s)
+{
+#ifdef USE_FFT_MUL
+ fft_clear_cache(s);
+#endif
+ bf_const_free(&s->log2_cache);
+ bf_const_free(&s->pi_cache);
+}
+
+/* ZivFunc should compute the result 'r' with faithful rounding at
+ precision 'prec'. For efficiency purposes, the final bf_round()
+ does not need to be done in the function. */
+typedef int ZivFunc(bf_t *r, const bf_t *a, limb_t prec, void *opaque);
+
+static int bf_ziv_rounding(bf_t *r, const bf_t *a,
+ limb_t prec, bf_flags_t flags,
+ ZivFunc *f, void *opaque)
+{
+ 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 */
+ f(r, a, prec, opaque);
+ ret = 0;
+ } else {
+ ziv_extra_bits = 32;
+ for(;;) {
+ prec1 = prec + ziv_extra_bits;
+ ret = f(r, a, prec1, opaque);
+ if (ret & (BF_ST_OVERFLOW | BF_ST_UNDERFLOW | BF_ST_MEM_ERROR)) {
+ /* overflow or underflow should never happen because
+ it indicates the rounding cannot be done correctly,
+ but we do not catch all the cases */
+ return ret;
+ }
+ /* if the result is exact, we can stop */
+ if (!(ret & BF_ST_INEXACT)) {
+ ret = 0;
+ break;
+ }
+ if (bf_can_round(r, prec, rnd_mode, prec1)) {
+ ret = BF_ST_INEXACT;
+ break;
+ }
+ ziv_extra_bits = ziv_extra_bits * 2;
+ // printf("ziv_extra_bits=%" PRId64 "\n", (int64_t)ziv_extra_bits);
+ }
+ }
+ if (r->len == 0)
+ return ret;
+ else
+ return __bf_round(r, prec, flags, r->len, ret);
+}
+
+/* add (1 - 2*e_sign) * 2^e */
+static int bf_add_epsilon(bf_t *r, const bf_t *a, slimb_t e, int e_sign,
+ limb_t prec, int flags)
+{
+ bf_t T_s, *T = &T_s;
+ int ret;
+ /* small argument case: result = 1 + epsilon * sign(x) */
+ bf_init(a->ctx, T);
+ bf_set_ui(T, 1);
+ T->sign = e_sign;
+ T->expn += e;
+ ret = bf_add(r, r, T, prec, flags);
+ bf_delete(T);
+ return ret;
+}
+
+/* Compute the exponential using faithful rounding at precision 'prec'.
+ Note: the algorithm is from MPFR */
+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:
+ T = a - n*log(2) with 0 <= T < log(2) and n integer.
+ */
+ bf_init(s, T);
+ if (a->expn <= -1) {
+ /* 0 <= abs(a) <= 0.5 */
+ if (a->sign)
+ n = -1;
+ else
+ n = 0;
+ } else {
+ bf_const_log2(T, LIMB_BITS, BF_RNDZ);
+ bf_div(T, a, T, LIMB_BITS, BF_RNDD);
+ bf_get_limb(&n, T, 0);
+ }
+
+ K = bf_isqrt((prec + 1) / 2);
+ l = (prec - 1) / K + 1;
+ /* XXX: precision analysis ? */
+ prec1 = prec + (K + 2 * l + 18) + K + 8;
+ if (a->expn > 0)
+ prec1 += a->expn;
+ // printf("n=%ld K=%ld prec1=%ld\n", n, K, prec1);
+
+ bf_const_log2(T, prec1, BF_RNDF);
+ bf_mul_si(T, T, n, prec1, BF_RNDN);
+ bf_sub(T, a, T, prec1, BF_RNDN);
+
+ /* 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 * (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--) {
+ bf_set_ui(U, i);
+ bf_div(U, T, U, prec1, BF_RNDN);
+ bf_mul(r, r, U, prec1, BF_RNDN);
+ bf_add_si(r, r, 1, prec1, BF_RNDN);
+ }
+ 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);
+ }
+
+ /* undo the argument reduction */
+ bf_mul_2exp(r, n, BF_PREC_INF, BF_RNDZ | BF_FLAG_EXT_EXP);
+
+ return BF_ST_INEXACT;
+}
+
+/* crude overflow and underflow tests for exp(a). a_low <= a <= a_high */
+static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r,
+ const bf_t *a_low, const bf_t *a_high,
+ limb_t prec, bf_flags_t flags)
+{
+ 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;
+
+ e_max = (limb_t)1 << (bf_get_exp_bits(flags) - 1);
+ 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);
+ bf_mul_ui(T, log2, e_max, LIMB_BITS, BF_RNDU);
+ /* a_low > e_max * log(2) implies exp(a) > e_max */
+ if (bf_cmp_lt(T, a_low) > 0) {
+ /* overflow */
+ bf_delete(T);
+ bf_delete(log2);
+ return bf_set_overflow(r, 0, prec, flags);
+ }
+ /* a_high < (e_min - 2) * log(2) implies exp(a) < (e_min - 2) */
+ bf_const_log2(log2, LIMB_BITS, BF_RNDD);
+ 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);
+ if (rnd_mode == BF_RNDU) {
+ /* set the smallest value */
+ bf_set_ui(r, 1);
+ r->expn = e_min;
+ } else {
+ bf_set_zero(r, 0);
+ }
+ return BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ }
+ bf_delete(log2);
+ bf_delete(T);
+ return 0;
+}
+
+int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ int ret;
+ assert(r != a);
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else if (a->expn == BF_EXP_INF) {
+ if (a->sign)
+ bf_set_zero(r, 0);
+ else
+ bf_set_inf(r, 0);
+ } else {
+ bf_set_ui(r, 1);
+ }
+ return 0;
+ }
+
+ ret = check_exp_underflow_overflow(s, r, a, a, prec, flags);
+ if (ret)
+ return ret;
+ 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);
+}
+
+static int bf_log_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;
+ 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);
+ /* argument reduction 1 */
+ /* T=a*2^n with 2/3 <= T <= 4/3 */
+ {
+ bf_t U_s, *U = &U_s;
+ bf_set(T, a);
+ n = T->expn;
+ T->expn = 0;
+ /* U= ~ 2/3 */
+ bf_init(s, U);
+ bf_set_ui(U, 0xaaaaaaaa);
+ U->expn = 0;
+ if (bf_cmp_lt(T, U)) {
+ T->expn++;
+ n--;
+ }
+ bf_delete(U);
+ }
+ // printf("n=%ld\n", n);
+ // bf_print_str("T", T);
+
+ /* XXX: precision analysis */
+ /* number of iterations for argument reduction 2 */
+ K = bf_isqrt((prec + 1) / 2);
+ /* order of Taylor expansion */
+ 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);
+
+ /* argument reduction 2 */
+ for(i = 0; i < K; i++) {
+ /* T = T / (1 + sqrt(1 + T)) */
+ bf_add_si(U, T, 1, prec1, BF_RNDN);
+ bf_sqrt(V, U, prec1, BF_RNDF);
+ bf_add_si(U, V, 1, prec1, BF_RNDN);
+ bf_div(T, T, U, prec1, BF_RNDN);
+ }
+
+ {
+ bf_t Y_s, *Y = &Y_s;
+ bf_t Y2_s, *Y2 = &Y2_s;
+ bf_init(s, Y);
+ 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)
+ with Y=Y^2
+ = y*(1+Y/3+Y^2/5+...) = y*(1+Y*(1/3+Y*(1/5 + ...)))
+ */
+ bf_add_si(Y, T, 2, prec1, BF_RNDN);
+ bf_div(Y, T, Y, prec1, BF_RNDN);
+
+ bf_mul(Y2, Y, Y, prec1, BF_RNDN);
+ bf_set_ui(r, 0);
+ for(i = l; i >= 1; i--) {
+ bf_set_ui(U, 1);
+ bf_set_ui(V, 2 * i + 1);
+ bf_div(U, U, V, prec1, BF_RNDN);
+ bf_add(r, r, U, prec1, BF_RNDN);
+ bf_mul(r, r, Y2, prec1, BF_RNDN);
+ }
+ bf_add_si(r, r, 1, prec1, BF_RNDN);
+ bf_mul(r, r, Y, prec1, BF_RNDN);
+ bf_delete(Y);
+ bf_delete(Y2);
+ }
+ bf_delete(V);
+ bf_delete(U);
+
+ /* 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;
+}
+
+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) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ if (a->sign) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_inf(r, 0);
+ return 0;
+ }
+ } else {
+ bf_set_inf(r, 1);
+ return 0;
+ }
+ }
+ if (a->sign) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ }
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ if (bf_cmp_eq(a, T)) {
+ bf_set_zero(r, 0);
+ bf_delete(T);
+ return 0;
+ }
+ bf_delete(T);
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_log_internal, NULL);
+}
+
+/* x and y finite and x > 0 */
+static int bf_pow_generic(bf_t *r, const bf_t *x, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ const bf_t *y = opaque;
+ bf_t T_s, *T = &T_s;
+ limb_t prec1;
+
+ bf_init(s, T);
+ /* XXX: proof for the added precision */
+ prec1 = prec + 32;
+ bf_log(T, x, prec1, BF_RNDF | BF_FLAG_EXT_EXP);
+ bf_mul(T, T, y, prec1, BF_RNDF | BF_FLAG_EXT_EXP);
+ if (bf_is_nan(T))
+ bf_set_nan(r);
+ else
+ bf_exp_internal(r, T, prec1, NULL); /* no overflow/underlow test needed */
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+/* x and y finite, x > 0, y integer and y fits on one limb */
+static int bf_pow_int(bf_t *r, const bf_t *x, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ const bf_t *y = opaque;
+ bf_t T_s, *T = &T_s;
+ limb_t prec1;
+ int ret;
+ slimb_t y1;
+
+ bf_get_limb(&y1, y, 0);
+ if (y1 < 0)
+ y1 = -y1;
+ /* XXX: proof for the added precision */
+ prec1 = prec + ceil_log2(y1) * 2 + 8;
+ ret = bf_pow_ui(r, x, y1 < 0 ? -y1 : y1, prec1, BF_RNDN | BF_FLAG_EXT_EXP);
+ if (y->sign) {
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ ret |= bf_div(r, T, r, prec1, BF_RNDN | BF_FLAG_EXT_EXP);
+ bf_delete(T);
+ }
+ return ret;
+}
+
+/* x must be a finite non zero float. Return TRUE if there is a
+ floating point number r such as x=r^(2^n) and return this floating
+ point number 'r'. Otherwise return FALSE and r is undefined. */
+static BOOL check_exact_power2n(bf_t *r, const bf_t *x, slimb_t n)
+{
+ bf_context_t *s = r->ctx;
+ 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 */
+ if (n > (LIMB_BITS - 1)) {
+ if (e != 0)
+ return FALSE;
+ er = 0;
+ } else {
+ if ((e & (((limb_t)1 << n) - 1)) != 0)
+ return FALSE;
+ er = e >> n;
+ }
+ /* every perfect odd square = 1 modulo 8 */
+ v = get_bits(x->tab, x->len, x->len * LIMB_BITS - x->expn + e);
+ if ((v & 7) != 1)
+ return FALSE;
+
+ bf_init(s, T);
+ bf_set(T, x);
+ T->expn -= e;
+ for(i = 0; i < n; i++) {
+ if (i != 0)
+ bf_set(T, r);
+ if (bf_sqrtrem(r, NULL, T) != 0)
+ return FALSE;
+ }
+ r->expn += er;
+ return TRUE;
+}
+
+/* prec = BF_PREC_INF is accepted for x and y integers and y >= 0 */
+int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ bf_t ytmp_s;
+ 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 */
+ bf_set_ui(r, 1);
+ } else if (x->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else {
+ int cmp_x_abs_1;
+ bf_set_ui(r, 1);
+ cmp_x_abs_1 = bf_cmpu(x, r);
+ if (cmp_x_abs_1 == 0 && (flags & BF_POW_JS_QUIRKS) &&
+ (y->expn >= BF_EXP_INF)) {
+ bf_set_nan(r);
+ } else if (cmp_x_abs_1 == 0 &&
+ (!x->sign || y->expn != BF_EXP_NAN)) {
+ /* pow(1, y) = 1 even if y = NaN */
+ /* pow(-1, +/-inf) = 1 */
+ } else if (y->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else if (y->expn == BF_EXP_INF) {
+ if (y->sign == (cmp_x_abs_1 > 0)) {
+ bf_set_zero(r, 0);
+ } else {
+ bf_set_inf(r, 0);
+ }
+ } else {
+ y_emin = bf_get_exp_min(y);
+ y_is_odd = (y_emin == 0);
+ if (y->sign == (x->expn == BF_EXP_ZERO)) {
+ bf_set_inf(r, y_is_odd & x->sign);
+ if (y->sign) {
+ /* pow(0, y) with y < 0 */
+ return BF_ST_DIVIDE_ZERO;
+ }
+ } else {
+ bf_set_zero(r, y_is_odd & x->sign);
+ }
+ }
+ }
+ return 0;
+ }
+ bf_init(s, T);
+ bf_set(T, x);
+ y_emin = bf_get_exp_min(y);
+ y_is_int = (y_emin >= 0);
+ rnd_mode = flags & BF_RND_MASK;
+ if (x->sign) {
+ if (!y_is_int) {
+ bf_set_nan(r);
+ bf_delete(T);
+ return BF_ST_INVALID_OP;
+ }
+ y_is_odd = (y_emin == 0);
+ r_sign = y_is_odd;
+ /* change the directed rounding mode if the sign of the result
+ is changed */
+ if (r_sign && (rnd_mode == BF_RNDD || rnd_mode == BF_RNDU))
+ flags ^= 1;
+ bf_neg(T);
+ } else {
+ r_sign = 0;
+ }
+
+ bf_set_ui(r, 1);
+ if (bf_cmp_eq(T, r)) {
+ /* abs(x) = 1: nothing more to do */
+ ret = 0;
+ } else {
+ /* check the overflow/underflow cases */
+ {
+ 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 */
+ /* XXX: compute bf_log() once */
+ /* XXX: add a fast test before this slow test */
+ bf_log(al, T, precl, BF_RNDD);
+ bf_log(ah, T, precl, BF_RNDU);
+ bf_mul(al, al, y, precl, BF_RNDD ^ y->sign);
+ bf_mul(ah, ah, y, precl, BF_RNDU ^ y->sign);
+ ret = check_exp_underflow_overflow(s, r, al, ah, prec, flags);
+ bf_delete(al);
+ bf_delete(ah);
+ if (ret)
+ goto done;
+ }
+
+ if (y_is_int) {
+ slimb_t T_bits, e;
+ int_pow:
+ T_bits = T->expn - bf_get_exp_min(T);
+ if (T_bits == 1) {
+ /* pow(2^b, y) = 2^(b*y) */
+ bf_mul_si(T, y, T->expn - 1, LIMB_BITS, BF_RNDZ);
+ bf_get_limb(&e, T, 0);
+ bf_set_ui(r, 1);
+ ret = bf_mul_2exp(r, e, prec, flags);
+ } else if (prec == BF_PREC_INF) {
+ slimb_t y1;
+ /* specific case for infinite precision (integer case) */
+ bf_get_limb(&y1, y, 0);
+ assert(!y->sign);
+ /* x must be an integer, so abs(x) >= 2 */
+ if (y1 >= ((slimb_t)1 << BF_EXP_BITS_MAX)) {
+ bf_delete(T);
+ return bf_set_overflow(r, 0, BF_PREC_INF, flags);
+ }
+ ret = bf_pow_ui(r, T, y1, BF_PREC_INF, BF_RNDZ);
+ } else {
+ if (y->expn <= 31) {
+ /* small enough power: use exponentiation in all cases */
+ } else if (y->sign) {
+ /* cannot be exact */
+ goto general_case;
+ } else {
+ if (rnd_mode == BF_RNDF)
+ goto general_case; /* no need to track exact results */
+ /* see if the result has a chance to be exact:
+ if x=a*2^b (a odd), x^y=a^y*2^(b*y)
+ x^y needs a precision of at least floor_log2(a)*y bits
+ */
+ bf_mul_si(r, y, T_bits - 1, LIMB_BITS, BF_RNDZ);
+ bf_get_limb(&e, r, 0);
+ if (prec < e)
+ goto general_case;
+ }
+ ret = bf_ziv_rounding(r, T, prec, flags, bf_pow_int, (void *)y);
+ }
+ } else {
+ if (rnd_mode != BF_RNDF) {
+ bf_t *y1;
+ if (y_emin < 0 && check_exact_power2n(r, T, -y_emin)) {
+ /* the problem is reduced to a power to an integer */
+#if 0
+ printf("\nn=%" PRId64 "\n", -(int64_t)y_emin);
+ bf_print_str("T", T);
+ bf_print_str("r", r);
+#endif
+ bf_set(T, r);
+ y1 = &ytmp_s;
+ y1->tab = y->tab;
+ y1->len = y->len;
+ y1->sign = y->sign;
+ y1->expn = y->expn - y_emin;
+ y = y1;
+ goto int_pow;
+ }
+ }
+ general_case:
+ ret = bf_ziv_rounding(r, T, prec, flags, bf_pow_generic, (void *)y);
+ }
+ }
+ done:
+ bf_delete(T);
+ r->sign = r_sign;
+ return ret;
+}
+
+/* compute sqrt(-2*x-x^2) to get |sin(x)| from cos(x) - 1. */
+static void bf_sqrt_sin(bf_t *r, const bf_t *x, limb_t prec1)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ bf_init(s, T);
+ bf_set(T, x);
+ bf_mul(r, T, T, prec1, BF_RNDN);
+ bf_mul_2exp(T, 1, BF_PREC_INF, BF_RNDZ);
+ bf_add(T, T, r, prec1, BF_RNDN);
+ bf_neg(T);
+ bf_sqrt(r, T, prec1, BF_RNDF);
+ bf_delete(T);
+}
+
+static int bf_sincos(bf_t *s, bf_t *c, const bf_t *a, limb_t prec)
+{
+ bf_context_t *s1 = a->ctx;
+ bf_t T_s, *T = &T_s;
+ bf_t U_s, *U = &U_s;
+ 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 */
+ bf_set(T, a);
+ mod = 0;
+ } else {
+ slimb_t cancel;
+ cancel = 0;
+ for(;;) {
+ prec2 = prec1 + a->expn + cancel;
+ bf_const_pi(U, prec2, BF_RNDF);
+ bf_mul_2exp(U, -1, BF_PREC_INF, BF_RNDZ);
+ bf_remquo(&mod, T, a, U, prec2, BF_RNDN, BF_RNDN);
+ // printf("T.expn=%ld prec2=%ld\n", T->expn, prec2);
+ if (mod == 0 || (T->expn != BF_EXP_ZERO &&
+ (T->expn + prec2) >= (prec1 - 1)))
+ break;
+ /* increase the number of bits until the precision is good enough */
+ cancel = bf_max(-T->expn, (cancel + 1) * 3 / 2);
+ }
+ 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! + ...
+ */
+ bf_set_ui(r, 1);
+ for(i = l ; i >= 1; i--) {
+ bf_set_ui(U, 2 * i - 1);
+ bf_mul_ui(U, U, 2 * i, BF_PREC_INF, BF_RNDZ);
+ bf_div(U, T, U, prec1, BF_RNDN);
+ bf_mul(r, r, U, prec1, BF_RNDN);
+ bf_neg(r);
+ if (i != 1)
+ bf_add_si(r, r, 1, prec1, BF_RNDN);
+ }
+ bf_delete(U);
+
+ /* undo argument reduction:
+ cosm1(2*x)= 2*(2*cosm1(x)+cosm1(x)^2)
+ */
+ for(i = 0; i < K; i++) {
+ bf_mul(T, r, r, prec1, BF_RNDN);
+ bf_mul_2exp(r, 1, BF_PREC_INF, BF_RNDZ);
+ bf_add(r, r, T, prec1, BF_RNDN);
+ bf_mul_2exp(r, 1, BF_PREC_INF, BF_RNDZ);
+ }
+ bf_delete(T);
+
+ if (c) {
+ if ((mod & 1) == 0) {
+ bf_add_si(c, r, 1, prec1, BF_RNDN);
+ } else {
+ bf_sqrt_sin(c, r, prec1);
+ c->sign = is_neg ^ 1;
+ }
+ c->sign ^= mod >> 1;
+ }
+ if (s) {
+ if ((mod & 1) == 0) {
+ bf_sqrt_sin(s, r, prec1);
+ s->sign = is_neg;
+ } else {
+ bf_add_si(s, r, 1, prec1, BF_RNDN);
+ }
+ s->sign ^= mod >> 1;
+ }
+ bf_delete(r);
+ return BF_ST_INEXACT;
+}
+
+static int bf_cos_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ return bf_sincos(NULL, r, a, prec);
+}
+
+int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_ui(r, 1);
+ return 0;
+ }
+ }
+
+ /* small argument case: result = 1+r(x) with r(x) = -x^2/2 +
+ O(X^4). We assume r(x) < 2^(2*EXP(x) - 1). */
+ if (a->expn < 0) {
+ slimb_t e;
+ e = 2 * a->expn - 1;
+ if (e < -(prec + 2)) {
+ bf_set_ui(r, 1);
+ return bf_add_epsilon(r, r, e, 1, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_cos_internal, NULL);
+}
+
+static int bf_sin_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ return bf_sincos(r, NULL, a, prec);
+}
+
+int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_zero(r, a->sign);
+ return 0;
+ }
+ }
+
+ /* 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) {
+ slimb_t e;
+ e = sat_add(2 * a->expn, a->expn - 2);
+ if (e < a->expn - bf_max(prec + 2, a->len * LIMB_BITS + 2)) {
+ bf_set(r, a);
+ return bf_add_epsilon(r, r, e, 1 - a->sign, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_sin_internal, NULL);
+}
+
+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);
+ bf_sincos(r, T, a, prec1);
+ bf_div(r, r, T, prec1, BF_RNDF);
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ assert(r != a);
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_zero(r, a->sign);
+ return 0;
+ }
+ }
+
+ /* small argument case: result = x+r(x) with r(x) = x^3/3 +
+ O(X^5). We assume r(x) < 2^(3*EXP(x) - 1). */
+ if (a->expn < 0) {
+ slimb_t e;
+ e = sat_add(2 * a->expn, a->expn - 1);
+ if (e < a->expn - bf_max(prec + 2, a->len * LIMB_BITS + 2)) {
+ bf_set(r, a);
+ return bf_add_epsilon(r, r, e, a->sign, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_tan_internal, NULL);
+}
+
+/* if add_pi2 is true, add pi/2 to the result (used for acos(x) to
+ avoid cancellation) */
+static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec,
+ void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ BOOL add_pi2 = (BOOL)(intptr_t)opaque;
+ bf_t T_s, *T = &T_s;
+ bf_t U_s, *U = &U_s;
+ bf_t V_s, *V = &V_s;
+ 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) {
+ bf_set_ui(T, 1);
+ bf_div(T, T, a, prec1, BF_RNDN);
+ } else {
+ bf_set(T, a);
+ }
+
+ /* abs(T) <= 1 */
+
+ /* argument reduction */
+
+ bf_init(s, U);
+ bf_init(s, V);
+ bf_init(s, X2);
+ for(i = 0; i < K; i++) {
+ /* T = T / (1 + sqrt(1 + T^2)) */
+ bf_mul(U, T, T, prec1, BF_RNDN);
+ bf_add_si(U, U, 1, prec1, BF_RNDN);
+ bf_sqrt(V, U, prec1, BF_RNDN);
+ bf_add_si(V, V, 1, prec1, BF_RNDN);
+ bf_div(T, T, V, prec1, BF_RNDN);
+ }
+
+ /* 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);
+ for(i = l; i >= 1; i--) {
+ bf_set_si(U, 1);
+ bf_set_ui(V, 2 * i + 1);
+ bf_div(U, U, V, prec1, BF_RNDN);
+ bf_neg(r);
+ bf_add(r, r, U, prec1, BF_RNDN);
+ bf_mul(r, r, X2, prec1, BF_RNDN);
+ }
+ bf_neg(r);
+ bf_add_si(r, r, 1, prec1, BF_RNDN);
+ bf_mul(r, r, T, prec1, BF_RNDN);
+
+ /* undo the argument reduction */
+ bf_mul_2exp(r, K, BF_PREC_INF, BF_RNDZ);
+
+ bf_delete(U);
+ bf_delete(V);
+ bf_delete(X2);
+
+ i = add_pi2;
+ if (cmp_1 > 0) {
+ /* undo the inversion : r = sign(a)*PI/2 - r */
+ bf_neg(r);
+ i += 1 - 2 * a->sign;
+ }
+ /* add i*(pi/2) with -1 <= i <= 2 */
+ if (i != 0) {
+ bf_const_pi(T, prec1, BF_RNDF);
+ if (i != 2)
+ bf_mul_2exp(T, -1, BF_PREC_INF, BF_RNDZ);
+ T->sign = (i < 0);
+ bf_add(r, T, r, prec1, BF_RNDN);
+ }
+
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+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);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ /* -PI/2 or PI/2 */
+ bf_const_pi_signed(r, a->sign, prec, flags);
+ bf_mul_2exp(r, -1, BF_PREC_INF, BF_RNDZ);
+ return BF_ST_INEXACT;
+ } else {
+ bf_set_zero(r, a->sign);
+ return 0;
+ }
+ }
+
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ res = bf_cmpu(a, T);
+ bf_delete(T);
+ if (res == 0) {
+ /* short cut: abs(a) == 1 -> +/-pi/4 */
+ bf_const_pi_signed(r, a->sign, prec, flags);
+ bf_mul_2exp(r, -2, BF_PREC_INF, BF_RNDZ);
+ return BF_ST_INEXACT;
+ }
+
+ /* small argument case: result = x+r(x) with r(x) = -x^3/3 +
+ O(X^5). We assume r(x) < 2^(3*EXP(x) - 1). */
+ if (a->expn < 0) {
+ slimb_t e;
+ e = sat_add(2 * a->expn, a->expn - 1);
+ if (e < a->expn - bf_max(prec + 2, a->len * LIMB_BITS + 2)) {
+ bf_set(r, a);
+ 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);
+}
+
+static int bf_atan2_internal(bf_t *r, const bf_t *y, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ const bf_t *x = 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;
+ }
+
+ /* compute atan(y/x) assumming inf/inf = 1 and 0/0 = 0 */
+ bf_init(s, T);
+ prec1 = prec + 32;
+ if (y->expn == BF_EXP_INF && x->expn == BF_EXP_INF) {
+ bf_set_ui(T, 1);
+ T->sign = y->sign ^ x->sign;
+ } else if (y->expn == BF_EXP_ZERO && x->expn == BF_EXP_ZERO) {
+ bf_set_zero(T, y->sign ^ x->sign);
+ } else {
+ bf_div(T, y, x, prec1, BF_RNDF);
+ }
+ ret = bf_atan(r, T, prec1, BF_RNDF);
+
+ if (x->sign) {
+ /* if x < 0 (it includes -0), return sign(y)*pi + atan(y/x) */
+ bf_const_pi(T, prec1, BF_RNDF);
+ T->sign = y->sign;
+ bf_add(r, r, T, prec1, BF_RNDN);
+ ret |= BF_ST_INEXACT;
+ }
+
+ bf_delete(T);
+ return ret;
+}
+
+int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
+ limb_t prec, bf_flags_t flags)
+{
+ return bf_ziv_rounding(r, y, prec, flags, bf_atan2_internal, (void *)x);
+}
+
+static int bf_asin_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ 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))
+ acos(x) = pi/2 - asin(x) */
+ prec1 = prec + 8;
+ /* increase the precision in x^2 to compensate the cancellation in
+ (1-x^2) if x is close to 1 */
+ /* XXX: use less precision when possible */
+ if (a->expn >= 0)
+ prec2 = BF_PREC_INF;
+ else
+ prec2 = prec1;
+ bf_init(s, T);
+ bf_mul(T, a, a, prec2, BF_RNDN);
+ bf_neg(T);
+ bf_add_si(T, T, 1, prec2, BF_RNDN);
+
+ bf_sqrt(r, T, prec1, BF_RNDN);
+ bf_div(T, a, r, prec1, BF_RNDN);
+ if (is_acos)
+ bf_neg(T);
+ bf_atan_internal(r, T, prec1, (void *)(intptr_t)is_acos);
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+int bf_asin(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);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_zero(r, a->sign);
+ return 0;
+ }
+ }
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ res = bf_cmpu(a, T);
+ bf_delete(T);
+ if (res > 0) {
+ 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) {
+ slimb_t e;
+ e = sat_add(2 * a->expn, a->expn - 2);
+ if (e < a->expn - bf_max(prec + 2, a->len * LIMB_BITS + 2)) {
+ bf_set(r, a);
+ return bf_add_epsilon(r, r, e, a->sign, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)FALSE);
+}
+
+int bf_acos(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);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_const_pi(r, prec, flags);
+ bf_mul_2exp(r, -1, BF_PREC_INF, BF_RNDZ);
+ return BF_ST_INEXACT;
+ }
+ }
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ res = bf_cmpu(a, T);
+ bf_delete(T);
+ if (res > 0) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else if (res == 0 && a->sign == 0) {
+ bf_set_zero(r, 0);
+ return 0;
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)TRUE);
+}
+
+/***************************************************************/
+/* decimal floating point numbers */
+
+#ifdef USE_BF_DEC
+
+#define adddq(r1, r0, a1, a0) \
+ do { \
+ limb_t __t = r0; \
+ r0 += (a0); \
+ r1 += (a1) + (r0 < __t); \
+ } while (0)
+
+#define subdq(r1, r0, a1, a0) \
+ do { \
+ limb_t __t = r0; \
+ r0 -= (a0); \
+ r1 -= (a1) + (r0 > __t); \
+ } while (0)
+
+#if LIMB_BITS == 64
+
+/* Note: we assume __int128 is available */
+#define muldq(r1, r0, a, b) \
+ do { \
+ unsigned __int128 __t; \
+ __t = (unsigned __int128)(a) * (unsigned __int128)(b); \
+ r0 = __t; \
+ r1 = __t >> 64; \
+ } while (0)
+
+#define divdq(q, r, a1, a0, b) \
+ do { \
+ unsigned __int128 __t; \
+ limb_t __b = (b); \
+ __t = ((unsigned __int128)(a1) << 64) | (a0); \
+ q = __t / __b; \
+ r = __t % __b; \
+ } while (0)
+
+#else
+
+#define muldq(r1, r0, a, b) \
+ do { \
+ uint64_t __t; \
+ __t = (uint64_t)(a) * (uint64_t)(b); \
+ r0 = __t; \
+ r1 = __t >> 32; \
+ } while (0)
+
+#define divdq(q, r, a1, a0, b) \
+ do { \
+ uint64_t __t; \
+ limb_t __b = (b); \
+ __t = ((uint64_t)(a1) << 32) | (a0); \
+ q = __t / __b; \
+ r = __t % __b; \
+ } while (0)
+
+#endif /* LIMB_BITS != 64 */
+
+#if LIMB_DIGITS == 19
+
+/* WARNING: hardcoded for b = 1e19. It is assumed that:
+ 0 <= a1 < 2^63 */
+#define divdq_base(q, r, a1, a0)\
+do {\
+ uint64_t __a0, __a1, __t0, __t1, __b = BF_DEC_BASE; \
+ __a0 = a0;\
+ __a1 = a1;\
+ __t0 = __a1;\
+ __t0 = shld(__t0, __a0, 1);\
+ muldq(q, __t1, __t0, UINT64_C(17014118346046923173)); \
+ muldq(__t1, __t0, q, __b);\
+ subdq(__a1, __a0, __t1, __t0);\
+ subdq(__a1, __a0, 1, __b * 2); \
+ __t0 = (slimb_t)__a1 >> 1; \
+ q += 2 + __t0;\
+ adddq(__a1, __a0, 0, __b & __t0);\
+ q += __a1; \
+ __a0 += __b & __a1; \
+ r = __a0;\
+} while(0)
+
+#elif LIMB_DIGITS == 9
+
+/* WARNING: hardcoded for b = 1e9. It is assumed that:
+ 0 <= a1 < 2^29 */
+#define divdq_base(q, r, a1, a0)\
+do {\
+ uint32_t __t0, __t1, __b = BF_DEC_BASE; \
+ __t0 = a1;\
+ __t1 = a0;\
+ __t0 = (__t0 << 3) | (__t1 >> (32 - 3)); \
+ muldq(q, __t1, __t0, 2305843009U);\
+ r = a0 - q * __b;\
+ __t1 = (r >= __b);\
+ q += __t1;\
+ if (__t1)\
+ r -= __b;\
+} while(0)
+
+#endif
+
+/* fast integer division by a fixed constant */
+
+typedef struct FastDivData {
+ limb_t m1; /* multiplier */
+ int8_t shift1;
+ int8_t shift2;
+} FastDivData;
+
+/* From "Division by Invariant Integers using Multiplication" by
+ Torborn Granlund and Peter L. Montgomery */
+/* d must be != 0 */
+static inline __maybe_unused void fast_udiv_init(FastDivData *s, limb_t d)
+{
+ int l;
+ limb_t q, r, m1;
+ if (d == 1)
+ l = 0;
+ else
+ l = 64 - clz64(d - 1);
+ divdq(q, r, ((limb_t)1 << l) - d, 0, d);
+ (void)r;
+ m1 = q + 1;
+ // printf("d=%lu l=%d m1=0x%016lx\n", d, l, m1);
+ s->m1 = m1;
+ s->shift1 = l;
+ if (s->shift1 > 1)
+ s->shift1 = 1;
+ s->shift2 = l - 1;
+ if (s->shift2 < 0)
+ s->shift2 = 0;
+}
+
+static inline limb_t fast_udiv(limb_t a, const FastDivData *s)
+{
+ limb_t t0, t1;
+ muldq(t1, t0, s->m1, a);
+ t0 = (a - t1) >> s->shift1;
+ return (t1 + t0) >> s->shift2;
+}
+
+#endif // USE_BF_DEC
+/* contains 10^i */
+const limb_t mp_pow_dec[LIMB_DIGITS + 1] = {
+ 1U,
+ 10U,
+ 100U,
+ 1000U,
+ 10000U,
+ 100000U,
+ 1000000U,
+ 10000000U,
+ 100000000U,
+ 1000000000U,
+#if LIMB_BITS == 64
+ 10000000000U,
+ 100000000000U,
+ 1000000000000U,
+ 10000000000000U,
+ 100000000000000U,
+ 1000000000000000U,
+ 10000000000000000U,
+ 100000000000000000U,
+ 1000000000000000000U,
+ 10000000000000000000U,
+#endif
+};
+#ifdef USE_BF_DEC
+
+/* precomputed from fast_udiv_init(10^i) */
+static const FastDivData mp_pow_div[LIMB_DIGITS + 1] = {
+#if LIMB_BITS == 32
+ { 0x00000001, 0, 0 },
+ { 0x9999999a, 1, 3 },
+ { 0x47ae147b, 1, 6 },
+ { 0x0624dd30, 1, 9 },
+ { 0xa36e2eb2, 1, 13 },
+ { 0x4f8b588f, 1, 16 },
+ { 0x0c6f7a0c, 1, 19 },
+ { 0xad7f29ac, 1, 23 },
+ { 0x5798ee24, 1, 26 },
+ { 0x12e0be83, 1, 29 },
+#else
+ { 0x0000000000000001, 0, 0 },
+ { 0x999999999999999a, 1, 3 },
+ { 0x47ae147ae147ae15, 1, 6 },
+ { 0x0624dd2f1a9fbe77, 1, 9 },
+ { 0xa36e2eb1c432ca58, 1, 13 },
+ { 0x4f8b588e368f0847, 1, 16 },
+ { 0x0c6f7a0b5ed8d36c, 1, 19 },
+ { 0xad7f29abcaf48579, 1, 23 },
+ { 0x5798ee2308c39dfa, 1, 26 },
+ { 0x12e0be826d694b2f, 1, 29 },
+ { 0xb7cdfd9d7bdbab7e, 1, 33 },
+ { 0x5fd7fe17964955fe, 1, 36 },
+ { 0x19799812dea11198, 1, 39 },
+ { 0xc25c268497681c27, 1, 43 },
+ { 0x6849b86a12b9b01f, 1, 46 },
+ { 0x203af9ee756159b3, 1, 49 },
+ { 0xcd2b297d889bc2b7, 1, 53 },
+ { 0x70ef54646d496893, 1, 56 },
+ { 0x2725dd1d243aba0f, 1, 59 },
+ { 0xd83c94fb6d2ac34d, 1, 63 },
+#endif
+};
+
+/* divide by 10^shift with 0 <= shift <= LIMB_DIGITS */
+static inline limb_t fast_shr_dec(limb_t a, int shift)
+{
+ return fast_udiv(a, &mp_pow_div[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,
+ mp_size_t n, limb_t carry)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t k, a, v;
+
+ k=carry;
+ for(i=0;i<n;i++) {
+ /* XXX: reuse the trick in add_mod */
+ v = op1[i];
+ a = v + op2[i] + k - base;
+ k = a <= v;
+ if (!k)
+ a += base;
+ res[i]=a;
+ }
+ return k;
+}
+
+limb_t mp_add_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, a, v;
+
+ k=b;
+ for(i=0;i<n;i++) {
+ v = tab[i];
+ a = v + k - base;
+ k = a <= v;
+ if (!k)
+ a += base;
+ tab[i] = a;
+ if (k == 0)
+ break;
+ }
+ return k;
+}
+
+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;
+ mp_size_t i;
+ limb_t k, v, a;
+
+ k=carry;
+ for(i=0;i<n;i++) {
+ v = op1[i];
+ a = v - op2[i] - k;
+ k = a > v;
+ if (k)
+ a += base;
+ res[i] = a;
+ }
+ return k;
+}
+
+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<n;i++) {
+ v = tab[i];
+ a = v - k;
+ k = a > v;
+ if (k)
+ a += base;
+ tab[i]=a;
+ if (k == 0)
+ break;
+ }
+ return k;
+}
+
+/* taba[] = taba[] * b + l. 0 <= b, l <= base - 1. Return the high carry */
+limb_t mp_mul1_dec(limb_t *tabr, const limb_t *taba, mp_size_t n,
+ limb_t b, limb_t l)
+{
+ mp_size_t i;
+ limb_t t0, t1, r;
+
+ for(i = 0; i < n; i++) {
+ muldq(t1, t0, taba[i], b);
+ adddq(t1, t0, 0, l);
+ divdq_base(l, r, t1, t0);
+ tabr[i] = r;
+ }
+ return l;
+}
+
+/* tabr[] += taba[] * b. 0 <= b <= base - 1. Return the value to add
+ to the high word */
+limb_t mp_add_mul1_dec(limb_t *tabr, const limb_t *taba, mp_size_t n,
+ limb_t b)
+{
+ mp_size_t i;
+ limb_t l, t0, t1, r;
+
+ l = 0;
+ for(i = 0; i < n; i++) {
+ muldq(t1, t0, taba[i], b);
+ adddq(t1, t0, 0, l);
+ adddq(t1, t0, 0, tabr[i]);
+ divdq_base(l, r, t1, t0);
+ tabr[i] = r;
+ }
+ return l;
+}
+
+/* tabr[] -= taba[] * b. 0 <= b <= base - 1. Return the value to
+ substract to the high word. */
+limb_t mp_sub_mul1_dec(limb_t *tabr, const limb_t *taba, mp_size_t n,
+ limb_t b)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t l, t0, t1, r, a, v, c;
+
+ /* XXX: optimize */
+ l = 0;
+ for(i = 0; i < n; i++) {
+ muldq(t1, t0, taba[i], b);
+ adddq(t1, t0, 0, l);
+ divdq_base(l, r, t1, t0);
+ v = tabr[i];
+ a = v - r;
+ c = a > v;
+ if (c)
+ a += base;
+ /* never bigger than base because r = 0 when l = base - 1 */
+ l += c;
+ tabr[i] = a;
+ }
+ return l;
+}
+
+/* size of the result : op1_size + op2_size. */
+void mp_mul_basecase_dec(limb_t *result,
+ const limb_t *op1, mp_size_t op1_size,
+ const limb_t *op2, mp_size_t op2_size)
+{
+ mp_size_t i;
+ limb_t r;
+
+ result[op1_size] = mp_mul1_dec(result, op1, op1_size, op2[0], 0);
+
+ for(i=1;i<op2_size;i++) {
+ r = mp_add_mul1_dec(result + i, op1, op1_size, op2[i]);
+ result[i + op1_size] = r;
+ }
+}
+
+/* taba[] = (taba[] + r*base^na) / b. 0 <= b < base. 0 <= r <
+ b. Return the remainder. */
+limb_t mp_div1_dec(limb_t *tabr, const limb_t *taba, mp_size_t na,
+ limb_t b, limb_t r)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t t0, t1, q;
+ int shift;
+
+#if (BF_DEC_BASE % 2) == 0
+ if (b == 2) {
+ limb_t base_div2;
+ /* Note: only works if base is even */
+ base_div2 = base >> 1;
+ if (r)
+ r = base_div2;
+ for(i = na - 1; i >= 0; i--) {
+ t0 = taba[i];
+ tabr[i] = (t0 >> 1) + r;
+ r = 0;
+ if (t0 & 1)
+ r = base_div2;
+ }
+ if (r)
+ r = 1;
+ } else
+#endif
+ if (na >= UDIV1NORM_THRESHOLD) {
+ shift = clz(b);
+ if (shift == 0) {
+ /* normalized case: b >= 2^(LIMB_BITS-1) */
+ limb_t b_inv;
+ b_inv = udiv1norm_init(b);
+ for(i = na - 1; i >= 0; i--) {
+ muldq(t1, t0, r, base);
+ adddq(t1, t0, 0, taba[i]);
+ q = udiv1norm(&r, t1, t0, b, b_inv);
+ tabr[i] = q;
+ }
+ } else {
+ limb_t b_inv;
+ b <<= shift;
+ b_inv = udiv1norm_init(b);
+ for(i = na - 1; i >= 0; i--) {
+ muldq(t1, t0, r, base);
+ adddq(t1, t0, 0, taba[i]);
+ t1 = (t1 << shift) | (t0 >> (LIMB_BITS - shift));
+ t0 <<= shift;
+ q = udiv1norm(&r, t1, t0, b, b_inv);
+ r >>= shift;
+ tabr[i] = q;
+ }
+ }
+ } else {
+ for(i = na - 1; i >= 0; i--) {
+ muldq(t1, t0, r, base);
+ adddq(t1, t0, 0, taba[i]);
+ divdq(q, r, t1, t0, b);
+ tabr[i] = q;
+ }
+ }
+ return r;
+}
+
+static __maybe_unused void mp_print_str_dec(const char *str,
+ const limb_t *tab, slimb_t n)
+{
+ slimb_t i;
+ printf("%s=", str);
+ for(i = n - 1; i >= 0; i--) {
+ if (i != n - 1)
+ printf("_");
+ printf("%0*" PRIu_LIMB, LIMB_DIGITS, tab[i]);
+ }
+ printf("\n");
+}
+
+static __maybe_unused void mp_print_str_h_dec(const char *str,
+ const limb_t *tab, slimb_t n,
+ limb_t high)
+{
+ slimb_t i;
+ printf("%s=", str);
+ printf("%0*" PRIu_LIMB, LIMB_DIGITS, high);
+ for(i = n - 1; i >= 0; i--) {
+ printf("_");
+ printf("%0*" PRIu_LIMB, LIMB_DIGITS, tab[i]);
+ }
+ printf("\n");
+}
+
+//#define DEBUG_DIV_SLOW
+
+#define DIV_STATIC_ALLOC_LEN 16
+
+/* 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]
+ >= B / 2.
+
+ The remainder is is returned in taba and contains nb libms. tabq
+ contains na - nb + 1 limbs. No overlap is permitted.
+
+ Running time of the standard method: (na - nb + 1) * nb
+ Return 0 if OK, -1 if memory alloc error
+*/
+/* XXX: optimize */
+static int mp_div_dec(bf_context_t *s, limb_t *tabq,
+ 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);
+#endif
+
+ /* normalize tabb */
+ r = tabb1[nb - 1];
+ assert(r != 0);
+ i = na - nb;
+ if (r >= BF_DEC_BASE / 2) {
+ mult = 1;
+ tabb = (limb_t *)tabb1;
+ q = 1;
+ for(j = nb - 1; j >= 0; j--) {
+ if (taba[i + j] != tabb[j]) {
+ if (taba[i + j] < tabb[j])
+ q = 0;
+ break;
+ }
+ }
+ tabq[i] = q;
+ if (q) {
+ mp_sub_dec(taba + i, taba + i, tabb, nb, 0);
+ }
+ i--;
+ } else {
+ mult = base / (r + 1);
+ if (likely(nb <= DIV_STATIC_ALLOC_LEN)) {
+ tabb = static_tabb;
+ } else {
+ tabb = bf_malloc(s, sizeof(limb_t) * nb);
+ if (!tabb)
+ return -1;
+ }
+ mp_mul1_dec(tabb, tabb1, nb, mult, 0);
+ taba[na] = mp_mul1_dec(taba, taba, na, mult, 0);
+ }
+
+#ifdef DEBUG_DIV_SLOW
+ printf("mult=" FMT_LIMB "\n", mult);
+ mp_print_str_dec("a_norm", taba, na + 1);
+ mp_print_str_dec("b_norm", tabb, nb);
+#endif
+
+ for(; i >= 0; i--) {
+ if (unlikely(taba[i + nb] >= tabb[nb - 1])) {
+ /* XXX: check if it is really possible */
+ q = base - 1;
+ } else {
+ muldq(t1, t0, taba[i + nb], base);
+ adddq(t1, t0, 0, taba[i + nb - 1]);
+ divdq(q, r, t1, t0, tabb[nb - 1]);
+ }
+ // printf("i=%d q1=%ld\n", i, q);
+
+ r = mp_sub_mul1_dec(taba + i, tabb, nb, q);
+ // mp_dump("r1", taba + i, nb, bd);
+ // printf("r2=%ld\n", r);
+
+ v = taba[i + nb];
+ a = v - r;
+ c = a > v;
+ if (c)
+ a += base;
+ taba[i + nb] = a;
+
+ if (c != 0) {
+ /* negative result */
+ for(;;) {
+ q--;
+ c = mp_add_dec(taba + i, taba + i, tabb, nb, 0);
+ /* propagate carry and test if positive result */
+ if (c != 0) {
+ if (++taba[i + nb] == base) {
+ break;
+ }
+ }
+ }
+ }
+ tabq[i] = q;
+ }
+
+#ifdef DEBUG_DIV_SLOW
+ mp_print_str_dec("q", tabq, na - nb + 1);
+ mp_print_str_dec("r", taba, nb);
+#endif
+
+ /* remove the normalization */
+ if (mult != 1) {
+ mp_div1_dec(taba, taba, nb, mult, 0);
+ if (unlikely(tabb != static_tabb))
+ bf_free(s, tabb);
+ }
+ return 0;
+}
+
+/* divide by 10^shift */
+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;
+ limb_t l, a, q, r;
+
+ assert(shift >= 1 && shift < LIMB_DIGITS);
+ l = high;
+ for(i = n - 1; i >= 0; i--) {
+ a = tab[i];
+ fast_shr_rem_dec(q, r, a, shift);
+ tab_r[i] = q + l * mp_pow_dec[LIMB_DIGITS - shift];
+ l = r;
+ }
+ return l;
+}
+
+/* multiply by 10^shift */
+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;
+ limb_t l, a, q, r;
+
+ assert(shift >= 1 && shift < LIMB_DIGITS);
+ l = low;
+ for(i = 0; i < n; i++) {
+ a = tab[i];
+ fast_shr_rem_dec(q, r, a, LIMB_DIGITS - shift);
+ tab_r[i] = r * mp_pow_dec[shift] + l;
+ l = q;
+ }
+ return l;
+}
+
+static limb_t mp_sqrtrem2_dec(limb_t *tabs, limb_t *taba)
+{
+ int k;
+ dlimb_t a, b, r;
+ limb_t taba1[2], s, r0, r1;
+
+ /* convert to binary and normalize */
+ a = (dlimb_t)taba[1] * BF_DEC_BASE + taba[0];
+ k = clz(a >> LIMB_BITS) & ~1;
+ b = a << k;
+ taba1[0] = b;
+ taba1[1] = b >> LIMB_BITS;
+ mp_sqrtrem2(&s, taba1);
+ s >>= (k >> 1);
+ /* convert the remainder back to decimal */
+ r = a - (dlimb_t)s * (dlimb_t)s;
+ divdq_base(r1, r0, r >> LIMB_BITS, r);
+ taba[0] = r0;
+ tabs[0] = s;
+ return r1;
+}
+
+//#define DEBUG_SQRTREM_DEC
+
+/* tmp_buf must contain (n / 2 + 1 limbs) */
+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
+ mp_print_str_dec("a", taba, 2 * n);
+#endif
+ l = n / 2;
+ h = n - l;
+ qh = mp_sqrtrem_rec_dec(tabs + l, taba + 2 * l, h, tmp_buf);
+#ifdef DEBUG_SQRTREM_DEC
+ mp_print_str_dec("s1", tabs + l, h);
+ 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);
+ }
+ /* instead of dividing by 2*s, divide by s (which is normalized)
+ and update q and r */
+ mp_div_dec(NULL, tmp_buf, taba + l, n, tabs + l, h);
+ qh += tmp_buf[l];
+ for(i = 0; i < l; i++)
+ tabs[i] = tmp_buf[i];
+ ql = mp_div1_dec(tabs, tabs, l, 2, qh & 1);
+ qh = qh >> 1; /* 0 or 1 */
+ if (ql)
+ rh = mp_add_dec(taba + l, taba + l, tabs + l, h, 0);
+ else
+ rh = 0;
+#ifdef DEBUG_SQRTREM_DEC
+ 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) {
+ c = qh;
+ } else {
+ mp_mul_basecase_dec(taba + n, tabs, l, tabs, l);
+ c = mp_sub_dec(taba, taba, taba + n, 2 * l, 0);
+ }
+ rh -= mp_sub_ui_dec(taba + 2 * l, c, n - 2 * l);
+ if ((slimb_t)rh < 0) {
+ mp_sub_ui_dec(tabs, 1, n);
+ rh += mp_add_mul1_dec(taba, tabs, n, 2);
+ rh += mp_add_ui_dec(taba, 1, n);
+ }
+ return rh;
+}
+
+/* 'taba' has 2*n limbs with n >= 1 and taba[2*n-1] >= B/4. Return (s,
+ r) with s=floor(sqrt(a)) and r=a-s^2. 0 <= r <= 2 * s. tabs has n
+ limbs. r is returned in the lower n limbs of taba. Its r[n] is the
+ returned value of the function. */
+int mp_sqrtrem_dec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n)
+{
+ limb_t tmp_buf1[8];
+ limb_t *tmp_buf;
+ mp_size_t n2;
+ n2 = n / 2 + 1;
+ if (n2 <= countof(tmp_buf1)) {
+ tmp_buf = tmp_buf1;
+ } else {
+ tmp_buf = bf_malloc(s, sizeof(limb_t) * n2);
+ if (!tmp_buf)
+ return -1;
+ }
+ taba[n] = mp_sqrtrem_rec_dec(tabs, taba, n, tmp_buf);
+ if (tmp_buf != tmp_buf1)
+ bf_free(s, tmp_buf);
+ return 0;
+}
+
+/* return the number of leading zero digits, from 0 to LIMB_DIGITS */
+static int clz_dec(limb_t a)
+{
+ if (a == 0)
+ return LIMB_DIGITS;
+ switch(LIMB_BITS - 1 - clz(a)) {
+ case 0: /* 1-1 */
+ return LIMB_DIGITS - 1;
+ case 1: /* 2-3 */
+ return LIMB_DIGITS - 1;
+ case 2: /* 4-7 */
+ return LIMB_DIGITS - 1;
+ case 3: /* 8-15 */
+ if (a < 10)
+ return LIMB_DIGITS - 1;
+ else
+ return LIMB_DIGITS - 2;
+ case 4: /* 16-31 */
+ return LIMB_DIGITS - 2;
+ case 5: /* 32-63 */
+ return LIMB_DIGITS - 2;
+ case 6: /* 64-127 */
+ if (a < 100)
+ return LIMB_DIGITS - 2;
+ else
+ return LIMB_DIGITS - 3;
+ case 7: /* 128-255 */
+ return LIMB_DIGITS - 3;
+ case 8: /* 256-511 */
+ return LIMB_DIGITS - 3;
+ case 9: /* 512-1023 */
+ if (a < 1000)
+ return LIMB_DIGITS - 3;
+ else
+ return LIMB_DIGITS - 4;
+ case 10: /* 1024-2047 */
+ return LIMB_DIGITS - 4;
+ case 11: /* 2048-4095 */
+ return LIMB_DIGITS - 4;
+ case 12: /* 4096-8191 */
+ return LIMB_DIGITS - 4;
+ case 13: /* 8192-16383 */
+ if (a < 10000)
+ return LIMB_DIGITS - 4;
+ else
+ return LIMB_DIGITS - 5;
+ case 14: /* 16384-32767 */
+ return LIMB_DIGITS - 5;
+ case 15: /* 32768-65535 */
+ return LIMB_DIGITS - 5;
+ case 16: /* 65536-131071 */
+ if (a < 100000)
+ return LIMB_DIGITS - 5;
+ else
+ return LIMB_DIGITS - 6;
+ case 17: /* 131072-262143 */
+ return LIMB_DIGITS - 6;
+ case 18: /* 262144-524287 */
+ return LIMB_DIGITS - 6;
+ case 19: /* 524288-1048575 */
+ if (a < 1000000)
+ return LIMB_DIGITS - 6;
+ else
+ return LIMB_DIGITS - 7;
+ case 20: /* 1048576-2097151 */
+ return LIMB_DIGITS - 7;
+ case 21: /* 2097152-4194303 */
+ return LIMB_DIGITS - 7;
+ case 22: /* 4194304-8388607 */
+ return LIMB_DIGITS - 7;
+ case 23: /* 8388608-16777215 */
+ if (a < 10000000)
+ return LIMB_DIGITS - 7;
+ else
+ return LIMB_DIGITS - 8;
+ case 24: /* 16777216-33554431 */
+ return LIMB_DIGITS - 8;
+ case 25: /* 33554432-67108863 */
+ return LIMB_DIGITS - 8;
+ case 26: /* 67108864-134217727 */
+ if (a < 100000000)
+ return LIMB_DIGITS - 8;
+ else
+ return LIMB_DIGITS - 9;
+#if LIMB_BITS == 64
+ case 27: /* 134217728-268435455 */
+ return LIMB_DIGITS - 9;
+ case 28: /* 268435456-536870911 */
+ return LIMB_DIGITS - 9;
+ case 29: /* 536870912-1073741823 */
+ if (a < 1000000000)
+ return LIMB_DIGITS - 9;
+ else
+ return LIMB_DIGITS - 10;
+ case 30: /* 1073741824-2147483647 */
+ return LIMB_DIGITS - 10;
+ case 31: /* 2147483648-4294967295 */
+ return LIMB_DIGITS - 10;
+ case 32: /* 4294967296-8589934591 */
+ return LIMB_DIGITS - 10;
+ case 33: /* 8589934592-17179869183 */
+ if (a < 10000000000)
+ return LIMB_DIGITS - 10;
+ else
+ return LIMB_DIGITS - 11;
+ case 34: /* 17179869184-34359738367 */
+ return LIMB_DIGITS - 11;
+ case 35: /* 34359738368-68719476735 */
+ return LIMB_DIGITS - 11;
+ case 36: /* 68719476736-137438953471 */
+ if (a < 100000000000)
+ return LIMB_DIGITS - 11;
+ else
+ return LIMB_DIGITS - 12;
+ case 37: /* 137438953472-274877906943 */
+ return LIMB_DIGITS - 12;
+ case 38: /* 274877906944-549755813887 */
+ return LIMB_DIGITS - 12;
+ case 39: /* 549755813888-1099511627775 */
+ if (a < 1000000000000)
+ return LIMB_DIGITS - 12;
+ else
+ return LIMB_DIGITS - 13;
+ case 40: /* 1099511627776-2199023255551 */
+ return LIMB_DIGITS - 13;
+ case 41: /* 2199023255552-4398046511103 */
+ return LIMB_DIGITS - 13;
+ case 42: /* 4398046511104-8796093022207 */
+ return LIMB_DIGITS - 13;
+ case 43: /* 8796093022208-17592186044415 */
+ if (a < 10000000000000)
+ return LIMB_DIGITS - 13;
+ else
+ return LIMB_DIGITS - 14;
+ case 44: /* 17592186044416-35184372088831 */
+ return LIMB_DIGITS - 14;
+ case 45: /* 35184372088832-70368744177663 */
+ return LIMB_DIGITS - 14;
+ case 46: /* 70368744177664-140737488355327 */
+ if (a < 100000000000000)
+ return LIMB_DIGITS - 14;
+ else
+ return LIMB_DIGITS - 15;
+ case 47: /* 140737488355328-281474976710655 */
+ return LIMB_DIGITS - 15;
+ case 48: /* 281474976710656-562949953421311 */
+ return LIMB_DIGITS - 15;
+ case 49: /* 562949953421312-1125899906842623 */
+ if (a < 1000000000000000)
+ return LIMB_DIGITS - 15;
+ else
+ return LIMB_DIGITS - 16;
+ case 50: /* 1125899906842624-2251799813685247 */
+ return LIMB_DIGITS - 16;
+ case 51: /* 2251799813685248-4503599627370495 */
+ return LIMB_DIGITS - 16;
+ case 52: /* 4503599627370496-9007199254740991 */
+ return LIMB_DIGITS - 16;
+ case 53: /* 9007199254740992-18014398509481983 */
+ if (a < 10000000000000000)
+ return LIMB_DIGITS - 16;
+ else
+ return LIMB_DIGITS - 17;
+ case 54: /* 18014398509481984-36028797018963967 */
+ return LIMB_DIGITS - 17;
+ case 55: /* 36028797018963968-72057594037927935 */
+ return LIMB_DIGITS - 17;
+ case 56: /* 72057594037927936-144115188075855871 */
+ if (a < 100000000000000000)
+ return LIMB_DIGITS - 17;
+ else
+ return LIMB_DIGITS - 18;
+ case 57: /* 144115188075855872-288230376151711743 */
+ return LIMB_DIGITS - 18;
+ case 58: /* 288230376151711744-576460752303423487 */
+ return LIMB_DIGITS - 18;
+ case 59: /* 576460752303423488-1152921504606846975 */
+ if (a < 1000000000000000000)
+ return LIMB_DIGITS - 18;
+ else
+ return LIMB_DIGITS - 19;
+#endif
+ default:
+ return 0;
+ }
+}
+
+/* for debugging */
+void bfdec_print_str(const char *str, const bfdec_t *a)
+{
+ slimb_t i;
+ printf("%s=", str);
+
+ if (a->expn == BF_EXP_NAN) {
+ printf("NaN");
+ } else {
+ if (a->sign)
+ putchar('-');
+ if (a->expn == BF_EXP_ZERO) {
+ putchar('0');
+ } else if (a->expn == BF_EXP_INF) {
+ printf("Inf");
+ } else {
+ printf("0.");
+ for(i = a->len - 1; i >= 0; i--)
+ printf("%0*" PRIu_LIMB, LIMB_DIGITS, a->tab[i]);
+ printf("e%" PRId_LIMB, a->expn);
+ }
+ }
+ printf("\n");
+}
+
+/* return != 0 if one digit between 0 and bit_pos inclusive is not zero. */
+static inline limb_t scan_digit_nz(const bfdec_t *r, slimb_t bit_pos)
+{
+ slimb_t pos;
+ limb_t v, q;
+ int shift;
+
+ if (bit_pos < 0)
+ return 0;
+ pos = (limb_t)bit_pos / LIMB_DIGITS;
+ shift = (limb_t)bit_pos % LIMB_DIGITS;
+ fast_shr_rem_dec(q, v, r->tab[pos], shift + 1);
+ (void)q;
+ if (v != 0)
+ return 1;
+ pos--;
+ while (pos >= 0) {
+ if (r->tab[pos] != 0)
+ return 1;
+ pos--;
+ }
+ return 0;
+}
+
+static limb_t get_digit(const limb_t *tab, limb_t len, slimb_t pos)
+{
+ slimb_t i;
+ int shift;
+ i = floor_div(pos, LIMB_DIGITS);
+ if (i < 0 || i >= len)
+ return 0;
+ shift = pos - i * LIMB_DIGITS;
+ return fast_shr_dec(tab[i], shift) % 10;
+}
+
+#if 0
+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)
+ a0 = tab[i];
+ else
+ a0 = 0;
+ if (shift == 0) {
+ return a0;
+ } else {
+ i++;
+ if (i >= 0 && i < len)
+ a1 = tab[i];
+ else
+ a1 = 0;
+ return fast_shr_dec(a0, shift) +
+ fast_urem(a1, &mp_pow_div[LIMB_DIGITS - shift]) *
+ mp_pow_dec[shift];
+ }
+}
+#endif
+
+/* return the addend for rounding. Note that prec can be <= 0 for bf_rint() */
+static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l,
+ slimb_t prec, int rnd_mode)
+{
+ 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 */
+ } else {
+ /* starting limb for bit 'prec + 1' */
+ digit0 = scan_digit_nz(r, l * LIMB_DIGITS - 1 - bf_max(0, prec + 1));
+ }
+
+ /* 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:
+ break;
+ case BF_RNDN:
+ if (digit1 == 5) {
+ if (digit0) {
+ add_one = 1;
+ } else {
+ /* round to even */
+ add_one =
+ get_digit(r->tab, l, l * LIMB_DIGITS - 1 - (prec - 1)) & 1;
+ }
+ } else if (digit1 > 5) {
+ add_one = 1;
+ }
+ break;
+ case BF_RNDD:
+ case BF_RNDU:
+ if (r->sign == (rnd_mode == BF_RNDD))
+ add_one = inexact;
+ break;
+ case BF_RNDNA:
+ case BF_RNDF:
+ add_one = (digit1 >= 5);
+ break;
+ case BF_RNDA:
+ add_one = inexact;
+ break;
+ default:
+ abort();
+ }
+
+ if (inexact)
+ *pret |= BF_ST_INEXACT;
+ return add_one;
+}
+
+/* round to prec1 bits assuming 'r' is non zero and finite. 'r' is
+ assumed to have length 'l' (1 <= l <= r->len). prec1 can be
+ BF_PREC_INF. BF_FLAG_SUBNORMAL is not supported. Cannot fail with
+ BF_ST_MEM_ERROR.
+ */
+static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l)
+{
+ int shift, add_one, rnd_mode, ret;
+ slimb_t i, bit_pos, pos, e_min, e_max, e_range, prec;
+
+ /* XXX: align to IEEE 754 2008 for decimal numbers ? */
+ 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)
+ prec = r->expn + prec1;
+ else
+ prec = prec1;
+ } else if (unlikely(r->expn < e_min) && (flags & BF_FLAG_SUBNORMAL)) {
+ /* restrict the precision in case of potentially subnormal
+ result */
+ assert(prec1 != BF_PREC_INF);
+ prec = prec1 - (e_min - r->expn);
+ } 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 */
+ r->tab[0] = BF_DEC_BASE / 10;
+ r->expn += 1 - prec;
+ ret |= BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ return ret;
+ } else {
+ goto underflow;
+ }
+ } 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;
+ carry = mp_pow_dec[bit_pos % LIMB_DIGITS];
+ carry = mp_add_ui_dec(r->tab + pos, carry, l - pos);
+ if (carry) {
+ /* shift right by one digit */
+ mp_shr_dec(r->tab + pos, r->tab + pos, l - pos, 1, 1);
+ r->expn++;
+ }
+ }
+
+ /* check underflow */
+ if (unlikely(r->expn < e_min)) {
+ if (flags & BF_FLAG_SUBNORMAL) {
+ /* if inexact, also set the underflow flag */
+ if (ret & BF_ST_INEXACT)
+ ret |= BF_ST_UNDERFLOW;
+ } else {
+ underflow:
+ bfdec_set_zero(r, r->sign);
+ ret |= BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ 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);
+ if (i >= 0) {
+ shift = smod(bit_pos, LIMB_DIGITS);
+ if (shift != 0) {
+ r->tab[i] = fast_shr_dec(r->tab[i], shift) *
+ mp_pow_dec[shift];
+ }
+ } else {
+ i = 0;
+ }
+ /* remove trailing zeros */
+ while (r->tab[i] == 0)
+ i++;
+ if (i > 0) {
+ l -= i;
+ memmove(r->tab, r->tab + i, l * sizeof(limb_t));
+ }
+ bfdec_resize(r, l); /* cannot fail */
+ return ret;
+}
+
+/* Cannot fail with BF_ST_MEM_ERROR. */
+int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags)
+{
+ if (r->len == 0)
+ return 0;
+ return __bfdec_round(r, prec, flags, r->len);
+}
+
+/* 'r' must be a finite number. Cannot fail with BF_ST_MEM_ERROR. */
+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)
+ l--;
+ if (l == 0) {
+ /* zero */
+ r->expn = BF_EXP_ZERO;
+ bfdec_resize(r, 0); /* cannot fail */
+ ret = 0;
+ } else {
+ r->expn -= (r->len - l) * LIMB_DIGITS;
+ /* shift to have the MSB set to '1' */
+ v = r->tab[l - 1];
+ shift = clz_dec(v);
+ if (shift != 0) {
+ mp_shl_dec(r->tab, r->tab, l, shift, 0);
+ r->expn -= shift;
+ }
+ ret = __bfdec_round(r, prec1, flags, l);
+ }
+ // bf_print_str("r_final", r);
+ return ret;
+}
+
+int bfdec_set_ui(bfdec_t *r, uint64_t v)
+{
+#if LIMB_BITS == 32
+ if (v >= BF_DEC_BASE * BF_DEC_BASE) {
+ if (bfdec_resize(r, 3))
+ goto fail;
+ r->tab[0] = v % BF_DEC_BASE;
+ v /= BF_DEC_BASE;
+ r->tab[1] = v % BF_DEC_BASE;
+ r->tab[2] = v / BF_DEC_BASE;
+ r->expn = 3 * LIMB_DIGITS;
+ } else
+#endif
+ if (v >= BF_DEC_BASE) {
+ if (bfdec_resize(r, 2))
+ goto fail;
+ r->tab[0] = v % BF_DEC_BASE;
+ r->tab[1] = v / BF_DEC_BASE;
+ r->expn = 2 * LIMB_DIGITS;
+ } else {
+ if (bfdec_resize(r, 1))
+ goto fail;
+ r->tab[0] = v;
+ r->expn = LIMB_DIGITS;
+ }
+ r->sign = 0;
+ return bfdec_normalize_and_round(r, BF_PREC_INF, 0);
+ fail:
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+int bfdec_set_si(bfdec_t *r, int64_t v)
+{
+ int ret;
+ if (v < 0) {
+ ret = bfdec_set_ui(r, -v);
+ r->sign = 1;
+ } else {
+ ret = bfdec_set_ui(r, v);
+ }
+ return ret;
+}
+
+static int bfdec_add_internal(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bf_flags_t flags, int b_neg)
+{
+ bf_context_t *s = r->ctx;
+ int is_sub, cmp_res, a_sign, b_sign, ret;
+
+ a_sign = a->sign;
+ b_sign = b->sign ^ b_neg;
+ is_sub = a_sign ^ b_sign;
+ cmp_res = bfdec_cmpu(a, b);
+ if (cmp_res < 0) {
+ const bfdec_t *tmp;
+ tmp = a;
+ a = b;
+ b = tmp;
+ a_sign = b_sign; /* b_sign is never used later */
+ }
+ /* abs(a) >= abs(b) */
+ if (cmp_res == 0 && is_sub && a->expn < BF_EXP_INF) {
+ /* zero result */
+ bfdec_set_zero(r, (flags & BF_RND_MASK) == BF_RNDD);
+ ret = 0;
+ } else if (a->len == 0 || b->len == 0) {
+ ret = 0;
+ if (a->expn >= BF_EXP_INF) {
+ if (a->expn == BF_EXP_NAN) {
+ /* at least one operand is NaN */
+ bfdec_set_nan(r);
+ ret = 0;
+ } else if (b->expn == BF_EXP_INF && is_sub) {
+ /* infinities with different signs */
+ bfdec_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bfdec_set_inf(r, a_sign);
+ }
+ } else {
+ /* at least one zero and not subtract */
+ if (bfdec_set(r, a))
+ return BF_ST_MEM_ERROR;
+ r->sign = a_sign;
+ goto renorm;
+ }
+ } else {
+ slimb_t d, a_offset, b_offset, i, r_len;
+ limb_t carry;
+ 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
+ not infinite */
+ r_len = bf_max(a->len, b->len + (d + LIMB_DIGITS - 1) / LIMB_DIGITS);
+ if (bfdec_resize(r, r_len))
+ goto fail;
+ r->sign = a_sign;
+ r->expn = a->expn;
+
+ a_offset = r_len - a->len;
+ for(i = 0; i < a_offset; i++)
+ 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;
+ b1_tab = (limb_t *)b->tab;
+ } else {
+ b1_len = b->len + 1;
+ b1_tab = bf_malloc(s, sizeof(limb_t) * b1_len);
+ if (!b1_tab)
+ goto fail;
+ b1_tab[0] = mp_shr_dec(b1_tab + 1, b->tab, b->len, b_shift, 0) *
+ 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);
+ if (carry != 0) {
+ carry = mp_sub_ui_dec(r->tab + b_offset + b1_len, carry,
+ r_len - (b_offset + b1_len));
+ assert(carry == 0);
+ }
+ } else {
+ carry = mp_add_dec(r->tab + b_offset, r->tab + b_offset,
+ b1_tab, b1_len, 0);
+ if (carry != 0) {
+ carry = mp_add_ui_dec(r->tab + b_offset + b1_len, carry,
+ r_len - (b_offset + b1_len));
+ }
+ if (carry != 0) {
+ if (bfdec_resize(r, r_len + 1)) {
+ if (b_shift != 0)
+ bf_free(s, b1_tab);
+ goto fail;
+ }
+ r->tab[r_len] = 1;
+ r->expn += LIMB_DIGITS;
+ }
+ }
+ if (b_shift != 0)
+ bf_free(s, b1_tab);
+ renorm:
+ ret = bfdec_normalize_and_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+static int __bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bfdec_add_internal(r, a, b, prec, flags, 0);
+}
+
+static int __bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bfdec_add_internal(r, a, b, prec, flags, 1);
+}
+
+int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2((bf_t *)r, (bf_t *)a, (bf_t *)b, prec, flags,
+ (bf_op2_func_t *)__bfdec_add);
+}
+
+int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2((bf_t *)r, (bf_t *)a, (bf_t *)b, prec, flags,
+ (bf_op2_func_t *)__bfdec_sub);
+}
+
+int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ int ret, r_sign;
+
+ if (a->len < b->len) {
+ const bfdec_t *tmp = a;
+ a = b;
+ b = tmp;
+ }
+ r_sign = a->sign ^ b->sign;
+ /* here b->len <= a->len */
+ if (b->len == 0) {
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ bfdec_set_nan(r);
+ ret = 0;
+ } else if (a->expn == BF_EXP_INF || b->expn == BF_EXP_INF) {
+ if ((a->expn == BF_EXP_INF && b->expn == BF_EXP_ZERO) ||
+ (a->expn == BF_EXP_ZERO && b->expn == BF_EXP_INF)) {
+ bfdec_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bfdec_set_inf(r, r_sign);
+ ret = 0;
+ }
+ } else {
+ bfdec_set_zero(r, r_sign);
+ ret = 0;
+ }
+ } else {
+ 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;
+ r = &tmp;
+ }
+ if (bfdec_resize(r, a_len + b_len)) {
+ bfdec_set_nan(r);
+ ret = BF_ST_MEM_ERROR;
+ goto done;
+ }
+ mp_mul_basecase_dec(r->tab, a_tab, a_len, b_tab, b_len);
+ r->sign = r_sign;
+ r->expn = a->expn + b->expn;
+ ret = bfdec_normalize_and_round(r, prec, flags);
+ done:
+ if (r == &tmp)
+ bfdec_move(r1, &tmp);
+ }
+ return ret;
+}
+
+int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bfdec_t b;
+ int ret;
+ bfdec_init(r->ctx, &b);
+ ret = bfdec_set_si(&b, b1);
+ ret |= bfdec_mul(r, a, &b, prec, flags);
+ bfdec_delete(&b);
+ return ret;
+}
+
+int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bfdec_t b;
+ int ret;
+
+ bfdec_init(r->ctx, &b);
+ ret = bfdec_set_si(&b, b1);
+ ret |= bfdec_add(r, a, &b, prec, flags);
+ bfdec_delete(&b);
+ return ret;
+}
+
+static int __bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
+ limb_t prec, bf_flags_t flags)
+{
+ 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) {
+ bfdec_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF && b->expn == BF_EXP_INF) {
+ bfdec_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else if (a->expn == BF_EXP_INF) {
+ bfdec_set_inf(r, r_sign);
+ return 0;
+ } else {
+ bfdec_set_zero(r, r_sign);
+ return 0;
+ }
+ } else if (a->expn == BF_EXP_ZERO) {
+ if (b->expn == BF_EXP_ZERO) {
+ bfdec_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bfdec_set_zero(r, r_sign);
+ return 0;
+ }
+ } else if (b->expn == BF_EXP_ZERO) {
+ bfdec_set_inf(r, r_sign);
+ return BF_ST_DIVIDE_ZERO;
+ }
+
+ nb = b->len;
+ if (prec == BF_PREC_INF) {
+ /* infinite precision: return BF_ST_INVALID_OP if not an exact
+ result */
+ /* XXX: check */
+ precl = nb + 1;
+ } else if (flags & BF_FLAG_RADPNT_PREC) {
+ /* number of digits after the decimal point */
+ /* XXX: check (2 extra digits for rounding + 2 digits) */
+ precl = (bf_max(a->expn - b->expn, 0) + 2 +
+ prec + 2 + LIMB_DIGITS - 1) / LIMB_DIGITS;
+ } else {
+ /* number of limbs of the quotient (2 extra digits for rounding) */
+ 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)
+ goto fail;
+ d = na - a->len;
+ memset(taba, 0, d * sizeof(limb_t));
+ memcpy(taba + d, a->tab, a->len * sizeof(limb_t));
+ if (bfdec_resize(r, n + 1))
+ goto fail1;
+ if (mp_div_dec(r->ctx, r->tab, taba, na, b->tab, nb)) {
+ fail1:
+ bf_free(r->ctx, taba);
+ goto fail;
+ }
+ /* see if non zero remainder */
+ for(i = 0; i < nb; i++) {
+ if (taba[i] != 0)
+ break;
+ }
+ bf_free(r->ctx, taba);
+ if (i != nb) {
+ if (prec == BF_PREC_INF) {
+ bfdec_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ r->tab[0] |= 1;
+ }
+ }
+ r->expn = a->expn - b->expn + LIMB_DIGITS;
+ r->sign = r_sign;
+ ret = bfdec_normalize_and_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2((bf_t *)r, (bf_t *)a, (bf_t *)b, prec, flags,
+ (bf_op2_func_t *)__bfdec_div);
+}
+
+/* a and b must be finite numbers with a >= 0 and b > 0. 'q' is the
+ integer defined as floor(a/b) and r = a - q * b. */
+static void bfdec_tdivremu(bf_context_t *s, bfdec_t *q, bfdec_t *r,
+ const bfdec_t *a, const bfdec_t *b)
+{
+ if (bfdec_cmpu(a, b) < 0) {
+ bfdec_set_ui(q, 0);
+ bfdec_set(r, a);
+ } else {
+ bfdec_div(q, a, b, 0, BF_RNDZ | BF_FLAG_RADPNT_PREC);
+ bfdec_mul(r, q, b, BF_PREC_INF, BF_RNDZ);
+ bfdec_sub(r, a, r, BF_PREC_INF, BF_RNDZ);
+ }
+}
+
+/* division and remainder.
+
+ rnd_mode is the rounding mode for the quotient. The additional
+ rounding mode BF_RND_EUCLIDIAN is supported.
+
+ 'q' is an integer. 'r' is rounded with prec and flags (prec can be
+ BF_PREC_INF).
+*/
+int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
+ limb_t prec, bf_flags_t flags, int rnd_mode)
+{
+ bf_context_t *s = q->ctx;
+ bfdec_t a1_s, *a1 = &a1_s;
+ bfdec_t b1_s, *b1 = &b1_s;
+ 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) {
+ bfdec_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF || b->expn == BF_EXP_ZERO) {
+ bfdec_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bfdec_set(r, a);
+ return bfdec_round(r, prec, flags);
+ }
+ }
+
+ q_sign = a->sign ^ b->sign;
+ is_rndn = (rnd_mode == BF_RNDN || rnd_mode == BF_RNDNA);
+ switch(rnd_mode) {
+ default:
+ case BF_RNDZ:
+ case BF_RNDN:
+ case BF_RNDNA:
+ is_ceil = FALSE;
+ break;
+ case BF_RNDD:
+ is_ceil = q_sign;
+ break;
+ case BF_RNDU:
+ is_ceil = q_sign ^ 1;
+ break;
+ case BF_RNDA:
+ is_ceil = TRUE;
+ break;
+ case BF_DIVREM_EUCLIDIAN:
+ is_ceil = a->sign;
+ break;
+ }
+
+ a1->expn = a->expn;
+ a1->tab = a->tab;
+ a1->len = a->len;
+ a1->sign = 0;
+
+ b1->expn = b->expn;
+ b1->tab = b->tab;
+ b1->len = b->len;
+ b1->sign = 0;
+
+ // bfdec_print_str("a1", a1);
+ // bfdec_print_str("b1", b1);
+ /* XXX: could improve to avoid having a large 'q' */
+ bfdec_tdivremu(s, q, r, a1, b1);
+ if (bfdec_is_nan(q) || bfdec_is_nan(r))
+ goto fail;
+ // bfdec_print_str("q", q);
+ // bfdec_print_str("r", r);
+
+ if (r->len != 0) {
+ if (is_rndn) {
+ bfdec_init(s, r1);
+ if (bfdec_set(r1, r))
+ goto fail;
+ if (bfdec_mul_si(r1, r1, 2, BF_PREC_INF, BF_RNDZ)) {
+ bfdec_delete(r1);
+ goto fail;
+ }
+ res = bfdec_cmpu(r1, b);
+ bfdec_delete(r1);
+ if (res > 0 ||
+ (res == 0 &&
+ (rnd_mode == BF_RNDNA ||
+ (get_digit(q->tab, q->len, q->len * LIMB_DIGITS - q->expn) & 1) != 0))) {
+ goto do_sub_r;
+ }
+ } else if (is_ceil) {
+ do_sub_r:
+ res = bfdec_add_si(q, q, 1, BF_PREC_INF, BF_RNDZ);
+ res |= bfdec_sub(r, r, b1, BF_PREC_INF, BF_RNDZ);
+ if (res & BF_ST_MEM_ERROR)
+ goto fail;
+ }
+ }
+
+ r->sign ^= a->sign;
+ q->sign = q_sign;
+ return bfdec_round(r, prec, flags);
+ fail:
+ bfdec_set_nan(q);
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode)
+{
+ 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);
+ return ret;
+}
+
+/* convert to integer (infinite precision) */
+int bfdec_rint(bfdec_t *r, int rnd_mode)
+{
+ return bfdec_round(r, 0, rnd_mode | BF_FLAG_RADPNT_PREC);
+}
+
+int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = a->ctx;
+ int ret, k;
+ limb_t *a1, v;
+ slimb_t n, n1, prec1;
+ limb_t res;
+
+ assert(r != a);
+
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bfdec_set_nan(r);
+ } else if (a->expn == BF_EXP_INF && a->sign) {
+ goto invalid_op;
+ } else {
+ bfdec_set(r, a);
+ }
+ ret = 0;
+ } else if (a->sign || prec == BF_PREC_INF) {
+ invalid_op:
+ bfdec_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ if (flags & BF_FLAG_RADPNT_PREC) {
+ prec1 = bf_max(floor_div(a->expn + 1, 2) + prec, 1);
+ } else {
+ prec1 = prec;
+ }
+ /* convert the mantissa to an integer with at least 2 *
+ prec + 4 digits */
+ n = (2 * (prec1 + 2) + 2 * LIMB_DIGITS - 1) / (2 * LIMB_DIGITS);
+ if (bfdec_resize(r, n))
+ goto fail;
+ a1 = bf_malloc(s, sizeof(limb_t) * 2 * n);
+ if (!a1)
+ goto fail;
+ n1 = bf_min(2 * n, a->len);
+ memset(a1, 0, (2 * n - n1) * sizeof(limb_t));
+ memcpy(a1 + 2 * n - n1, a->tab + a->len - n1, n1 * sizeof(limb_t));
+ if (a->expn & 1) {
+ res = mp_shr_dec(a1, a1, 2 * n, 1, 0);
+ } else {
+ res = 0;
+ }
+ /* normalize so that a1 >= B^(2*n)/4. Not need for n = 1
+ because mp_sqrtrem2_dec already does it */
+ k = 0;
+ if (n > 1) {
+ v = a1[2 * n - 1];
+ while (v < BF_DEC_BASE / 4) {
+ k++;
+ v *= 4;
+ }
+ if (k != 0)
+ mp_mul1_dec(a1, a1, 2 * n, 1 << (2 * k), 0);
+ }
+ if (mp_sqrtrem_dec(s, r->tab, a1, n)) {
+ bf_free(s, a1);
+ goto fail;
+ }
+ if (k != 0)
+ mp_div1_dec(r->tab, r->tab, n, 1 << k, 0);
+ if (!res) {
+ res = mp_scan_nz(a1, n + 1);
+ }
+ bf_free(s, a1);
+ if (!res) {
+ res = mp_scan_nz(a->tab, a->len - n1);
+ }
+ if (res != 0)
+ r->tab[0] |= 1;
+ r->sign = 0;
+ r->expn = (a->expn + 1) >> 1;
+ ret = bfdec_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+/* The rounding mode is always BF_RNDZ. Return BF_ST_OVERFLOW if there
+ is an overflow and 0 otherwise. No memory error is possible. */
+int bfdec_get_int32(int *pres, const bfdec_t *a)
+{
+ uint32_t v;
+ int ret;
+ if (a->expn >= BF_EXP_INF) {
+ ret = 0;
+ if (a->expn == BF_EXP_INF) {
+ v = (uint32_t)INT32_MAX + a->sign;
+ /* XXX: return overflow ? */
+ } else {
+ v = INT32_MAX;
+ }
+ } else if (a->expn <= 0) {
+ v = 0;
+ ret = 0;
+ } else if (a->expn <= 9) {
+ v = fast_shr_dec(a->tab[a->len - 1], LIMB_DIGITS - a->expn);
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ } else if (a->expn == 10) {
+ uint64_t v1;
+ uint32_t v_max;
+#if LIMB_BITS == 64
+ v1 = fast_shr_dec(a->tab[a->len - 1], LIMB_DIGITS - a->expn);
+#else
+ v1 = (uint64_t)a->tab[a->len - 1] * 10 +
+ get_digit(a->tab, a->len, (a->len - 1) * LIMB_DIGITS - 1);
+#endif
+ v_max = (uint32_t)INT32_MAX + a->sign;
+ if (v1 > v_max) {
+ v = v_max;
+ ret = BF_ST_OVERFLOW;
+ } else {
+ v = v1;
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ }
+ } else {
+ v = (uint32_t)INT32_MAX + a->sign;
+ ret = BF_ST_OVERFLOW;
+ }
+ *pres = v;
+ return ret;
+}
+
+/* power to an integer with infinite precision */
+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);
+ ret = bfdec_set(r, a);
+ n_bits = LIMB_BITS - clz(b);
+ for(i = n_bits - 2; i >= 0; i--) {
+ ret |= bfdec_mul(r, r, r, BF_PREC_INF, BF_RNDZ);
+ if ((b >> i) & 1)
+ ret |= bfdec_mul(r, r, a, BF_PREC_INF, BF_RNDZ);
+ }
+ return ret;
+}
+
+char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags)
+{
+ return bf_ftoa_internal(plen, (const bf_t *)a, 10, prec, flags, TRUE);
+}
+
+int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
+ limb_t prec, bf_flags_t flags)
+{
+ slimb_t dummy_exp;
+ return bf_atof_internal((bf_t *)r, &dummy_exp, str, pnext, 10, prec,
+ flags, TRUE);
+}
+
+#endif /* USE_BF_DEC */
+
+#ifdef USE_FFT_MUL
+/***************************************************************/
+/* Integer multiplication with FFT */
+
+/* or LIMB_BITS at bit position 'pos' in tab */
+static inline void put_bits(limb_t *tab, limb_t len, slimb_t pos, limb_t val)
+{
+ limb_t i;
+ int p;
+
+ i = pos >> LIMB_LOG2_BITS;
+ p = pos & (LIMB_BITS - 1);
+ if (i < len)
+ tab[i] |= val << p;
+ if (p != 0) {
+ i++;
+ if (i < len) {
+ tab[i] |= val >> (LIMB_BITS - p);
+ }
+ }
+}
+
+#if defined(__AVX2__)
+
+typedef double NTTLimb;
+
+/* we must have: modulo >= 1 << NTT_MOD_LOG2_MIN */
+#define NTT_MOD_LOG2_MIN 50
+#define NTT_MOD_LOG2_MAX 51
+#define NB_MODS 5
+#define NTT_PROOT_2EXP 39
+static const int ntt_int_bits[NB_MODS] = { 254, 203, 152, 101, 50, };
+
+static const limb_t ntt_mods[NB_MODS] = { 0x00073a8000000001, 0x0007858000000001, 0x0007a38000000001, 0x0007a68000000001, 0x0007fd8000000001,
+};
+
+static const limb_t ntt_proot[2][NB_MODS] = {
+ { 0x00056198d44332c8, 0x0002eb5d640aad39, 0x00047e31eaa35fd0, 0x0005271ac118a150, 0x00075e0ce8442bd5, },
+ { 0x000461169761bcc5, 0x0002dac3cb2da688, 0x0004abc97751e3bf, 0x000656778fc8c485, 0x0000dc6469c269fa, },
+};
+
+static const limb_t ntt_mods_cr[NB_MODS * (NB_MODS - 1) / 2] = {
+ 0x00020e4da740da8e, 0x0004c3dc09c09c1d, 0x000063bd097b4271, 0x000799d8f18f18fd,
+ 0x0005384222222264, 0x000572b07c1f07fe, 0x00035cd08888889a,
+ 0x00066015555557e3, 0x000725960b60b623,
+ 0x0002fc1fa1d6ce12,
+};
+
+#else
+
+typedef limb_t NTTLimb;
+
+#if LIMB_BITS == 64
+
+#define NTT_MOD_LOG2_MIN 61
+#define NTT_MOD_LOG2_MAX 62
+#define NB_MODS 5
+#define NTT_PROOT_2EXP 51
+static const int ntt_int_bits[NB_MODS] = { 307, 246, 185, 123, 61, };
+
+static const limb_t ntt_mods[NB_MODS] = { 0x28d8000000000001, 0x2a88000000000001, 0x2ed8000000000001, 0x3508000000000001, 0x3aa8000000000001,
+};
+
+static const limb_t ntt_proot[2][NB_MODS] = {
+ { 0x1b8ea61034a2bea7, 0x21a9762de58206fb, 0x02ca782f0756a8ea, 0x278384537a3e50a1, 0x106e13fee74ce0ab, },
+ { 0x233513af133e13b8, 0x1d13140d1c6f75f1, 0x12cde57f97e3eeda, 0x0d6149e23cbe654f, 0x36cd204f522a1379, },
+};
+
+static const limb_t ntt_mods_cr[NB_MODS * (NB_MODS - 1) / 2] = {
+ 0x08a9ed097b425eea, 0x18a44aaaaaaaaab3, 0x2493f57f57f57f5d, 0x126b8d0649a7f8d4,
+ 0x09d80ed7303b5ccc, 0x25b8bcf3cf3cf3d5, 0x2ce6ce63398ce638,
+ 0x0e31fad40a57eb59, 0x02a3529fd4a7f52f,
+ 0x3a5493e93e93e94a,
+};
+
+#elif LIMB_BITS == 32
+
+/* we must have: modulo >= 1 << NTT_MOD_LOG2_MIN */
+#define NTT_MOD_LOG2_MIN 29
+#define NTT_MOD_LOG2_MAX 30
+#define NB_MODS 5
+#define NTT_PROOT_2EXP 20
+static const int ntt_int_bits[NB_MODS] = { 148, 119, 89, 59, 29, };
+
+static const limb_t ntt_mods[NB_MODS] = { 0x0000000032b00001, 0x0000000033700001, 0x0000000036d00001, 0x0000000037300001, 0x000000003e500001,
+};
+
+static const limb_t ntt_proot[2][NB_MODS] = {
+ { 0x0000000032525f31, 0x0000000005eb3b37, 0x00000000246eda9f, 0x0000000035f25901, 0x00000000022f5768, },
+ { 0x00000000051eba1a, 0x00000000107be10e, 0x000000001cd574e0, 0x00000000053806e6, 0x000000002cd6bf98, },
+};
+
+static const limb_t ntt_mods_cr[NB_MODS * (NB_MODS - 1) / 2] = {
+ 0x000000000449559a, 0x000000001eba6ca9, 0x000000002ec18e46, 0x000000000860160b,
+ 0x000000000d321307, 0x000000000bf51120, 0x000000000f662938,
+ 0x000000000932ab3e, 0x000000002f40eef8,
+ 0x000000002e760905,
+};
+
+#endif /* LIMB_BITS */
+
+#endif /* !AVX2 */
+
+#if defined(__AVX2__)
+#define NTT_TRIG_K_MAX 18
+#else
+#define NTT_TRIG_K_MAX 19
+#endif
+
+typedef struct BFNTTState {
+ bf_context_t *ctx;
+
+ /* used for mul_mod_fast() */
+ limb_t ntt_mods_div[NB_MODS];
+
+ limb_t ntt_proot_pow[NB_MODS][2][NTT_PROOT_2EXP + 1];
+ limb_t ntt_proot_pow_inv[NB_MODS][2][NTT_PROOT_2EXP + 1];
+ NTTLimb *ntt_trig[NB_MODS][2][NTT_TRIG_K_MAX + 1];
+ /* 1/2^n mod m */
+ limb_t ntt_len_inv[NB_MODS][NTT_PROOT_2EXP + 1][2];
+#if defined(__AVX2__)
+ __m256d ntt_mods_cr_vec[NB_MODS * (NB_MODS - 1) / 2];
+ __m256d ntt_mods_vec[NB_MODS];
+ __m256d ntt_mods_inv_vec[NB_MODS];
+#else
+ limb_t ntt_mods_cr_inv[NB_MODS * (NB_MODS - 1) / 2];
+#endif
+} BFNTTState;
+
+static NTTLimb *get_trig(BFNTTState *s, int k, int inverse, int m_idx);
+
+/* add modulo with up to (LIMB_BITS-1) bit modulo */
+static inline limb_t add_mod(limb_t a, limb_t b, limb_t m)
+{
+ limb_t r;
+ r = a + b;
+ if (r >= m)
+ r -= m;
+ return r;
+}
+
+/* sub modulo with up to LIMB_BITS bit modulo */
+static inline limb_t sub_mod(limb_t a, limb_t b, limb_t m)
+{
+ limb_t r;
+ r = a - b;
+ if (r > a)
+ r += m;
+ return r;
+}
+
+/* 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,
+ 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;
+ t0 = (slimb_t)r1 >> 1;
+ r += m & t0;
+ r0 = r;
+ r1 = r >> LIMB_BITS;
+ r0 += m & r1;
+ return r0;
+}
+
+/* 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,
+ limb_t m, limb_t m_inv)
+{
+ dlimb_t r;
+ r = (dlimb_t)a * (dlimb_t)b;
+ return mod_fast(r, m, m_inv);
+}
+
+static inline limb_t init_mul_mod_fast(limb_t m)
+{
+ dlimb_t t;
+ assert(m < (limb_t)1 << NTT_MOD_LOG2_MAX);
+ assert(m >= (limb_t)1 << NTT_MOD_LOG2_MIN);
+ t = (dlimb_t)1 << (LIMB_BITS + NTT_MOD_LOG2_MIN);
+ return 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,
+ limb_t m, limb_t b_inv)
+{
+ limb_t r, q;
+
+ q = ((dlimb_t)a * (dlimb_t)b_inv) >> LIMB_BITS;
+ r = a * b - q * m;
+ if (r >= m)
+ r -= m;
+ return r;
+}
+
+/* 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,
+ limb_t m, limb_t b_inv)
+{
+ limb_t r, q;
+
+ q = ((dlimb_t)a * (dlimb_t)b_inv) >> LIMB_BITS;
+ r = a * b - q * m;
+ return r;
+}
+
+static inline limb_t init_mul_mod_fast2(limb_t b, limb_t m)
+{
+ return ((dlimb_t)b << LIMB_BITS) / m;
+}
+
+#ifdef __AVX2__
+
+static inline limb_t ntt_limb_to_int(NTTLimb a, limb_t m)
+{
+ slimb_t v;
+ v = a;
+ if (v < 0)
+ v += m;
+ if (v >= m)
+ v -= m;
+ return v;
+}
+
+static inline NTTLimb int_to_ntt_limb(limb_t a, limb_t m)
+{
+ return (slimb_t)a;
+}
+
+static inline NTTLimb int_to_ntt_limb2(limb_t a, limb_t m)
+{
+ if (a >= (m / 2))
+ a -= m;
+ return (slimb_t)a;
+}
+
+/* return r + m if r < 0 otherwise r. */
+static inline __m256d ntt_mod1(__m256d r, __m256d m)
+{
+ return _mm256_blendv_pd(r, r + m, r);
+}
+
+/* input: abs(r) < 2 * m. Output: abs(r) < m */
+static inline __m256d ntt_mod(__m256d r, __m256d mf, __m256d m2f)
+{
+ return _mm256_blendv_pd(r, r + m2f, r) - mf;
+}
+
+/* input: abs(a*b) < 2 * m^2, output: abs(r) < m */
+static inline __m256d ntt_mul_mod(__m256d a, __m256d b, __m256d mf,
+ __m256d m_inv)
+{
+ __m256d r, q, ab1, ab0, qm0, qm1;
+ ab1 = a * b;
+ q = _mm256_round_pd(ab1 * m_inv, 0); /* round to nearest */
+ qm1 = q * mf;
+ qm0 = _mm256_fmsub_pd(q, mf, qm1); /* low part */
+ ab0 = _mm256_fmsub_pd(a, b, ab1); /* low part */
+ r = (ab1 - qm1) + (ab0 - qm0);
+ return r;
+}
+
+static void *bf_aligned_malloc(bf_context_t *s, size_t size, size_t align)
+{
+ void *ptr;
+ void **ptr1;
+ ptr = bf_malloc(s, size + sizeof(void *) + align - 1);
+ if (!ptr)
+ return NULL;
+ ptr1 = (void **)(((uintptr_t)ptr + sizeof(void *) + align - 1) &
+ ~(align - 1));
+ ptr1[-1] = ptr;
+ return ptr1;
+}
+
+static void bf_aligned_free(bf_context_t *s, void *ptr)
+{
+ if (!ptr)
+ return;
+ bf_free(s, ((void **)ptr)[-1]);
+}
+
+static void *ntt_malloc(BFNTTState *s, size_t size)
+{
+ return bf_aligned_malloc(s->ctx, size, 64);
+}
+
+static void ntt_free(BFNTTState *s, void *ptr)
+{
+ bf_aligned_free(s->ctx, ptr);
+}
+
+static no_inline int ntt_fft(BFNTTState *s,
+ NTTLimb *out_buf, NTTLimb *in_buf,
+ NTTLimb *tmp_buf, int fft_len_log2,
+ int inverse, int m_idx)
+{
+ limb_t nb_blocks, fft_per_block, p, k, n, stride_in, i, j;
+ NTTLimb *tab_in, *tab_out, *tmp, *trig;
+ __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);
+
+ n = (limb_t)1 << fft_len_log2;
+ assert(n >= 8);
+ stride_in = n / 2;
+
+ tab_in = in_buf;
+ tab_out = tmp_buf;
+ trig = get_trig(s, fft_len_log2, inverse, m_idx);
+ if (!trig)
+ return -1;
+ p = 0;
+ for(k = 0; k < stride_in; k += 4) {
+ a0 = _mm256_load_pd(&tab_in[k]);
+ a1 = _mm256_load_pd(&tab_in[k + stride_in]);
+ c = _mm256_load_pd(trig);
+ trig += 4;
+ b0 = ntt_mod(a0 + a1, mf, m2f);
+ b1 = ntt_mul_mod(a0 - a1, c, mf, m_inv);
+ a0 = _mm256_permute2f128_pd(b0, b1, 0x20);
+ a1 = _mm256_permute2f128_pd(b0, b1, 0x31);
+ a0 = _mm256_permute4x64_pd(a0, 0xd8);
+ a1 = _mm256_permute4x64_pd(a1, 0xd8);
+ _mm256_store_pd(&tab_out[p], a0);
+ _mm256_store_pd(&tab_out[p + 4], a1);
+ p += 2 * 4;
+ }
+ tmp = tab_in;
+ tab_in = tab_out;
+ tab_out = tmp;
+
+ trig = get_trig(s, fft_len_log2 - 1, inverse, m_idx);
+ if (!trig)
+ return -1;
+ p = 0;
+ for(k = 0; k < stride_in; k += 4) {
+ a0 = _mm256_load_pd(&tab_in[k]);
+ a1 = _mm256_load_pd(&tab_in[k + stride_in]);
+ c = _mm256_setr_pd(trig[0], trig[0], trig[1], trig[1]);
+ trig += 2;
+ b0 = ntt_mod(a0 + a1, mf, m2f);
+ b1 = ntt_mul_mod(a0 - a1, c, mf, m_inv);
+ a0 = _mm256_permute2f128_pd(b0, b1, 0x20);
+ a1 = _mm256_permute2f128_pd(b0, b1, 0x31);
+ _mm256_store_pd(&tab_out[p], a0);
+ _mm256_store_pd(&tab_out[p + 4], a1);
+ p += 2 * 4;
+ }
+ tmp = tab_in;
+ tab_in = tab_out;
+ tab_out = tmp;
+
+ nb_blocks = n / 4;
+ fft_per_block = 4;
+
+ l = fft_len_log2 - 2;
+ while (nb_blocks != 2) {
+ nb_blocks >>= 1;
+ p = 0;
+ k = 0;
+ trig = get_trig(s, l, inverse, m_idx);
+ if (!trig)
+ return -1;
+ for(i = 0; i < nb_blocks; i++) {
+ c = _mm256_set1_pd(trig[0]);
+ trig++;
+ for(j = 0; j < fft_per_block; j += 4) {
+ a0 = _mm256_load_pd(&tab_in[k + j]);
+ a1 = _mm256_load_pd(&tab_in[k + j + stride_in]);
+ b0 = ntt_mod(a0 + a1, mf, m2f);
+ b1 = ntt_mul_mod(a0 - a1, c, mf, m_inv);
+ _mm256_store_pd(&tab_out[p + j], b0);
+ _mm256_store_pd(&tab_out[p + j + fft_per_block], b1);
+ }
+ k += fft_per_block;
+ p += 2 * fft_per_block;
+ }
+ fft_per_block <<= 1;
+ l--;
+ tmp = tab_in;
+ tab_in = tab_out;
+ tab_out = tmp;
+ }
+
+ tab_out = out_buf;
+ for(k = 0; k < stride_in; k += 4) {
+ a0 = _mm256_load_pd(&tab_in[k]);
+ a1 = _mm256_load_pd(&tab_in[k + stride_in]);
+ b0 = ntt_mod(a0 + a1, mf, m2f);
+ b1 = ntt_mod(a0 - a1, mf, m2f);
+ _mm256_store_pd(&tab_out[k], b0);
+ _mm256_store_pd(&tab_out[k + stride_in], b1);
+ }
+ return 0;
+}
+
+static void ntt_vec_mul(BFNTTState *s,
+ NTTLimb *tab1, NTTLimb *tab2, limb_t fft_len_log2,
+ int k_tot, int m_idx)
+{
+ 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);
+ mf = _mm256_set1_pd(m);
+ c = _mm256_set1_pd(int_to_ntt_limb(c_inv, m));
+ n = (limb_t)1 << fft_len_log2;
+ for(i = 0; i < n; i += 4) {
+ a = _mm256_load_pd(&tab1[i]);
+ b = _mm256_load_pd(&tab2[i]);
+ a = ntt_mul_mod(a, b, mf, m_inv);
+ a = ntt_mul_mod(a, c, mf, m_inv);
+ _mm256_store_pd(&tab1[i], a);
+ }
+}
+
+static no_inline void mul_trig(NTTLimb *buf,
+ limb_t n, limb_t c1, limb_t m, limb_t m_inv1)
+{
+ 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);
+
+ c2 = mul_mod_fast(c1, c1, m, m_inv1);
+ c3 = mul_mod_fast(c2, c1, m, m_inv1);
+ c4 = mul_mod_fast(c2, c2, m, m_inv1);
+ c = _mm256_setr_pd(1, int_to_ntt_limb(c1, m),
+ int_to_ntt_limb(c2, m), int_to_ntt_limb(c3, m));
+ c_mul = _mm256_set1_pd(int_to_ntt_limb(c4, m));
+ for(i = 0; i < n; i += 4) {
+ a0 = _mm256_load_pd(&buf[i]);
+ a0 = ntt_mul_mod(a0, c, mf, m_inv);
+ _mm256_store_pd(&buf[i], a0);
+ c = ntt_mul_mod(c, c_mul, mf, m_inv);
+ }
+}
+
+#else
+
+static void *ntt_malloc(BFNTTState *s, size_t size)
+{
+ return bf_malloc(s->ctx, size);
+}
+
+static void ntt_free(BFNTTState *s, void *ptr)
+{
+ bf_free(s->ctx, ptr);
+}
+
+static inline limb_t ntt_limb_to_int(NTTLimb a, limb_t m)
+{
+ if (a >= m)
+ a -= m;
+ return a;
+}
+
+static inline NTTLimb int_to_ntt_limb(slimb_t a, limb_t m)
+{
+ return a;
+}
+
+static no_inline int ntt_fft(BFNTTState *s, NTTLimb *out_buf, NTTLimb *in_buf,
+ NTTLimb *tmp_buf, int fft_len_log2,
+ int inverse, int m_idx)
+{
+ 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;
+ nb_blocks = n;
+ fft_per_block = 1;
+ stride_in = n / 2;
+ tab_in = in_buf;
+ tab_out = tmp_buf;
+ l = fft_len_log2;
+ while (nb_blocks != 2) {
+ nb_blocks >>= 1;
+ p = 0;
+ k = 0;
+ trig = get_trig(s, l, inverse, m_idx);
+ if (!trig)
+ return -1;
+ for(i = 0; i < nb_blocks; i++) {
+ c = trig[0];
+ c_inv = trig[1];
+ trig += 2;
+ for(j = 0; j < fft_per_block; j++) {
+ a0 = tab_in[k + j];
+ a1 = tab_in[k + j + stride_in];
+ b0 = add_mod(a0, a1, m2);
+ b1 = a0 - a1 + m2;
+ b1 = mul_mod_fast3(b1, c, m, c_inv);
+ tab_out[p + j] = b0;
+ tab_out[p + j + fft_per_block] = b1;
+ }
+ k += fft_per_block;
+ p += 2 * fft_per_block;
+ }
+ fft_per_block <<= 1;
+ l--;
+ tmp = tab_in;
+ tab_in = tab_out;
+ tab_out = tmp;
+ }
+ /* no twiddle in last step */
+ tab_out = out_buf;
+ for(k = 0; k < stride_in; k++) {
+ a0 = tab_in[k];
+ a1 = tab_in[k + stride_in];
+ b0 = add_mod(a0, a1, m2);
+ b1 = sub_mod(a0, a1, m2);
+ tab_out[k] = b0;
+ tab_out[k + stride_in] = b1;
+ }
+ return 0;
+}
+
+static void ntt_vec_mul(BFNTTState *s,
+ NTTLimb *tab1, NTTLimb *tab2, int fft_len_log2,
+ 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];
+ norm_inv = s->ntt_len_inv[m_idx][k_tot][1];
+ n = (limb_t)1 << fft_len_log2;
+ for(i = 0; i < n; i++) {
+ a = tab1[i];
+ /* need to reduce the range so that the product is <
+ 2^(LIMB_BITS+NTT_MOD_LOG2_MIN) */
+ if (a >= m)
+ a -= m;
+ a = mul_mod_fast(a, tab2[i], m, m_inv);
+ a = mul_mod_fast3(a, norm, m, norm_inv);
+ tab1[i] = a;
+ }
+}
+
+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++) {
+ buf[i] = mul_mod_fast(buf[i], c0, m, m_inv);
+ c0 = mul_mod_fast2(c0, c_mul, m, c_mul_inv);
+ }
+}
+
+#endif /* !AVX2 */
+
+static no_inline NTTLimb *get_trig(BFNTTState *s,
+ int k, int inverse, int m_idx)
+{
+ NTTLimb *tab;
+ limb_t i, n2, c, c_mul, m, c_mul_inv;
+
+ if (k > NTT_TRIG_K_MAX)
+ return NULL;
+
+ tab = s->ntt_trig[m_idx][inverse][k];
+ if (tab)
+ return tab;
+ n2 = (limb_t)1 << (k - 1);
+ m = ntt_mods[m_idx];
+#ifdef __AVX2__
+ tab = ntt_malloc(s, sizeof(NTTLimb) * n2);
+#else
+ tab = ntt_malloc(s, sizeof(NTTLimb) * n2 * 2);
+#endif
+ if (!tab)
+ return NULL;
+ c = 1;
+ c_mul = s->ntt_proot_pow[m_idx][inverse][k];
+ c_mul_inv = s->ntt_proot_pow_inv[m_idx][inverse][k];
+ for(i = 0; i < n2; i++) {
+#ifdef __AVX2__
+ tab[i] = int_to_ntt_limb2(c, m);
+#else
+ tab[2 * i] = int_to_ntt_limb(c, m);
+ tab[2 * i + 1] = init_mul_mod_fast2(c, m);
+#endif
+ c = mul_mod_fast2(c, c_mul, m, c_mul_inv);
+ }
+ s->ntt_trig[m_idx][inverse][k] = tab;
+ return tab;
+}
+
+void fft_clear_cache(bf_context_t *s1)
+{
+ int m_idx, inverse, k;
+ BFNTTState *s = s1->ntt_state;
+ if (s) {
+ for(m_idx = 0; m_idx < NB_MODS; m_idx++) {
+ for(inverse = 0; inverse < 2; inverse++) {
+ for(k = 0; k < NTT_TRIG_K_MAX + 1; k++) {
+ if (s->ntt_trig[m_idx][inverse][k]) {
+ ntt_free(s, s->ntt_trig[m_idx][inverse][k]);
+ s->ntt_trig[m_idx][inverse][k] = NULL;
+ }
+ }
+ }
+ }
+#if defined(__AVX2__)
+ bf_aligned_free(s1, s);
+#else
+ bf_free(s1, s);
+#endif
+ s1->ntt_state = NULL;
+ }
+}
+
+#define STRIP_LEN 16
+
+/* dst = buf1, src = buf2 */
+static int ntt_fft_partial(BFNTTState *s, NTTLimb *buf1,
+ int k1, int k2, limb_t n1, limb_t n2, int inverse,
+ limb_t m_idx)
+{
+ 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)
+ goto fail;
+ if (k2 == 0) {
+ if (ntt_fft(s, buf1, buf1, buf3, k1, inverse, m_idx))
+ goto fail;
+ } else {
+ strip_len = STRIP_LEN;
+ buf2 = ntt_malloc(s, sizeof(NTTLimb) * n1 * strip_len);
+ if (!buf2)
+ goto fail;
+ m = ntt_mods[m_idx];
+ m_inv = s->ntt_mods_div[m_idx];
+ c0 = s->ntt_proot_pow[m_idx][inverse][k1 + k2];
+ c_mul = 1;
+ assert((n2 % strip_len) == 0);
+ for(j = 0; j < n2; j += strip_len) {
+ for(i = 0; i < n1; i++) {
+ for(l = 0; l < strip_len; l++) {
+ buf2[i + l * n1] = buf1[i * n2 + (j + l)];
+ }
+ }
+ for(l = 0; l < strip_len; l++) {
+ if (inverse)
+ mul_trig(buf2 + l * n1, n1, c_mul, m, m_inv);
+ if (ntt_fft(s, buf2 + l * n1, buf2 + l * n1, buf3, k1, inverse, m_idx))
+ goto fail;
+ if (!inverse)
+ 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];
+ }
+ }
+ }
+ ntt_free(s, buf2);
+ }
+ ntt_free(s, buf3);
+ return 0;
+ fail:
+ ntt_free(s, buf2);
+ ntt_free(s, buf3);
+ return -1;
+}
+
+
+/* dst = buf1, src = buf2, tmp = buf3 */
+static int ntt_conv(BFNTTState *s, NTTLimb *buf1, NTTLimb *buf2,
+ int k, int k_tot, limb_t m_idx)
+{
+ limb_t n1, n2, i;
+ int k1, k2;
+
+ if (k <= NTT_TRIG_K_MAX) {
+ k1 = k;
+ } else {
+ /* recursive split of the FFT */
+ k1 = bf_min(k / 2, NTT_TRIG_K_MAX);
+ }
+ 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))
+ return -1;
+ if (k2 == 0) {
+ ntt_vec_mul(s, buf1, buf2, k, k_tot, m_idx);
+ } else {
+ for(i = 0; i < n1; i++) {
+ ntt_conv(s, buf1 + i * n2, buf2 + i * n2, k2, k_tot, m_idx);
+ }
+ }
+ if (ntt_fft_partial(s, buf1, k1, k2, n1, n2, 1, m_idx))
+ return -1;
+ return 0;
+}
+
+
+static no_inline void limb_to_ntt(BFNTTState *s,
+ NTTLimb *tabr, limb_t fft_len,
+ const limb_t *taba, limb_t a_len, int dpl,
+ int first_m_idx, int nb_mods)
+{
+ slimb_t i, n;
+ 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
+ memset(tabr, 0, sizeof(NTTLimb) * fft_len * nb_mods);
+ shift = dpl & (LIMB_BITS - 1);
+ if (shift == 0)
+ base_mask1 = -1;
+ else
+ base_mask1 = ((limb_t)1 << shift) - 1;
+ n = bf_min(fft_len, (a_len * LIMB_BITS + dpl - 1) / dpl);
+ for(i = 0; i < n; i++) {
+ a0 = get_bits(taba, a_len, i * dpl);
+ if (dpl <= LIMB_BITS) {
+ a0 &= base_mask1;
+ a = a0;
+ } else {
+ a1 = get_bits(taba, a_len, i * dpl + LIMB_BITS);
+ if (dpl <= (LIMB_BITS + NTT_MOD_LOG2_MIN)) {
+ a = a0 | ((dlimb_t)(a1 & base_mask1) << LIMB_BITS);
+ } else {
+ if (dpl > 2 * LIMB_BITS) {
+ a2 = get_bits(taba, a_len, i * dpl + LIMB_BITS * 2) &
+ base_mask1;
+ } else {
+ a1 &= base_mask1;
+ a2 = 0;
+ }
+ // printf("a=0x%016lx%016lx%016lx\n", a2, a1, a0);
+ a = (a0 >> (LIMB_BITS - NTT_MOD_LOG2_MAX + NTT_MOD_LOG2_MIN)) |
+ ((dlimb_t)a1 << (NTT_MOD_LOG2_MAX - NTT_MOD_LOG2_MIN)) |
+ ((dlimb_t)a2 << (LIMB_BITS + NTT_MOD_LOG2_MAX - NTT_MOD_LOG2_MIN));
+ a0 &= ((limb_t)1 << (LIMB_BITS - NTT_MOD_LOG2_MAX + NTT_MOD_LOG2_MIN)) - 1;
+ }
+ }
+ for(j = 0; j < nb_mods; j++) {
+ m = ntt_mods[first_m_idx + j];
+ m_inv = s->ntt_mods_div[first_m_idx + j];
+ r = mod_fast(a, m, m_inv);
+ if (dpl > (LIMB_BITS + NTT_MOD_LOG2_MIN)) {
+ b = ((dlimb_t)r << (LIMB_BITS - NTT_MOD_LOG2_MAX + NTT_MOD_LOG2_MIN)) | a0;
+ r = mod_fast(b, m, m_inv);
+ }
+ tabr[i + j * fft_len] = int_to_ntt_limb(r, m);
+ }
+ }
+}
+
+#if defined(__AVX2__)
+
+#define VEC_LEN 4
+
+typedef union {
+ __m256d v;
+ double d[4];
+} VecUnion;
+
+static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
+ const NTTLimb *buf, int fft_len_log2, int dpl,
+ int nb_mods)
+{
+ const limb_t *mods = ntt_mods + NB_MODS - nb_mods;
+ const __m256d *mods_cr_vec, *mf, *m_inv;
+ VecUnion y[NB_MODS];
+ limb_t u[NB_MODS], carry[NB_MODS], fft_len, base_mask1, r;
+ 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++)
+ carry[j] = 0;
+ 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;
+ len = bf_min(fft_len, (r_len * LIMB_BITS + dpl - 1) / dpl);
+ len = (len + VEC_LEN - 1) & ~(VEC_LEN - 1);
+ i = 0;
+ while (i < len) {
+ for(j = 0; j < nb_mods; j++)
+ y[j].v = *(__m256d *)&buf[i + fft_len * j];
+
+ /* Chinese remainder to get mixed radix representation */
+ l = 0;
+ for(j = 0; j < nb_mods - 1; j++) {
+ y[j].v = ntt_mod1(y[j].v, mf[j]);
+ for(k = j + 1; k < nb_mods; k++) {
+ y[k].v = ntt_mul_mod(y[k].v - y[j].v,
+ mods_cr_vec[l], mf[k], m_inv[k]);
+ l++;
+ }
+ }
+ 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];
+ l = 1;
+ for(j = nb_mods - 2; j >= 1; j--) {
+ r = (int64_t)y[j].d[p];
+ for(k = 0; k < l; k++) {
+ t = (dlimb_t)u[k] * mods[j] + r;
+ r = t >> LIMB_BITS;
+ u[k] = t;
+ }
+ u[l] = r;
+ 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++) {
+ t = (dlimb_t)u[k] * mods[j] + r + carry[k];
+ r = t >> LIMB_BITS;
+ u[k] = t;
+ }
+ u[l] = r + carry[l];
+
+#if 0
+ printf("%" PRId64 ": ", i);
+ for(j = nb_mods - 1; j >= 0; j--) {
+ printf(" %019" PRIu64, u[j]);
+ }
+ printf("\n");
+#endif
+
+ /* write the digits */
+ pos = i * dpl;
+ for(j = 0; j < n_limb1; j++) {
+ put_bits(tabr, r_len, pos, u[j]);
+ pos += LIMB_BITS;
+ }
+ put_bits(tabr, r_len, pos, u[n_limb1] & base_mask1);
+ /* shift by dpl digits and set the carry */
+ if (shift == 0) {
+ for(j = n_limb1 + 1; j < nb_mods; j++)
+ carry[j - (n_limb1 + 1)] = u[j];
+ } else {
+ for(j = n_limb1; j < nb_mods - 1; j++) {
+ carry[j - n_limb1] = (u[j] >> shift) |
+ (u[j + 1] << (LIMB_BITS - shift));
+ }
+ carry[nb_mods - 1 - n_limb1] = u[nb_mods - 1] >> shift;
+ }
+ i++;
+ }
+ }
+}
+#else
+static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
+ const NTTLimb *buf, int fft_len_log2, int dpl,
+ int nb_mods)
+{
+ const limb_t *mods = ntt_mods + NB_MODS - nb_mods;
+ const limb_t *mods_cr, *mods_cr_inv;
+ limb_t y[NB_MODS], u[NB_MODS], carry[NB_MODS], fft_len, base_mask1, r;
+ 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;
+
+ 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++)
+ carry[j] = 0;
+ 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;
+ len = bf_min(fft_len, (r_len * LIMB_BITS + dpl - 1) / dpl);
+ for(i = 0; i < len; i++) {
+ for(j = 0; j < nb_mods; j++) {
+ y[j] = ntt_limb_to_int(buf[i + fft_len * j], mods[j]);
+ }
+
+ /* Chinese remainder to get mixed radix representation */
+ l = 0;
+ for(j = 0; j < nb_mods - 1; j++) {
+ for(k = j + 1; k < nb_mods; k++) {
+ limb_t m;
+ 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,
+ mods_cr[l], m, mods_cr_inv[l]);
+ l++;
+ }
+ }
+
+ /* back to normal representation */
+ u[0] = y[nb_mods - 1];
+ l = 1;
+ for(j = nb_mods - 2; j >= 1; j--) {
+ r = y[j];
+ for(k = 0; k < l; k++) {
+ t = (dlimb_t)u[k] * mods[j] + r;
+ r = t >> LIMB_BITS;
+ u[k] = t;
+ }
+ u[l] = r;
+ l++;
+ }
+
+ /* last step adds the carry */
+ r = y[0];
+ for(k = 0; k < l; k++) {
+ t = (dlimb_t)u[k] * mods[j] + r + carry[k];
+ r = t >> LIMB_BITS;
+ u[k] = t;
+ }
+ u[l] = r + carry[l];
+
+#if 0
+ printf("%" PRId64 ": ", (int64_t)i);
+ for(j = nb_mods - 1; j >= 0; j--) {
+ printf(" " FMT_LIMB, u[j]);
+ }
+ printf("\n");
+#endif
+
+ /* write the digits */
+ pos = i * dpl;
+ for(j = 0; j < n_limb1; j++) {
+ put_bits(tabr, r_len, pos, u[j]);
+ pos += LIMB_BITS;
+ }
+ put_bits(tabr, r_len, pos, u[n_limb1] & base_mask1);
+ /* shift by dpl digits and set the carry */
+ if (shift == 0) {
+ for(j = n_limb1 + 1; j < nb_mods; j++)
+ carry[j - (n_limb1 + 1)] = u[j];
+ } else {
+ for(j = n_limb1; j < nb_mods - 1; j++) {
+ carry[j - n_limb1] = (u[j] >> shift) |
+ (u[j + 1] << (LIMB_BITS - shift));
+ }
+ carry[nb_mods - 1 - n_limb1] = u[nb_mods - 1] >> shift;
+ }
+ }
+}
+#endif
+
+static int ntt_static_init(bf_context_t *s1)
+{
+ BFNTTState *s;
+ int inverse, i, j, k, l;
+ limb_t c, c_inv, c_inv2, m, m_inv;
+
+ if (s1->ntt_state)
+ return 0;
+#if defined(__AVX2__)
+ s = bf_aligned_malloc(s1, sizeof(*s), 64);
+#else
+ s = bf_malloc(s1, sizeof(*s));
+#endif
+ if (!s)
+ return -1;
+ 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);
+ s->ntt_mods_div[j] = m_inv;
+#if defined(__AVX2__)
+ s->ntt_mods_vec[j] = _mm256_set1_pd(m);
+ s->ntt_mods_inv_vec[j] = _mm256_set1_pd(1.0 / (double)m);
+#endif
+ c_inv2 = (m + 1) / 2; /* 1/2 */
+ c_inv = 1;
+ for(i = 0; i <= NTT_PROOT_2EXP; i++) {
+ s->ntt_len_inv[j][i][0] = c_inv;
+ s->ntt_len_inv[j][i][1] = init_mul_mod_fast2(c_inv, m);
+ c_inv = mul_mod_fast(c_inv, c_inv2, m, m_inv);
+ }
+
+ for(inverse = 0; inverse < 2; inverse++) {
+ c = ntt_proot[inverse][j];
+ for(i = 0; i < NTT_PROOT_2EXP; i++) {
+ s->ntt_proot_pow[j][inverse][NTT_PROOT_2EXP - i] = c;
+ s->ntt_proot_pow_inv[j][inverse][NTT_PROOT_2EXP - i] =
+ init_mul_mod_fast2(c, m);
+ c = mul_mod_fast(c, c, m, m_inv);
+ }
+ }
+ }
+
+ l = 0;
+ for(j = 0; j < NB_MODS - 1; j++) {
+ for(k = j + 1; k < NB_MODS; k++) {
+#if defined(__AVX2__)
+ s->ntt_mods_cr_vec[l] = _mm256_set1_pd(int_to_ntt_limb2(ntt_mods_cr[l],
+ ntt_mods[k]));
+#else
+ s->ntt_mods_cr_inv[l] = init_mul_mod_fast2(ntt_mods_cr[l],
+ ntt_mods[k]);
+#endif
+ l++;
+ }
+ }
+ return 0;
+}
+
+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;
+ fft_len_log2_found = 0;
+ for(nb_mods = 3; nb_mods <= NB_MODS; nb_mods++) {
+ int_bits = ntt_int_bits[NB_MODS - nb_mods];
+ dpl = bf_min((int_bits - 4) / 2,
+ 2 * LIMB_BITS + 2 * NTT_MOD_LOG2_MIN - NTT_MOD_LOG2_MAX);
+ for(;;) {
+ fft_len_log2 = ceil_log2((len * LIMB_BITS + dpl - 1) / dpl);
+ if (fft_len_log2 > NTT_PROOT_2EXP)
+ goto next;
+ n_bits = fft_len_log2 + 2 * dpl;
+ if (n_bits <= int_bits) {
+ cost = ((limb_t)(fft_len_log2 + 1) << fft_len_log2) * nb_mods;
+ // printf("n=%d dpl=%d: cost=%" PRId64 "\n", nb_mods, dpl, (int64_t)cost);
+ if (cost < min_cost) {
+ min_cost = cost;
+ dpl_found = dpl;
+ nb_mods_found = nb_mods;
+ fft_len_log2_found = fft_len_log2;
+ }
+ break;
+ }
+ dpl--;
+ if (dpl == 0)
+ break;
+ }
+ next: ;
+ }
+ if (!dpl_found)
+ abort();
+ /* limit dpl if possible to reduce fixed cost of limb/NTT conversion */
+ if (dpl_found > (LIMB_BITS + NTT_MOD_LOG2_MIN) &&
+ ((limb_t)(LIMB_BITS + NTT_MOD_LOG2_MIN) << fft_len_log2_found) >=
+ len * LIMB_BITS) {
+ dpl_found = LIMB_BITS + NTT_MOD_LOG2_MIN;
+ }
+ *pnb_mods = nb_mods_found;
+ *pdpl = dpl_found;
+ return fft_len_log2_found;
+}
+
+/* return 0 if OK, -1 if memory error */
+static no_inline int fft_mul(bf_context_t *s1,
+ bf_t *res, limb_t *a_tab, limb_t a_len,
+ limb_t *b_tab, limb_t b_len, int mul_flags)
+{
+ BFNTTState *s;
+ int dpl, fft_len_log2, j, nb_mods, reduced_mem;
+ slimb_t len, fft_len;
+ NTTLimb *buf1, *buf2, *ptr;
+#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);
+ fft_len = (uint64_t)1 << fft_len_log2;
+ // printf("len=%" PRId64 " fft_len_log2=%d dpl=%d\n", len, fft_len_log2, dpl);
+#if defined(USE_MUL_CHECK)
+ ha = mp_mod1(a_tab, a_len, BF_CHKSUM_MOD, 0);
+ hb = mp_mod1(b_tab, b_len, BF_CHKSUM_MOD, 0);
+#endif
+ if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) == 0) {
+ if (!(mul_flags & FFT_MUL_R_NORESIZE))
+ bf_resize(res, 0);
+ } else if (mul_flags & FFT_MUL_R_OVERLAP_B) {
+ limb_t *tmp_tab, tmp_len;
+ /* it is better to free 'b' first */
+ tmp_tab = a_tab;
+ a_tab = b_tab;
+ b_tab = tmp_tab;
+ tmp_len = a_len;
+ a_len = b_len;
+ b_len = tmp_len;
+ }
+ buf1 = ntt_malloc(s, sizeof(NTTLimb) * fft_len * nb_mods);
+ if (!buf1)
+ 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)) ==
+ FFT_MUL_R_OVERLAP_A) {
+ if (!(mul_flags & FFT_MUL_R_NORESIZE))
+ bf_resize(res, 0);
+ }
+ reduced_mem = (fft_len_log2 >= 14);
+ if (!reduced_mem) {
+ buf2 = ntt_malloc(s, sizeof(NTTLimb) * fft_len * nb_mods);
+ if (!buf2)
+ goto fail;
+ limb_to_ntt(s, buf2, fft_len, b_tab, b_len, dpl,
+ NB_MODS - nb_mods, nb_mods);
+ if (!(mul_flags & FFT_MUL_R_NORESIZE))
+ bf_resize(res, 0); /* in case res == b */
+ } else {
+ buf2 = ntt_malloc(s, sizeof(NTTLimb) * fft_len);
+ if (!buf2)
+ goto fail;
+ }
+ for(j = 0; j < nb_mods; j++) {
+ if (reduced_mem) {
+ limb_to_ntt(s, buf2, fft_len, b_tab, b_len, dpl,
+ NB_MODS - nb_mods + j, 1);
+ ptr = buf2;
+ } else {
+ ptr = buf2 + fft_len * j;
+ }
+ if (ntt_conv(s, buf1 + fft_len * j, ptr,
+ fft_len_log2, fft_len_log2, j + NB_MODS - nb_mods))
+ goto fail;
+ }
+ if (!(mul_flags & FFT_MUL_R_NORESIZE))
+ bf_resize(res, 0); /* in case res == b and reduced mem */
+ ntt_free(s, buf2);
+ buf2 = NULL;
+ if (!(mul_flags & FFT_MUL_R_NORESIZE)) {
+ if (bf_resize(res, len))
+ goto fail;
+ }
+ ntt_to_limb(s, res->tab, len, buf1, fft_len_log2, dpl, nb_mods);
+ ntt_free(s, buf1);
+#if defined(USE_MUL_CHECK)
+ hr = mp_mod1(res->tab, len, BF_CHKSUM_MOD, 0);
+ h_ref = mul_mod(ha, hb, BF_CHKSUM_MOD);
+ if (hr != h_ref) {
+ printf("ntt_mul_error: len=%" PRId_LIMB " fft_len_log2=%d dpl=%d nb_mods=%d\n",
+ len, fft_len_log2, dpl, nb_mods);
+ // 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
+ return 0;
+ fail:
+ ntt_free(s, buf1);
+ ntt_free(s, buf2);
+ return -1;
+}
+
+#else /* USE_FFT_MUL */
+
+int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len)
+{
+ return 0;
+}
+
+#endif /* !USE_FFT_MUL */
diff --git a/src/shared/quickjs/libbf.h b/src/shared/quickjs/libbf.h
new file mode 100644
index 000000000..b247952b1
--- /dev/null
+++ b/src/shared/quickjs/libbf.h
@@ -0,0 +1,543 @@
+/*
+ * Tiny arbitrary precision floating point library
+ *
+ * Copyright (c) 2017-2021 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef LIBBF_H
+#define LIBBF_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
+#define LIMB_LOG2_BITS 6
+#else
+#define LIMB_LOG2_BITS 5
+#endif
+
+#define LIMB_BITS (1 << LIMB_LOG2_BITS)
+
+#if LIMB_BITS == 64
+typedef __int128 int128_t;
+typedef unsigned __int128 uint128_t;
+typedef int64_t slimb_t;
+typedef uint64_t limb_t;
+typedef uint128_t dlimb_t;
+#define BF_RAW_EXP_MIN INT64_MIN
+#define BF_RAW_EXP_MAX INT64_MAX
+
+#define LIMB_DIGITS 19
+#define BF_DEC_BASE UINT64_C(10000000000000000000)
+
+#else
+
+typedef int32_t slimb_t;
+typedef uint32_t limb_t;
+typedef uint64_t dlimb_t;
+#define BF_RAW_EXP_MIN INT32_MIN
+#define BF_RAW_EXP_MAX INT32_MAX
+
+#define LIMB_DIGITS 9
+#define BF_DEC_BASE 1000000000U
+
+#endif
+
+/* in bits */
+/* minimum number of bits for the exponent */
+#define BF_EXP_BITS_MIN 3
+/* maximum number of bits for the exponent */
+#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
+/* extended range for exponent, used internally */
+#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
+/* minimum possible precision */
+#define BF_PREC_MIN 2
+/* minimum possible precision */
+#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
+/* some operations support infinite precision */
+#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
+
+#if LIMB_BITS == 64
+#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
+#else
+#define BF_CHKSUM_MOD 975620677U
+#endif
+
+#define BF_EXP_ZERO BF_RAW_EXP_MIN
+#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
+#define BF_EXP_NAN BF_RAW_EXP_MAX
+
+/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
+ +/-infinity is represented with expn = BF_EXP_INF and len = 0,
+ NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
+ */
+typedef struct {
+ struct bf_context_t *ctx;
+ int sign;
+ slimb_t expn;
+ limb_t len;
+ limb_t *tab;
+} bf_t;
+
+typedef struct {
+ /* must be kept identical to bf_t */
+ struct bf_context_t *ctx;
+ int sign;
+ slimb_t expn;
+ limb_t len;
+ limb_t *tab;
+} bfdec_t;
+
+typedef enum {
+ BF_RNDN, /* round to nearest, ties to even */
+ BF_RNDZ, /* round to zero */
+ BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */
+ BF_RNDU, /* round to +inf */
+ BF_RNDNA, /* round to nearest, ties away from zero */
+ BF_RNDA, /* round away from zero */
+ BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
+ inexact flag is always set) */
+} bf_rnd_t;
+
+/* allow subnormal numbers. Only available if the number of exponent
+ bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */
+#define BF_FLAG_SUBNORMAL (1 << 3)
+/* 'prec' is the precision after the radix point instead of the whole
+ mantissa. Can only be used with bf_round() and
+ bfdec_[add|sub|mul|div|sqrt|round](). */
+#define BF_FLAG_RADPNT_PREC (1 << 4)
+
+#define BF_RND_MASK 0x7
+#define BF_EXP_BITS_SHIFT 5
+#define BF_EXP_BITS_MASK 0x3f
+
+/* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */
+#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
+
+/* contains the rounding mode and number of exponents bits */
+typedef uint32_t bf_flags_t;
+
+typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
+
+typedef struct {
+ bf_t val;
+ limb_t prec;
+} BFConstCache;
+
+typedef struct bf_context_t {
+ void *realloc_opaque;
+ bf_realloc_func_t *realloc_func;
+ BFConstCache log2_cache;
+ BFConstCache pi_cache;
+ struct BFNTTState *ntt_state;
+} bf_context_t;
+
+static inline int bf_get_exp_bits(bf_flags_t flags)
+{
+ int e;
+ e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
+ if (e == BF_EXP_BITS_MASK)
+ return BF_EXP_BITS_MAX + 1;
+ else
+ return BF_EXP_BITS_MAX - e;
+}
+
+static inline bf_flags_t bf_set_exp_bits(int n)
+{
+ return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
+}
+
+/* returned status */
+#define BF_ST_INVALID_OP (1 << 0)
+#define BF_ST_DIVIDE_ZERO (1 << 1)
+#define BF_ST_OVERFLOW (1 << 2)
+#define BF_ST_UNDERFLOW (1 << 3)
+#define BF_ST_INEXACT (1 << 4)
+/* indicate that a memory allocation error occured. NaN is returned */
+#define BF_ST_MEM_ERROR (1 << 5)
+
+#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
+
+static inline slimb_t bf_max(slimb_t a, slimb_t b)
+{
+ if (a > b)
+ return a;
+ else
+ return b;
+}
+
+static inline slimb_t bf_min(slimb_t a, slimb_t b)
+{
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
+ void *realloc_opaque);
+void bf_context_end(bf_context_t *s);
+/* free memory allocated for the bf cache data */
+void bf_clear_cache(bf_context_t *s);
+
+static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
+{
+ return s->realloc_func(s->realloc_opaque, ptr, size);
+}
+
+/* 'size' must be != 0 */
+static inline void *bf_malloc(bf_context_t *s, size_t size)
+{
+ return bf_realloc(s, NULL, size);
+}
+
+static inline void bf_free(bf_context_t *s, void *ptr)
+{
+ /* must test ptr otherwise equivalent to malloc(0) */
+ if (ptr)
+ bf_realloc(s, ptr, 0);
+}
+
+void bf_init(bf_context_t *s, bf_t *r);
+
+static inline void bf_delete(bf_t *r)
+{
+ bf_context_t *s = r->ctx;
+ /* we accept to delete a zeroed bf_t structure */
+ if (s && r->tab) {
+ bf_realloc(s, r->tab, 0);
+ }
+}
+
+static inline void bf_neg(bf_t *r)
+{
+ r->sign ^= 1;
+}
+
+static inline int bf_is_finite(const bf_t *a)
+{
+ return (a->expn < BF_EXP_INF);
+}
+
+static inline int bf_is_nan(const bf_t *a)
+{
+ return (a->expn == BF_EXP_NAN);
+}
+
+static inline int bf_is_zero(const bf_t *a)
+{
+ return (a->expn == BF_EXP_ZERO);
+}
+
+static inline void bf_memcpy(bf_t *r, const bf_t *a)
+{
+ *r = *a;
+}
+
+int bf_set_ui(bf_t *r, uint64_t a);
+int bf_set_si(bf_t *r, int64_t a);
+void bf_set_nan(bf_t *r);
+void bf_set_zero(bf_t *r, int is_neg);
+void bf_set_inf(bf_t *r, int is_neg);
+int bf_set(bf_t *r, const bf_t *a);
+void bf_move(bf_t *r, bf_t *a);
+int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
+int bf_set_float64(bf_t *a, double d);
+
+int bf_cmpu(const bf_t *a, const bf_t *b);
+int bf_cmp_full(const bf_t *a, const bf_t *b);
+int bf_cmp(const bf_t *a, const bf_t *b);
+static inline int bf_cmp_eq(const bf_t *a, const bf_t *b)
+{
+ return bf_cmp(a, b) == 0;
+}
+
+static inline int bf_cmp_le(const bf_t *a, const bf_t *b)
+{
+ return bf_cmp(a, b) <= 0;
+}
+
+static inline int bf_cmp_lt(const bf_t *a, const bf_t *b)
+{
+ return bf_cmp(a, b) < 0;
+}
+
+int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
+int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
+int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
+int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
+int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
+int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags);
+int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
+int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
+#define BF_DIVREM_EUCLIDIAN BF_RNDF
+int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
+ limb_t prec, bf_flags_t flags, int rnd_mode);
+int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode);
+int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode);
+/* round to integer with infinite precision */
+int bf_rint(bf_t *r, int rnd_mode);
+int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
+int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
+int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+slimb_t bf_get_exp_min(const bf_t *a);
+int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
+int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
+int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
+
+/* additional flags for bf_atof */
+/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
+#define BF_ATOF_NO_HEX (1 << 16)
+/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
+#define BF_ATOF_BIN_OCT (1 << 17)
+/* Do not parse NaN or Inf */
+#define BF_ATOF_NO_NAN_INF (1 << 18)
+/* return the exponent separately */
+#define BF_ATOF_EXPONENT (1 << 19)
+
+int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags);
+/* this version accepts prec = BF_PREC_INF and returns the radix
+ exponent */
+int bf_atof2(bf_t *r, slimb_t *pexponent,
+ const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags);
+int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
+ slimb_t expn, limb_t prec, bf_flags_t flags);
+
+
+/* Conversion of floating point number to string. Return a null
+ terminated string or NULL if memory error. *plen contains its
+ length if plen != NULL. The exponent letter is "e" for base 10,
+ "p" for bases 2, 8, 16 with a binary exponent and "@" for the other
+ bases. */
+
+#define BF_FTOA_FORMAT_MASK (3 << 16)
+
+/* fixed format: prec significant digits rounded with (flags &
+ BF_RND_MASK). Exponential notation is used if too many zeros are
+ needed.*/
+#define BF_FTOA_FORMAT_FIXED (0 << 16)
+/* fractional format: prec digits after the decimal point rounded with
+ (flags & BF_RND_MASK) */
+#define BF_FTOA_FORMAT_FRAC (1 << 16)
+/* free format:
+
+ For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
+ number of digits to represent 'a'. The precision and the rounding
+ mode are ignored.
+
+ For the non binary radices with bf_ftoa(): use as many digits as
+ necessary so that bf_atof() return the same number when using
+ precision 'prec', rounding to nearest and the subnormal
+ configuration of 'flags'. The result is meaningful only if 'a' is
+ already rounded to 'prec' bits. If the subnormal flag is set, the
+ exponent in 'flags' must also be set to the desired exponent range.
+*/
+#define BF_FTOA_FORMAT_FREE (2 << 16)
+/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
+ (takes more computation time). Identical to BF_FTOA_FORMAT_FREE for
+ binary radices with bf_ftoa() and for bfdec_ftoa(). */
+#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
+
+/* force exponential notation for fixed or free format */
+#define BF_FTOA_FORCE_EXP (1 << 20)
+/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
+ base 2 if non zero value */
+#define BF_FTOA_ADD_PREFIX (1 << 21)
+/* return "Infinity" instead of "Inf" and add a "+" for positive
+ exponents */
+#define BF_FTOA_JS_QUIRKS (1 << 22)
+
+char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
+ bf_flags_t flags);
+
+/* modulo 2^n instead of saturation. NaN and infinity return 0 */
+#define BF_GET_INT_MOD (1 << 0)
+int bf_get_int32(int *pres, const bf_t *a, int flags);
+int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
+int bf_get_uint64(uint64_t *pres, const bf_t *a);
+
+/* the following functions are exported for testing only. */
+void mp_print_str(const char *str, const limb_t *tab, limb_t n);
+void bf_print_str(const char *str, const bf_t *a);
+int bf_resize(bf_t *r, limb_t len);
+int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
+int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
+int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
+slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
+ int is_ceil1);
+int mp_mul(bf_context_t *s, limb_t *result,
+ const limb_t *op1, limb_t op1_size,
+ const limb_t *op2, limb_t op2_size);
+limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
+ limb_t n, limb_t carry);
+limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
+int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
+int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n);
+limb_t bf_isqrt(limb_t a);
+
+/* transcendental functions */
+int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
+int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
+int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
+int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
+int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
+ limb_t prec, bf_flags_t flags);
+int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+
+/* decimal floating point */
+
+static inline void bfdec_init(bf_context_t *s, bfdec_t *r)
+{
+ bf_init(s, (bf_t *)r);
+}
+static inline void bfdec_delete(bfdec_t *r)
+{
+ bf_delete((bf_t *)r);
+}
+
+static inline void bfdec_neg(bfdec_t *r)
+{
+ r->sign ^= 1;
+}
+
+static inline int bfdec_is_finite(const bfdec_t *a)
+{
+ return (a->expn < BF_EXP_INF);
+}
+
+static inline int bfdec_is_nan(const bfdec_t *a)
+{
+ return (a->expn == BF_EXP_NAN);
+}
+
+static inline int bfdec_is_zero(const bfdec_t *a)
+{
+ return (a->expn == BF_EXP_ZERO);
+}
+
+static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a)
+{
+ bf_memcpy((bf_t *)r, (const bf_t *)a);
+}
+
+int bfdec_set_ui(bfdec_t *r, uint64_t a);
+int bfdec_set_si(bfdec_t *r, int64_t a);
+
+static inline void bfdec_set_nan(bfdec_t *r)
+{
+ bf_set_nan((bf_t *)r);
+}
+static inline void bfdec_set_zero(bfdec_t *r, int is_neg)
+{
+ bf_set_zero((bf_t *)r, is_neg);
+}
+static inline void bfdec_set_inf(bfdec_t *r, int is_neg)
+{
+ bf_set_inf((bf_t *)r, is_neg);
+}
+static inline int bfdec_set(bfdec_t *r, const bfdec_t *a)
+{
+ return bf_set((bf_t *)r, (bf_t *)a);
+}
+static inline void bfdec_move(bfdec_t *r, bfdec_t *a)
+{
+ bf_move((bf_t *)r, (bf_t *)a);
+}
+static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b)
+{
+ return bf_cmpu((const bf_t *)a, (const bf_t *)b);
+}
+static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b)
+{
+ return bf_cmp_full((const bf_t *)a, (const bf_t *)b);
+}
+static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b)
+{
+ return bf_cmp((const bf_t *)a, (const bf_t *)b);
+}
+static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b)
+{
+ return bfdec_cmp(a, b) == 0;
+}
+static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b)
+{
+ return bfdec_cmp(a, b) <= 0;
+}
+static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b)
+{
+ return bfdec_cmp(a, b) < 0;
+}
+
+int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags);
+int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags);
+int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags);
+int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags);
+int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags);
+int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags);
+int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
+ limb_t prec, bf_flags_t flags, int rnd_mode);
+int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode);
+int bfdec_rint(bfdec_t *r, int rnd_mode);
+int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags);
+int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
+int bfdec_get_int32(int *pres, const bfdec_t *a);
+int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b);
+
+char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags);
+int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
+ limb_t prec, bf_flags_t flags);
+
+/* the following functions are exported for testing only. */
+extern const limb_t mp_pow_dec[LIMB_DIGITS + 1];
+void bfdec_print_str(const char *str, const bfdec_t *a);
+static inline int bfdec_resize(bfdec_t *r, limb_t len)
+{
+ return bf_resize((bf_t *)r, len);
+}
+int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
+#endif /* LIBBF_H */
diff --git a/src/shared/quickjs/libregexp-opcode.h b/src/shared/quickjs/libregexp-opcode.h
index f90c23b34..f255e09f2 100644
--- a/src/shared/quickjs/libregexp-opcode.h
+++ b/src/shared/quickjs/libregexp-opcode.h
@@ -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
@@ -50,8 +50,7 @@ DEF(range32, 3) /* variable length */
DEF(lookahead, 5)
DEF(negative_lookahead, 5)
DEF(push_char_pos, 1) /* push the character position on the stack */
-DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character
- position */
+DEF(check_advance, 1) /* pop one stack element and check that it is different from the character position */
DEF(prev, 1) /* go to the previous char */
DEF(simple_greedy_quant, 17)
diff --git a/src/shared/quickjs/libregexp.c b/src/shared/quickjs/libregexp.c
index ad91f781a..4db042941 100644
--- a/src/shared/quickjs/libregexp.c
+++ b/src/shared/quickjs/libregexp.c
@@ -30,13 +30,11 @@
#include "cutils.h"
#include "libregexp.h"
+#include "libunicode.h"
/*
TODO:
- - Add full unicode canonicalize rules for character ranges (not
- really useful but needed for exact "ignorecase" compatibility).
-
- Add a lock step execution mode (=linear time execution guaranteed)
when the regular expression is "simple" i.e. no backreference nor
complicated lookahead. The opcodes are designed for this execution
@@ -69,7 +67,7 @@ typedef struct {
const uint8_t *buf_end;
const uint8_t *buf_start;
int re_flags;
- BOOL is_utf16;
+ BOOL is_unicode;
BOOL ignore_case;
BOOL dotall;
int capture_count;
@@ -103,6 +101,7 @@ static const REOpCode reopcode_info[REOP_COUNT] = {
#define RE_HEADER_FLAGS 0
#define RE_HEADER_CAPTURE_COUNT 1
#define RE_HEADER_STACK_SIZE 2
+#define RE_HEADER_BYTECODE_LEN 3
#define RE_HEADER_LEN 7
@@ -120,33 +119,6 @@ static int dbuf_insert(DynBuf *s, int pos, int len)
return 0;
}
-/* canonicalize with the specific JS regexp rules */
-static uint32_t lre_canonicalize(uint32_t c, BOOL is_utf16)
-{
- uint32_t res[LRE_CC_RES_LEN_MAX];
- int len;
- if (is_utf16) {
- if (likely(c < 128)) {
- if (c >= 'A' && c <= 'Z')
- c = c - 'A' + 'a';
- } else {
- lre_case_conv(res, c, 2);
- c = res[0];
- }
- } else {
- if (likely(c < 128)) {
- if (c >= 'a' && c <= 'z')
- c = c - 'a' + 'A';
- } else {
- /* legacy regexp: to upper case if single char >= 128 */
- len = lre_case_conv(res, c, FALSE);
- if (len == 1 && res[0] >= 128)
- c = res[0];
- }
- }
- return c;
-}
-
static const uint16_t char_range_d[] = {
1,
0x0030, 0x0039 + 1,
@@ -170,32 +142,6 @@ static const uint16_t char_range_s[] = {
0xFEFF, 0xFEFF + 1,
};
-BOOL lre_is_space(int c)
-{
- int i, n, low, high;
- n = (countof(char_range_s) - 1) / 2;
- for(i = 0; i < n; i++) {
- low = char_range_s[2 * i + 1];
- if (c < low)
- return FALSE;
- high = char_range_s[2 * i + 2];
- if (c < high)
- return TRUE;
- }
- return FALSE;
-}
-
-uint32_t const lre_id_start_table_ascii[4] = {
- /* $ A-Z _ a-z */
- 0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE
-};
-
-uint32_t const lre_id_continue_table_ascii[4] = {
- /* $ 0-9 A-Z _ a-z */
- 0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE
-};
-
-
static const uint16_t char_range_w[] = {
4,
0x0030, 0x0039 + 1,
@@ -215,7 +161,7 @@ typedef enum {
CHAR_RANGE_W,
} CharRangeEnum;
-static const uint16_t *char_range_table[] = {
+static const uint16_t * const char_range_table[] = {
char_range_d,
char_range_s,
char_range_w,
@@ -245,33 +191,8 @@ static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c)
return -1;
}
-static int cr_canonicalize(CharRange *cr)
-{
- CharRange a;
- uint32_t pt[2];
- int i, ret;
-
- cr_init(&a, cr->mem_opaque, lre_realloc);
- pt[0] = 'a';
- pt[1] = 'z' + 1;
- ret = cr_op(&a, cr->points, cr->len, pt, 2, CR_OP_INTER);
- if (ret)
- goto fail;
- /* convert to upper case */
- /* XXX: the generic unicode case would be much more complicated
- and not really useful */
- for(i = 0; i < a.len; i++) {
- a.points[i] += 'A' - 'a';
- }
- /* Note: for simplicity we keep the lower case ranges */
- ret = cr_union1(cr, a.points, a.len);
- fail:
- cr_free(&a);
- return ret;
-}
-
#ifdef DUMP_REOP
-static MAYBE_UNUSED void lre_dump_bytecode(const uint8_t *buf,
+static __maybe_unused void lre_dump_bytecode(const uint8_t *buf,
int buf_len)
{
int pos, len, opcode, bc_len, re_flags, i;
@@ -279,16 +200,16 @@ static MAYBE_UNUSED void lre_dump_bytecode(const uint8_t *buf,
assert(buf_len >= RE_HEADER_LEN);
- re_flags= buf[0];
- bc_len = get_u32(buf + 3);
+ re_flags = lre_get_flags(buf);
+ bc_len = get_u32(buf + RE_HEADER_BYTECODE_LEN);
assert(bc_len + RE_HEADER_LEN <= buf_len);
printf("flags: 0x%x capture_count=%d stack_size=%d\n",
- re_flags, buf[1], buf[2]);
+ re_flags, buf[RE_HEADER_CAPTURE_COUNT], buf[RE_HEADER_STACK_SIZE]);
if (re_flags & LRE_FLAG_NAMED_GROUPS) {
const char *p;
p = (char *)buf + RE_HEADER_LEN + bc_len;
printf("named groups: ");
- for(i = 1; i < buf[1]; i++) {
+ for(i = 1; i < buf[RE_HEADER_CAPTURE_COUNT]; i++) {
if (i != 1)
printf(",");
printf("<%s>", p);
@@ -335,7 +256,6 @@ static MAYBE_UNUSED void lre_dump_bytecode(const uint8_t *buf,
case REOP_loop:
case REOP_lookahead:
case REOP_negative_lookahead:
- case REOP_bne_char_pos:
val = get_u32(buf + pos + 1);
val += (pos + 5);
printf(" %u", val);
@@ -550,7 +470,7 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16)
}
c = (c << 4) | h;
}
- if (c >= 0xd800 && c < 0xdc00 &&
+ if (is_hi_surrogate(c) &&
allow_utf16 == 2 && p[0] == '\\' && p[1] == 'u') {
/* convert an escaped surrogate pair into a
unicode char */
@@ -561,9 +481,9 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16)
break;
c1 = (c1 << 4) | h;
}
- if (i == 4 && c1 >= 0xdc00 && c1 < 0xe000) {
+ if (i == 4 && is_lo_surrogate(c1)) {
p += 6;
- c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
+ c = from_surrogate(c, c1);
}
}
}
@@ -752,10 +672,10 @@ static int get_class_atom(REParseState *s, CharRange *cr,
if ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(((c >= '0' && c <= '9') || c == '_') &&
- inclass && !s->is_utf16)) { /* Annex B.1.4 */
+ inclass && !s->is_unicode)) { /* Annex B.1.4 */
c &= 0x1f;
p++;
- } else if (s->is_utf16) {
+ } else if (s->is_unicode) {
goto invalid_escape;
} else {
/* otherwise return '\' and 'c' */
@@ -766,7 +686,7 @@ static int get_class_atom(REParseState *s, CharRange *cr,
#ifdef CONFIG_ALL_UNICODE
case 'p':
case 'P':
- if (s->is_utf16) {
+ if (s->is_unicode) {
if (parse_unicode_property(s, cr, &p, (c == 'P')))
return -1;
c = CLASS_RANGE_BASE;
@@ -776,14 +696,14 @@ static int get_class_atom(REParseState *s, CharRange *cr,
#endif
default:
p--;
- ret = lre_parse_escape(&p, s->is_utf16 * 2);
+ ret = lre_parse_escape(&p, s->is_unicode * 2);
if (ret >= 0) {
c = ret;
} else {
if (ret == -2 && *p != '\0' && strchr("^$\\.*+?()[]{}|/", *p)) {
/* always valid to escape these characters */
goto normal_char;
- } else if (s->is_utf16) {
+ } else if (s->is_unicode) {
invalid_escape:
return re_parse_error(s, "invalid escape sequence in regular expression");
} else {
@@ -805,7 +725,7 @@ static int get_class_atom(REParseState *s, CharRange *cr,
/* normal char */
if (c >= 128) {
c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
- if ((unsigned)c > 0xffff && !s->is_utf16) {
+ if ((unsigned)c > 0xffff && !s->is_unicode) {
/* XXX: should handle non BMP-1 code points */
return re_parse_error(s, "malformed unicode char");
}
@@ -867,11 +787,13 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
cr_init(cr, s->opaque, lre_realloc);
p = *pp;
p++; /* skip '[' */
+
invert = FALSE;
if (*p == '^') {
p++;
invert = TRUE;
}
+
for(;;) {
if (*p == ']')
break;
@@ -881,7 +803,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
if (*p == '-' && p[1] != ']') {
const uint8_t *p0 = p + 1;
if (c1 >= CLASS_RANGE_BASE) {
- if (s->is_utf16) {
+ if (s->is_unicode) {
cr_free(cr1);
goto invalid_class_range;
}
@@ -893,7 +815,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
goto fail;
if (c2 >= CLASS_RANGE_BASE) {
cr_free(cr1);
- if (s->is_utf16) {
+ if (s->is_unicode) {
goto invalid_class_range;
}
/* Annex B: match '-' character */
@@ -922,7 +844,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
}
}
if (s->ignore_case) {
- if (cr_canonicalize(cr))
+ if (cr_regexp_canonicalize(cr, s->is_unicode))
goto memory_error;
}
if (invert) {
@@ -943,22 +865,17 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
}
/* Return:
- 1 if the opcodes in bc_buf[] always advance the character pointer.
- 0 if the character pointer may not be advanced.
- -1 if the code may depend on side effects of its previous execution (backreference)
+ - true if the opcodes may not advance the char pointer
+ - false if the opcodes always advance the char pointer
*/
-static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
+static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len)
{
- int pos, opcode, ret, len, i;
- uint32_t val, last;
- BOOL has_back_reference;
- uint8_t capture_bitmap[CAPTURE_COUNT_MAX];
+ int pos, opcode, len;
+ uint32_t val;
+ BOOL ret;
- ret = -2; /* not known yet */
+ ret = TRUE;
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;
@@ -976,8 +893,7 @@ static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
case REOP_dot:
case REOP_any:
simple_char:
- if (ret == -2)
- ret = 1;
+ ret = FALSE;
break;
case REOP_line_start:
case REOP_line_end:
@@ -991,41 +907,16 @@ static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
break;
case REOP_save_start:
case REOP_save_end:
- val = bc_buf[pos + 1];
- capture_bitmap[val] |= 1;
- break;
case REOP_save_reset:
- {
- val = bc_buf[pos + 1];
- last = bc_buf[pos + 2];
- while (val < last)
- capture_bitmap[val++] |= 1;
- }
- break;
case REOP_back_reference:
case REOP_backward_back_reference:
- val = bc_buf[pos + 1];
- capture_bitmap[val] |= 2;
- has_back_reference = TRUE;
break;
default:
- /* safe behvior: we cannot predict the outcome */
- if (ret == -2)
- ret = 0;
- break;
+ /* safe behavior: we cannot predict the outcome */
+ return TRUE;
}
pos += len;
}
- if (has_back_reference) {
- /* check if there is back reference which references a capture
- made in the some code */
- for(i = 0; i < CAPTURE_COUNT_MAX; i++) {
- if (capture_bitmap[i] == 3)
- return -1;
- }
- }
- if (ret == -2)
- ret = 0;
return ret;
}
@@ -1071,11 +962,10 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len)
}
/* '*pp' is the first char after '<' */
-static int re_parse_group_name(char *buf, int buf_size,
- const uint8_t **pp, BOOL is_utf16)
+static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp)
{
- const uint8_t *p;
- uint32_t c;
+ const uint8_t *p, *p1;
+ uint32_t c, d;
char *q;
p = *pp;
@@ -1086,11 +976,18 @@ static int re_parse_group_name(char *buf, int buf_size,
p++;
if (*p != 'u')
return -1;
- c = lre_parse_escape(&p, is_utf16 * 2);
+ c = lre_parse_escape(&p, 2); // accept surrogate pairs
} else if (c == '>') {
break;
} else if (c >= 128) {
c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ if (is_hi_surrogate(c)) {
+ d = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
+ if (is_lo_surrogate(d)) {
+ c = from_surrogate(c, d);
+ p = p1;
+ }
+ }
} else {
p++;
}
@@ -1140,8 +1037,7 @@ static int re_parse_captures(REParseState *s, int *phas_named_captures,
/* potential named capture */
if (capture_name) {
p += 3;
- if (re_parse_group_name(name, sizeof(name), &p,
- s->is_utf16) == 0) {
+ if (re_parse_group_name(name, sizeof(name), &p) == 0) {
if (!strcmp(name, capture_name))
return capture_index;
}
@@ -1196,9 +1092,10 @@ static int find_group_name(REParseState *s, const char *name)
size_t len, name_len;
int capture_index;
- name_len = strlen(name);
p = (char *)s->group_names.buf;
+ if (!p) return -1;
buf_end = (char *)s->group_names.buf + s->group_names.size;
+ name_len = strlen(name);
capture_index = 1;
while (p < buf_end) {
len = strlen(p);
@@ -1243,7 +1140,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
re_emit_op(s, REOP_prev);
break;
case '{':
- if (s->is_utf16) {
+ if (s->is_unicode) {
return re_parse_error(s, "syntax error");
} else if (!is_digit(p[1])) {
/* Annex B: we accept '{' not followed by digits as a
@@ -1295,7 +1192,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
lookahead:
/* Annex B allows lookahead to be used as an atom for
the quantifiers */
- if (!s->is_utf16 && !is_backward_lookahead) {
+ if (!s->is_unicode && !is_backward_lookahead) {
last_atom_start = s->byte_code.size;
last_capture_count = s->capture_count;
}
@@ -1314,7 +1211,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
} else if (p[2] == '<') {
p += 3;
if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf),
- &p, s->is_utf16)) {
+ &p)) {
return re_parse_error(s, "invalid group name");
}
if (find_group_name(s, s->u.tmp_buf) > 0) {
@@ -1371,15 +1268,15 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
/* annex B: we tolerate invalid group names in non
unicode mode if there is no named capture
definition */
- if (s->is_utf16 || re_has_named_captures(s))
+ if (s->is_unicode || re_has_named_captures(s))
return re_parse_error(s, "expecting group name");
else
goto parse_class_atom;
}
p1 += 3;
if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf),
- &p1, s->is_utf16)) {
- if (s->is_utf16 || re_has_named_captures(s))
+ &p1)) {
+ if (s->is_unicode || re_has_named_captures(s))
return re_parse_error(s, "invalid group name");
else
goto parse_class_atom;
@@ -1390,7 +1287,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
after (inefficient, but hopefully not common */
c = re_parse_captures(s, &dummy_res, s->u.tmp_buf);
if (c < 0) {
- if (s->is_utf16 || re_has_named_captures(s))
+ if (s->is_unicode || re_has_named_captures(s))
return re_parse_error(s, "group name not defined");
else
goto parse_class_atom;
@@ -1402,7 +1299,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
case '0':
p += 2;
c = 0;
- if (s->is_utf16) {
+ if (s->is_unicode) {
if (is_digit(*p)) {
return re_parse_error(s, "invalid decimal escape in regular expression");
}
@@ -1424,7 +1321,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
c = parse_digits(&p, FALSE);
if (c < 0 || (c >= s->capture_count && c >= re_count_captures(s))) {
- if (!s->is_utf16) {
+ if (!s->is_unicode) {
/* Annex B.1.4: accept legacy octal */
p = q;
if (*p <= '7') {
@@ -1466,13 +1363,13 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
break;
case ']':
case '}':
- if (s->is_utf16)
+ if (s->is_unicode)
return re_parse_error(s, "syntax error");
goto parse_class_atom;
default:
parse_class_atom:
c = get_class_atom(s, cr, &p, FALSE);
- if (c < 0)
+ if ((int)c < 0)
return -1;
normal_char:
last_atom_start = s->byte_code.size;
@@ -1488,7 +1385,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
return -1;
} else {
if (s->ignore_case)
- c = lre_canonicalize(c, s->is_utf16);
+ c = lre_canonicalize(c, s->is_unicode);
if (c <= 0xffff)
re_emit_op_u16(s, REOP_char, c);
else
@@ -1524,7 +1421,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
/* As an extension (see ES6 annex B), we accept '{' not
followed by digits as a normal atom */
if (!is_digit(p[1])) {
- if (s->is_utf16)
+ if (s->is_unicode)
goto invalid_quant_count;
break;
}
@@ -1543,7 +1440,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
quant_max = INT32_MAX; /* infinity */
}
}
- if (*p != '}' && !s->is_utf16) {
+ if (*p != '}' && !s->is_unicode) {
/* Annex B: normal atom if invalid '{' syntax */
p = p1;
break;
@@ -1591,8 +1488,12 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
if (dbuf_error(&s->byte_code))
goto out_of_memory;
- add_zero_advance_check = (re_check_advance(s->byte_code.buf + last_atom_start,
- s->byte_code.size - last_atom_start) == 0);
+ /* the spec tells that if there is no advance when
+ running the atom after the first quant_min times,
+ then there is no match. We remove this test when we
+ are sure the atom always advances the position. */
+ add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
+ s->byte_code.size - last_atom_start);
} else {
add_zero_advance_check = FALSE;
}
@@ -1612,38 +1513,34 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
}
if (quant_max == 0) {
s->byte_code.size = last_atom_start;
- } else if (quant_max == 1) {
- if (dbuf_insert(&s->byte_code, last_atom_start, 5))
- goto out_of_memory;
- s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
- greedy;
- put_u32(s->byte_code.buf + last_atom_start + 1, len);
- } else if (quant_max == INT32_MAX) {
+ } else if (quant_max == 1 || quant_max == INT32_MAX) {
+ BOOL has_goto = (quant_max == INT32_MAX);
if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check))
goto out_of_memory;
s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
greedy;
put_u32(s->byte_code.buf + last_atom_start + 1,
- len + 5 + add_zero_advance_check);
+ len + 5 * has_goto + add_zero_advance_check * 2);
if (add_zero_advance_check) {
- /* avoid infinite loop by stoping the
- recursion if no advance was made in the
- 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);
- } else {
- re_emit_goto(s, REOP_goto, last_atom_start);
+ re_emit_op(s, REOP_check_advance);
}
+ if (has_goto)
+ re_emit_goto(s, REOP_goto, last_atom_start);
} else {
- if (dbuf_insert(&s->byte_code, last_atom_start, 10))
+ if (dbuf_insert(&s->byte_code, last_atom_start, 10 + add_zero_advance_check))
goto out_of_memory;
pos = last_atom_start;
s->byte_code.buf[pos++] = REOP_push_i32;
put_u32(s->byte_code.buf + pos, quant_max);
pos += 4;
s->byte_code.buf[pos++] = REOP_split_goto_first + greedy;
- put_u32(s->byte_code.buf + pos, len + 5);
+ put_u32(s->byte_code.buf + pos, len + 5 + add_zero_advance_check * 2);
+ pos += 4;
+ if (add_zero_advance_check) {
+ s->byte_code.buf[pos++] = REOP_push_char_pos;
+ re_emit_op(s, REOP_check_advance);
+ }
re_emit_goto(s, REOP_loop, last_atom_start + 5);
re_emit_op(s, REOP_drop);
}
@@ -1667,22 +1564,25 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
if (quant_max == INT32_MAX) {
pos = s->byte_code.size;
re_emit_op_u32(s, REOP_split_goto_first + greedy,
- len + 5 + add_zero_advance_check);
+ len + 5 + add_zero_advance_check * 2);
if (add_zero_advance_check)
re_emit_op(s, REOP_push_char_pos);
/* copy the atom */
dbuf_put_self(&s->byte_code, last_atom_start, len);
if (add_zero_advance_check)
- re_emit_goto(s, REOP_bne_char_pos, pos);
- else
- re_emit_goto(s, REOP_goto, pos);
+ re_emit_op(s, REOP_check_advance);
+ re_emit_goto(s, REOP_goto, pos);
} else if (quant_max > quant_min) {
re_emit_op_u32(s, REOP_push_i32, quant_max - quant_min);
pos = s->byte_code.size;
- re_emit_op_u32(s, REOP_split_goto_first + greedy, len + 5);
+ re_emit_op_u32(s, REOP_split_goto_first + greedy,
+ len + 5 + add_zero_advance_check * 2);
+ if (add_zero_advance_check)
+ re_emit_op(s, REOP_push_char_pos);
/* copy the atom */
dbuf_put_self(&s->byte_code, last_atom_start, len);
-
+ if (add_zero_advance_check)
+ re_emit_op(s, REOP_check_advance);
re_emit_goto(s, REOP_loop, pos);
re_emit_op(s, REOP_drop);
}
@@ -1796,7 +1696,7 @@ static int compute_stack_size(const uint8_t *bc_buf, int bc_buf_len)
}
break;
case REOP_drop:
- case REOP_bne_char_pos:
+ case REOP_check_advance:
assert(stack_size > 0);
stack_size--;
break;
@@ -1832,7 +1732,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
s->buf_end = s->buf_ptr + buf_len;
s->buf_start = s->buf_ptr;
s->re_flags = re_flags;
- s->is_utf16 = ((re_flags & LRE_FLAG_UTF16) != 0);
+ s->is_unicode = ((re_flags & LRE_FLAG_UNICODE) != 0);
is_sticky = ((re_flags & LRE_FLAG_STICKY) != 0);
s->ignore_case = ((re_flags & LRE_FLAG_IGNORECASE) != 0);
s->dotall = ((re_flags & LRE_FLAG_DOTALL) != 0);
@@ -1890,7 +1790,8 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
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);
+ put_u32(s->byte_code.buf + RE_HEADER_BYTECODE_LEN,
+ s->byte_code.size - RE_HEADER_LEN);
/* add the named groups if needed */
if (s->group_names.size > (s->capture_count - 1)) {
@@ -1921,93 +1822,86 @@ static BOOL is_word_char(uint32_t c)
(c == '_'));
}
-#define GET_CHAR(c, cptr, cbuf_end) \
+#define GET_CHAR(c, cptr, cbuf_end, cbuf_type) \
do { \
if (cbuf_type == 0) { \
- (c) = *(cptr)++; \
+ c = *cptr++; \
} else { \
- uint32_t __c1; \
- (c) = *(uint16_t *)(cptr); \
- (cptr) += 2; \
- if ((c) >= 0xd800 && (c) < 0xdc00 && \
- cbuf_type == 2 && (cptr) < (cbuf_end)) { \
- __c1 = *(uint16_t *)(cptr); \
- if (__c1 >= 0xdc00 && __c1 < 0xe000) { \
- (c) = ((((c) & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
- (cptr) += 2; \
+ const uint16_t *_p = (const uint16_t *)cptr; \
+ const uint16_t *_end = (const uint16_t *)cbuf_end; \
+ c = *_p++; \
+ if (is_hi_surrogate(c) && cbuf_type == 2) { \
+ if (_p < _end && is_lo_surrogate(*_p)) { \
+ c = from_surrogate(c, *_p++); \
} \
} \
+ cptr = (const void *)_p; \
} \
} while (0)
-#define PEEK_CHAR(c, cptr, cbuf_end) \
- do { \
- if (cbuf_type == 0) { \
- (c) = (cptr)[0]; \
- } else { \
- uint32_t __c1; \
- (c) = ((uint16_t *)(cptr))[0]; \
- if ((c) >= 0xd800 && (c) < 0xdc00 && \
- cbuf_type == 2 && ((cptr) + 2) < (cbuf_end)) { \
- __c1 = ((uint16_t *)(cptr))[1]; \
- if (__c1 >= 0xdc00 && __c1 < 0xe000) { \
- (c) = ((((c) & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
+#define PEEK_CHAR(c, cptr, cbuf_end, cbuf_type) \
+ do { \
+ if (cbuf_type == 0) { \
+ c = cptr[0]; \
+ } else { \
+ const uint16_t *_p = (const uint16_t *)cptr; \
+ const uint16_t *_end = (const uint16_t *)cbuf_end; \
+ c = *_p++; \
+ if (is_hi_surrogate(c) && cbuf_type == 2) { \
+ if (_p < _end && is_lo_surrogate(*_p)) { \
+ c = from_surrogate(c, *_p); \
} \
} \
- } \
+ } \
} while (0)
-#define PEEK_PREV_CHAR(c, cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
- (c) = (cptr)[-1]; \
- } else { \
- uint32_t __c1; \
- (c) = ((uint16_t *)(cptr))[-1]; \
- if ((c) >= 0xdc00 && (c) < 0xe000 && \
- cbuf_type == 2 && ((cptr) - 4) >= (cbuf_start)) { \
- __c1 = ((uint16_t *)(cptr))[-2]; \
- if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \
- (c) = (((__c1 & 0x3ff) << 10) | ((c) & 0x3ff)) + 0x10000; \
+#define PEEK_PREV_CHAR(c, cptr, cbuf_start, cbuf_type) \
+ do { \
+ if (cbuf_type == 0) { \
+ c = cptr[-1]; \
+ } else { \
+ const uint16_t *_p = (const uint16_t *)cptr - 1; \
+ const uint16_t *_start = (const uint16_t *)cbuf_start; \
+ c = *_p; \
+ if (is_lo_surrogate(c) && cbuf_type == 2) { \
+ if (_p > _start && is_hi_surrogate(_p[-1])) { \
+ c = from_surrogate(*--_p, c); \
} \
} \
} \
} while (0)
-#define GET_PREV_CHAR(c, cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
- (cptr)--; \
- (c) = (cptr)[0]; \
- } else { \
- uint32_t __c1; \
- (cptr) -= 2; \
- (c) = ((uint16_t *)(cptr))[0]; \
- if ((c) >= 0xdc00 && (c) < 0xe000 && \
- cbuf_type == 2 && (cptr) > (cbuf_start)) { \
- __c1 = ((uint16_t *)(cptr))[-1]; \
- if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \
- (cptr) -= 2; \
- (c) = (((__c1 & 0x3ff) << 10) | ((c) & 0x3ff)) + 0x10000; \
+#define GET_PREV_CHAR(c, cptr, cbuf_start, cbuf_type) \
+ do { \
+ if (cbuf_type == 0) { \
+ cptr--; \
+ c = cptr[0]; \
+ } else { \
+ const uint16_t *_p = (const uint16_t *)cptr - 1; \
+ const uint16_t *_start = (const uint16_t *)cbuf_start; \
+ c = *_p; \
+ if (is_lo_surrogate(c) && cbuf_type == 2) { \
+ if (_p > _start && is_hi_surrogate(_p[-1])) { \
+ c = from_surrogate(*--_p, c); \
} \
} \
+ cptr = (const void *)_p; \
} \
} while (0)
-#define PREV_CHAR(cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
- (cptr)--; \
- } else { \
- (cptr) -= 2; \
- if (cbuf_type == 2) { \
- c = ((uint16_t *)(cptr))[0]; \
- if (c >= 0xdc00 && c < 0xe000 && (cptr) > (cbuf_start)) { \
- c = ((uint16_t *)(cptr))[-1]; \
- if (c >= 0xd800 && c < 0xdc00) \
- (cptr) -= 2; \
+#define PREV_CHAR(cptr, cbuf_start, cbuf_type) \
+ do { \
+ if (cbuf_type == 0) { \
+ cptr--; \
+ } else { \
+ const uint16_t *_p = (const uint16_t *)cptr - 1; \
+ const uint16_t *_start = (const uint16_t *)cbuf_start; \
+ if (is_lo_surrogate(*_p) && cbuf_type == 2) { \
+ if (_p > _start && is_hi_surrogate(_p[-1])) { \
+ --_p; \
} \
} \
+ cptr = (const void *)_p; \
} \
} while (0)
@@ -2038,7 +1932,7 @@ typedef struct {
int stack_size_max;
BOOL multi_line;
BOOL ignore_case;
- BOOL is_utf16;
+ BOOL is_unicode;
void *opaque; /* used for stack overflow check */
size_t state_size;
@@ -2049,7 +1943,7 @@ typedef struct {
static int push_state(REExecContext *s,
uint8_t **capture,
- const StackInt *stack, size_t stack_len,
+ StackInt *stack, size_t stack_len,
const uint8_t *pc, const uint8_t *cptr,
REExecStateEnum type, size_t count)
{
@@ -2147,7 +2041,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
/* go backward */
char_count = get_u32(pc + 12);
for(i = 0; i < char_count; i++) {
- PREV_CHAR(cptr, s->cbuf);
+ PREV_CHAR(cptr, s->cbuf, cbuf_type);
}
pc = (pc + 16) + (int)get_u32(pc);
rs->cptr = cptr;
@@ -2182,9 +2076,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
test_char:
if (cptr >= cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
if (s->ignore_case) {
- c = lre_canonicalize(c, s->is_utf16);
+ c = lre_canonicalize(c, s->is_unicode);
}
if (val != c)
goto no_match;
@@ -2229,7 +2123,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
break;
if (!s->multi_line)
goto no_match;
- PEEK_PREV_CHAR(c, cptr, s->cbuf);
+ PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
if (!is_line_terminator(c))
goto no_match;
break;
@@ -2238,21 +2132,21 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
break;
if (!s->multi_line)
goto no_match;
- PEEK_CHAR(c, cptr, cbuf_end);
+ PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
if (!is_line_terminator(c))
goto no_match;
break;
case REOP_dot:
if (cptr == cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
if (is_line_terminator(c))
goto no_match;
break;
case REOP_any:
if (cptr == cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
break;
case REOP_save_start:
case REOP_save_end:
@@ -2292,11 +2186,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
case REOP_push_char_pos:
stack[stack_len++] = (uintptr_t)cptr;
break;
- case REOP_bne_char_pos:
- val = get_u32(pc);
- pc += 4;
- if (stack[--stack_len] != (uintptr_t)cptr)
- pc += (int)val;
+ case REOP_check_advance:
+ if (stack[--stack_len] == (uintptr_t)cptr)
+ goto no_match;
break;
case REOP_word_boundary:
case REOP_not_word_boundary:
@@ -2306,14 +2198,14 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
if (cptr == s->cbuf) {
v1 = FALSE;
} else {
- PEEK_PREV_CHAR(c, cptr, s->cbuf);
+ PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
v1 = is_word_char(c);
}
/* current char */
if (cptr >= cbuf_end) {
v2 = FALSE;
} else {
- PEEK_CHAR(c, cptr, cbuf_end);
+ PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
v2 = is_word_char(c);
}
if (v1 ^ v2 ^ (REOP_not_word_boundary - opcode))
@@ -2338,11 +2230,11 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
while (cptr1 < cptr1_end) {
if (cptr >= cbuf_end)
goto no_match;
- GET_CHAR(c1, cptr1, cptr1_end);
- GET_CHAR(c2, cptr, cbuf_end);
+ GET_CHAR(c1, cptr1, cptr1_end, cbuf_type);
+ GET_CHAR(c2, cptr, cbuf_end, cbuf_type);
if (s->ignore_case) {
- c1 = lre_canonicalize(c1, s->is_utf16);
- c2 = lre_canonicalize(c2, s->is_utf16);
+ c1 = lre_canonicalize(c1, s->is_unicode);
+ c2 = lre_canonicalize(c2, s->is_unicode);
}
if (c1 != c2)
goto no_match;
@@ -2352,11 +2244,11 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
while (cptr1 > cptr1_start) {
if (cptr == s->cbuf)
goto no_match;
- GET_PREV_CHAR(c1, cptr1, cptr1_start);
- GET_PREV_CHAR(c2, cptr, s->cbuf);
+ GET_PREV_CHAR(c1, cptr1, cptr1_start, cbuf_type);
+ GET_PREV_CHAR(c2, cptr, s->cbuf, cbuf_type);
if (s->ignore_case) {
- c1 = lre_canonicalize(c1, s->is_utf16);
- c2 = lre_canonicalize(c2, s->is_utf16);
+ c1 = lre_canonicalize(c1, s->is_unicode);
+ c2 = lre_canonicalize(c2, s->is_unicode);
}
if (c1 != c2)
goto no_match;
@@ -2373,9 +2265,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
pc += 2;
if (cptr >= cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
if (s->ignore_case) {
- c = lre_canonicalize(c, s->is_utf16);
+ c = lre_canonicalize(c, s->is_unicode);
}
idx_min = 0;
low = get_u16(pc + 0 * 4);
@@ -2413,9 +2305,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
pc += 2;
if (cptr >= cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
if (s->ignore_case) {
- c = lre_canonicalize(c, s->is_utf16);
+ c = lre_canonicalize(c, s->is_unicode);
}
idx_min = 0;
low = get_u32(pc + 0 * 8);
@@ -2445,7 +2337,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
/* go to the previous char */
if (cptr == s->cbuf)
goto no_match;
- PREV_CHAR(cptr, s->cbuf);
+ PREV_CHAR(cptr, s->cbuf, cbuf_type);
break;
case REOP_simple_greedy_quant:
{
@@ -2504,16 +2396,16 @@ int lre_exec(uint8_t **capture,
int re_flags, i, alloca_size, ret;
StackInt *stack_buf;
- re_flags = bc_buf[RE_HEADER_FLAGS];
+ re_flags = lre_get_flags(bc_buf);
s->multi_line = (re_flags & LRE_FLAG_MULTILINE) != 0;
s->ignore_case = (re_flags & LRE_FLAG_IGNORECASE) != 0;
- s->is_utf16 = (re_flags & LRE_FLAG_UTF16) != 0;
+ s->is_unicode = (re_flags & LRE_FLAG_UNICODE) != 0;
s->capture_count = bc_buf[RE_HEADER_CAPTURE_COUNT];
s->stack_size_max = bc_buf[RE_HEADER_STACK_SIZE];
s->cbuf = cbuf;
s->cbuf_end = cbuf + (clen << cbuf_type);
s->cbuf_type = cbuf_type;
- if (s->cbuf_type == 1 && s->is_utf16)
+ if (s->cbuf_type == 1 && s->is_unicode)
s->cbuf_type = 2;
s->opaque = opaque;
@@ -2551,8 +2443,8 @@ const char *lre_get_groupnames(const uint8_t *bc_buf)
uint32_t re_bytecode_len;
if ((lre_get_flags(bc_buf) & LRE_FLAG_NAMED_GROUPS) == 0)
return NULL;
- re_bytecode_len = get_u32(bc_buf + 3);
- return (const char *)(bc_buf + 7 + re_bytecode_len);
+ re_bytecode_len = get_u32(bc_buf + RE_HEADER_BYTECODE_LEN);
+ return (const char *)(bc_buf + RE_HEADER_LEN + re_bytecode_len);
}
#ifdef TEST
@@ -2569,25 +2461,26 @@ void *lre_realloc(void *opaque, void *ptr, size_t size)
int main(int argc, char **argv)
{
- int len, ret, i;
+ int len, flags, ret, i;
uint8_t *bc;
char error_msg[64];
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);
+ if (argc < 4) {
+ printf("usage: %s regexp flags input\n", argv[0]);
+ return 1;
}
+ flags = atoi(argv[2]);
bc = lre_compile(&len, error_msg, sizeof(error_msg), argv[1],
- strlen(argv[1]), 0, NULL);
+ strlen(argv[1]), flags, NULL);
if (!bc) {
fprintf(stderr, "error: %s\n", error_msg);
exit(1);
}
- input = argv[2];
+ input = argv[3];
input_len = strlen(input);
ret = lre_exec(capture, bc, (uint8_t *)input, 0, input_len, 0, NULL);
diff --git a/src/shared/quickjs/libregexp.h b/src/shared/quickjs/libregexp.h
index 9aedb7e93..7af7ece0f 100644
--- a/src/shared/quickjs/libregexp.h
+++ b/src/shared/quickjs/libregexp.h
@@ -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
@@ -25,18 +25,15 @@
#define LIBREGEXP_H
#include <stddef.h>
-
-#include "libunicode.h"
-
-#define LRE_BOOL int /* for documentation purposes */
+#include <stdint.h>
#define LRE_FLAG_GLOBAL (1 << 0)
#define LRE_FLAG_IGNORECASE (1 << 1)
#define LRE_FLAG_MULTILINE (1 << 2)
#define LRE_FLAG_DOTALL (1 << 3)
-#define LRE_FLAG_UTF16 (1 << 4)
+#define LRE_FLAG_UNICODE (1 << 4)
#define LRE_FLAG_STICKY (1 << 5)
-
+#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
@@ -50,43 +47,9 @@ int lre_exec(uint8_t **capture,
int cbuf_type, void *opaque);
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
-LRE_BOOL lre_is_space(int c);
-/* must be provided by the user */
-LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
+/* must be provided by the user, return non zero if overflow */
+int lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
-/* JS identifier test */
-extern uint32_t const lre_id_start_table_ascii[4];
-extern uint32_t const lre_id_continue_table_ascii[4];
-
-static inline int lre_js_is_ident_first(int c)
-{
- if ((uint32_t)c < 128) {
- return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
- } else {
-#ifdef CONFIG_ALL_UNICODE
- return lre_is_id_start(c);
-#else
- return !lre_is_space(c);
-#endif
- }
-}
-
-static inline int lre_js_is_ident_next(int c)
-{
- if ((uint32_t)c < 128) {
- return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
- } else {
- /* ZWNJ and ZWJ are accepted in identifiers */
-#ifdef CONFIG_ALL_UNICODE
- return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
-#else
- return !lre_is_space(c) || c == 0x200C || c == 0x200D;
-#endif
- }
-}
-
-#undef LRE_BOOL
-
#endif /* LIBREGEXP_H */
diff --git a/src/shared/quickjs/libunicode-table.h b/src/shared/quickjs/libunicode-table.h
index 1727525fb..72d495e78 100644
--- a/src/shared/quickjs/libunicode-table.h
+++ b/src/shared/quickjs/libunicode-table.h
@@ -160,40 +160,45 @@ static const uint16_t case_conv_ext[58] = {
0x006b, 0x00e5,
};
-static const uint8_t unicode_prop_Cased1_table[188] = {
+static const uint8_t unicode_prop_Cased1_table[196] = {
0x40, 0xa9, 0x80, 0x8e, 0x80, 0xfc, 0x80, 0xd3,
0x80, 0x8c, 0x80, 0x8d, 0x81, 0x8d, 0x02, 0x80,
0xe1, 0x80, 0x91, 0x85, 0x9a, 0x01, 0x00, 0x01,
0x11, 0x00, 0x01, 0x04, 0x08, 0x01, 0x08, 0x30,
0x08, 0x01, 0x15, 0x20, 0x00, 0x39, 0x99, 0x31,
0x9d, 0x84, 0x40, 0x94, 0x80, 0xd6, 0x82, 0xa6,
- 0x80, 0x41, 0x62, 0x80, 0xa6, 0x80, 0x57, 0x76,
- 0xf8, 0x02, 0x80, 0x8f, 0x80, 0xb0, 0x40, 0xdb,
- 0x08, 0x80, 0x41, 0xd0, 0x80, 0x8c, 0x80, 0x8f,
- 0x8c, 0xe4, 0x03, 0x01, 0x89, 0x00, 0x14, 0x28,
- 0x10, 0x11, 0x02, 0x01, 0x18, 0x0b, 0x24, 0x4b,
- 0x26, 0x01, 0x01, 0x86, 0xe5, 0x80, 0x60, 0x79,
- 0xb6, 0x81, 0x40, 0x91, 0x81, 0xbd, 0x88, 0x94,
- 0x05, 0x80, 0x98, 0x80, 0xa2, 0x00, 0x80, 0xa1,
- 0x82, 0x43, 0x34, 0xa2, 0x06, 0x80, 0x8c, 0x60,
- 0x5c, 0x16, 0x01, 0x10, 0xa9, 0x80, 0x88, 0x60,
- 0xcc, 0x44, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09,
- 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03,
- 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16,
- 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, 0x80,
+ 0x80, 0x41, 0x62, 0x80, 0xa6, 0x80, 0x4b, 0x72,
+ 0x80, 0x4c, 0x02, 0xf8, 0x02, 0x80, 0x8f, 0x80,
+ 0xb0, 0x40, 0xdb, 0x08, 0x80, 0x41, 0xd0, 0x80,
+ 0x8c, 0x80, 0x8f, 0x8c, 0xe4, 0x03, 0x01, 0x89,
+ 0x00, 0x14, 0x28, 0x10, 0x11, 0x02, 0x01, 0x18,
+ 0x0b, 0x24, 0x4b, 0x26, 0x01, 0x01, 0x86, 0xe5,
+ 0x80, 0x60, 0x79, 0xb6, 0x81, 0x40, 0x91, 0x81,
+ 0xbd, 0x88, 0x94, 0x05, 0x80, 0x98, 0x80, 0xa2,
+ 0x00, 0x80, 0x9b, 0x12, 0x82, 0x43, 0x34, 0xa2,
+ 0x06, 0x80, 0x8d, 0x60, 0x5c, 0x15, 0x01, 0x10,
+ 0xa9, 0x80, 0x88, 0x60, 0xcc, 0x44, 0xd4, 0x80,
+ 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00,
+ 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b,
+ 0x03, 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, 0x81,
+ 0x98, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80,
0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80,
- 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x07,
- 0x47, 0x33, 0x89, 0x80, 0x93, 0x52, 0x10, 0x99,
+ 0x9e, 0x80, 0x98, 0x07, 0x47, 0x33, 0x89, 0x80,
+ 0x93, 0x2d, 0x41, 0x04, 0xbd, 0x50, 0xc1, 0x99,
0x85, 0x99, 0x85, 0x99,
};
-static const uint8_t unicode_prop_Cased1_index[18] = {
- 0xb9, 0x02, 0xe0, 0xa0, 0x1e, 0x40, 0x9e, 0xa6,
- 0x40, 0x55, 0xd4, 0x61, 0xfb, 0xd6, 0x21, 0x8a,
- 0xf1, 0x01,
+static const uint8_t unicode_prop_Cased1_index[21] = {
+ 0xb9, 0x02, 0xe0, // 002B9 at 39
+ 0xc0, 0x1d, 0x20, // 01DC0 at 65
+ 0xe5, 0x2c, 0x20, // 02CE5 at 97
+ 0xb1, 0x07, 0x21, // 107B1 at 129
+ 0xc1, 0xd6, 0x21, // 1D6C1 at 161
+ 0x4a, 0xf1, 0x01, // 1F14A at 192
+ 0x8a, 0xf1, 0x01, // 1F18A at 224 (upper bound)
};
-static const uint8_t unicode_prop_Case_Ignorable_table[720] = {
+static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
0xa6, 0x05, 0x80, 0x8a, 0x80, 0xa2, 0x00, 0x80,
0xc6, 0x03, 0x00, 0x03, 0x01, 0x81, 0x41, 0xf6,
0x40, 0xbf, 0x19, 0x18, 0x88, 0x08, 0x80, 0x40,
@@ -215,7 +220,7 @@ static const uint8_t unicode_prop_Case_Ignorable_table[720] = {
0x01, 0x05, 0x04, 0x81, 0x93, 0x81, 0x9b, 0x81,
0xb8, 0x0b, 0x1f, 0x80, 0x93, 0x81, 0x9c, 0x80,
0xc7, 0x06, 0x10, 0x80, 0xd9, 0x01, 0x86, 0x8a,
- 0x88, 0xe1, 0x01, 0x88, 0x88, 0x00, 0x85, 0xc9,
+ 0x88, 0xe1, 0x01, 0x88, 0x88, 0x00, 0x86, 0xc8,
0x81, 0x9a, 0x00, 0x00, 0x80, 0xb6, 0x8d, 0x04,
0x01, 0x84, 0x8a, 0x80, 0xa3, 0x88, 0x80, 0xe5,
0x18, 0x28, 0x09, 0x81, 0x98, 0x0b, 0x82, 0x8f,
@@ -256,49 +261,66 @@ static const uint8_t unicode_prop_Case_Ignorable_table[720] = {
0x80, 0x40, 0x94, 0x84, 0x44, 0x04, 0x28, 0xa9,
0x80, 0x88, 0x42, 0x45, 0x10, 0x0c, 0x83, 0xa7,
0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x83,
- 0x41, 0x82, 0x81, 0x40, 0x98, 0x8a, 0xb0, 0x83,
- 0xfa, 0x80, 0xb5, 0x8e, 0xa8, 0x01, 0x81, 0x89,
- 0x82, 0xb0, 0x19, 0x09, 0x03, 0x80, 0x89, 0x80,
- 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80, 0x8b,
- 0x81, 0xb3, 0x88, 0x89, 0x19, 0x80, 0xde, 0x11,
- 0x00, 0x0d, 0x80, 0x40, 0x9f, 0x02, 0x87, 0x94,
- 0x81, 0xb8, 0x0a, 0x80, 0xa4, 0x32, 0x84, 0x40,
- 0xc2, 0x39, 0x10, 0x80, 0x96, 0x80, 0xd3, 0x28,
- 0x03, 0x08, 0x81, 0x40, 0xed, 0x1d, 0x08, 0x81,
- 0x9a, 0x81, 0xd4, 0x39, 0x00, 0x81, 0xe9, 0x00,
- 0x01, 0x28, 0x80, 0xe4, 0x11, 0x18, 0x84, 0x41,
- 0x02, 0x88, 0x01, 0x40, 0xff, 0x08, 0x03, 0x80,
- 0x40, 0x8f, 0x19, 0x0b, 0x80, 0x9f, 0x89, 0xa7,
- 0x29, 0x1f, 0x80, 0x88, 0x29, 0x82, 0xad, 0x8c,
- 0x01, 0x41, 0x95, 0x30, 0x28, 0x80, 0xd1, 0x95,
- 0x0e, 0x01, 0x01, 0xf9, 0x2a, 0x00, 0x08, 0x30,
- 0x80, 0xc7, 0x0a, 0x00, 0x80, 0x41, 0x5a, 0x81,
- 0x55, 0x3a, 0x88, 0x60, 0x36, 0xb6, 0x84, 0xba,
- 0x86, 0x88, 0x83, 0x44, 0x0a, 0x80, 0xbe, 0x90,
- 0xbf, 0x08, 0x81, 0x60, 0x40, 0x0a, 0x18, 0x30,
- 0x81, 0x4c, 0x9d, 0x08, 0x83, 0x52, 0x5b, 0xad,
- 0x81, 0x96, 0x42, 0x1f, 0x82, 0x88, 0x8f, 0x0e,
- 0x9d, 0x83, 0x40, 0x93, 0x82, 0x47, 0xba, 0xb6,
- 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e,
- 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0x41,
- 0x04, 0x8d, 0x41, 0x6f, 0x80, 0xbc, 0x83, 0x45,
- 0xdf, 0x86, 0xec, 0x87, 0x4a, 0xae, 0x84, 0x6c,
- 0x0c, 0x00, 0x80, 0x9d, 0xdf, 0xff, 0x40, 0xef,
+ 0x41, 0x82, 0x81, 0xcf, 0x82, 0xc5, 0x8a, 0xb0,
+ 0x83, 0xfa, 0x80, 0xb5, 0x8e, 0xa8, 0x01, 0x81,
+ 0x89, 0x82, 0xb0, 0x19, 0x09, 0x03, 0x80, 0x89,
+ 0x80, 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80,
+ 0x8b, 0x81, 0xb3, 0x88, 0x89, 0x19, 0x80, 0xde,
+ 0x11, 0x00, 0x0d, 0x01, 0x80, 0x40, 0x9c, 0x02,
+ 0x87, 0x94, 0x81, 0xb8, 0x0a, 0x80, 0xa4, 0x32,
+ 0x84, 0x40, 0xc2, 0x39, 0x10, 0x80, 0x96, 0x80,
+ 0xd3, 0x28, 0x03, 0x08, 0x81, 0x40, 0xed, 0x1d,
+ 0x08, 0x81, 0x9a, 0x81, 0xd4, 0x39, 0x00, 0x81,
+ 0xe9, 0x00, 0x01, 0x28, 0x80, 0xe4, 0x11, 0x18,
+ 0x84, 0x41, 0x02, 0x88, 0x01, 0x40, 0xff, 0x08,
+ 0x03, 0x80, 0x40, 0x8f, 0x19, 0x0b, 0x80, 0x9f,
+ 0x89, 0xa7, 0x29, 0x1f, 0x80, 0x88, 0x29, 0x82,
+ 0xad, 0x8c, 0x01, 0x41, 0x95, 0x30, 0x28, 0x80,
+ 0xd1, 0x95, 0x0e, 0x01, 0x01, 0xf9, 0x2a, 0x00,
+ 0x08, 0x30, 0x80, 0xc7, 0x0a, 0x00, 0x80, 0x41,
+ 0x5a, 0x81, 0x8a, 0x81, 0xb3, 0x24, 0x00, 0x80,
+ 0x54, 0xec, 0x90, 0x85, 0x8e, 0x60, 0x36, 0x99,
+ 0x84, 0xba, 0x86, 0x88, 0x83, 0x44, 0x0a, 0x80,
+ 0xbe, 0x90, 0xbf, 0x08, 0x81, 0x60, 0x40, 0x0a,
+ 0x18, 0x30, 0x81, 0x4c, 0x9d, 0x08, 0x83, 0x52,
+ 0x5b, 0xad, 0x81, 0x96, 0x42, 0x1f, 0x82, 0x88,
+ 0x8f, 0x0e, 0x9d, 0x83, 0x40, 0x93, 0x82, 0x47,
+ 0xba, 0xb6, 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95,
+ 0x20, 0x8e, 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01,
+ 0x04, 0x84, 0xbd, 0xa0, 0x80, 0x40, 0x9f, 0x8d,
+ 0x41, 0x6f, 0x80, 0xbc, 0x83, 0x41, 0xfa, 0x84,
+ 0x43, 0xdf, 0x86, 0xec, 0x87, 0x4a, 0xae, 0x84,
+ 0x6c, 0x0c, 0x00, 0x80, 0x9d, 0xdf, 0xff, 0x40,
+ 0xef,
};
static const uint8_t unicode_prop_Case_Ignorable_index[69] = {
- 0xbe, 0x05, 0x00, 0xfe, 0x07, 0x00, 0x52, 0x0a,
- 0xa0, 0xc1, 0x0b, 0x00, 0x82, 0x0d, 0x00, 0x3f,
- 0x10, 0x80, 0xd4, 0x17, 0x40, 0xcf, 0x1a, 0x20,
- 0xf5, 0x1c, 0x00, 0x80, 0x20, 0x00, 0x16, 0xa0,
- 0x00, 0xc6, 0xa8, 0x00, 0xc2, 0xaa, 0x60, 0x56,
- 0xfe, 0x20, 0xb1, 0x07, 0x01, 0x82, 0x10, 0x21,
- 0x02, 0x13, 0x21, 0xb8, 0x16, 0x61, 0x97, 0x1a,
- 0x01, 0x37, 0x6b, 0x21, 0x8c, 0xd1, 0x01, 0xd7,
- 0xe8, 0x41, 0xf0, 0x01, 0x0e,
+ 0xbe, 0x05, 0x00, // 005BE at 32
+ 0xfe, 0x07, 0x00, // 007FE at 64
+ 0x52, 0x0a, 0xa0, // 00A52 at 101
+ 0xc1, 0x0b, 0x00, // 00BC1 at 128
+ 0x82, 0x0d, 0x00, // 00D82 at 160
+ 0x3f, 0x10, 0x80, // 0103F at 196
+ 0xd4, 0x17, 0x40, // 017D4 at 226
+ 0xcf, 0x1a, 0x20, // 01ACF at 257
+ 0xf5, 0x1c, 0x00, // 01CF5 at 288
+ 0x80, 0x20, 0x00, // 02080 at 320
+ 0x16, 0xa0, 0x00, // 0A016 at 352
+ 0xc6, 0xa8, 0x00, // 0A8C6 at 384
+ 0xc2, 0xaa, 0x60, // 0AAC2 at 419
+ 0x56, 0xfe, 0x20, // 0FE56 at 449
+ 0xb1, 0x07, 0x01, // 107B1 at 480
+ 0x75, 0x10, 0x01, // 11075 at 512
+ 0xeb, 0x12, 0x21, // 112EB at 545
+ 0x41, 0x16, 0x01, // 11641 at 576
+ 0x5c, 0x1a, 0x01, // 11A5C at 608
+ 0x43, 0x1f, 0x01, // 11F43 at 640
+ 0x2e, 0xcf, 0x41, // 1CF2E at 674
+ 0x25, 0xe0, 0x01, // 1E025 at 704
+ 0xf0, 0x01, 0x0e, // E01F0 at 736 (upper bound)
};
-static const uint8_t unicode_prop_ID_Start_table[1079] = {
+static const uint8_t unicode_prop_ID_Start_table[1100] = {
0xc0, 0x99, 0x85, 0x99, 0xae, 0x80, 0x89, 0x03,
0x04, 0x96, 0x80, 0x9e, 0x80, 0x41, 0xc9, 0x83,
0x8b, 0x8d, 0x26, 0x00, 0x80, 0x40, 0x80, 0x20,
@@ -392,67 +414,92 @@ static const uint8_t unicode_prop_ID_Start_table[1079] = {
0xad, 0x94, 0x9a, 0x96, 0x8b, 0xb4, 0xb8, 0x09,
0x80, 0x8c, 0xac, 0x9f, 0x98, 0x99, 0xa3, 0x9c,
0x01, 0x07, 0xa2, 0x10, 0x8b, 0xaf, 0x8d, 0x83,
- 0x94, 0x00, 0x80, 0xa2, 0x91, 0x80, 0x98, 0xd3,
- 0x30, 0x00, 0x18, 0x8e, 0x80, 0x89, 0x86, 0xae,
- 0xa5, 0x39, 0x09, 0x95, 0x06, 0x01, 0x04, 0x10,
- 0x91, 0x80, 0x8b, 0x84, 0x40, 0x9d, 0xb4, 0x91,
- 0x83, 0x93, 0x82, 0x9d, 0xaf, 0x93, 0x08, 0x80,
- 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3, 0xaf, 0x93,
- 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6, 0x9a, 0xa4,
- 0x86, 0x40, 0xb8, 0xab, 0xf3, 0xbf, 0x9e, 0x39,
- 0x01, 0x38, 0x08, 0x97, 0x8e, 0x00, 0x80, 0xdd,
- 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b, 0x80, 0x89,
- 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad, 0x92, 0x80,
- 0x91, 0xc8, 0x41, 0x06, 0x88, 0x80, 0xa4, 0x90,
- 0x80, 0xb0, 0x9d, 0xef, 0x30, 0x08, 0xa5, 0x94,
- 0x80, 0x98, 0x28, 0x08, 0x9f, 0x8d, 0x80, 0x41,
- 0x46, 0x92, 0x40, 0xbc, 0x80, 0xce, 0x43, 0x99,
- 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, 0x4b, 0xe0,
- 0x8e, 0x44, 0x2e, 0x4f, 0xd0, 0x42, 0x46, 0x60,
+ 0x94, 0x00, 0x80, 0xa2, 0x91, 0x80, 0x98, 0x92,
+ 0x81, 0xbe, 0x30, 0x00, 0x18, 0x8e, 0x80, 0x89,
+ 0x86, 0xae, 0xa5, 0x39, 0x09, 0x95, 0x06, 0x01,
+ 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, 0x40, 0x9d,
+ 0xb4, 0x91, 0x83, 0x93, 0x82, 0x9d, 0xaf, 0x93,
+ 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3,
+ 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6,
+ 0x9a, 0xa4, 0x86, 0x40, 0xb8, 0xab, 0xf3, 0xbf,
+ 0x9e, 0x39, 0x01, 0x38, 0x08, 0x97, 0x8e, 0x00,
+ 0x80, 0xdd, 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b,
+ 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad,
+ 0x92, 0x80, 0x91, 0xc8, 0x41, 0x06, 0x88, 0x80,
+ 0xa4, 0x90, 0x80, 0xb0, 0x9d, 0xef, 0x30, 0x08,
+ 0xa5, 0x94, 0x80, 0x98, 0x28, 0x08, 0x9f, 0x8d,
+ 0x80, 0x41, 0x46, 0x92, 0x8e, 0x00, 0x8c, 0x80,
+ 0xa1, 0xfb, 0x80, 0xce, 0x43, 0x99, 0xe5, 0xee,
+ 0x90, 0x40, 0xc3, 0x4a, 0x4b, 0xe0, 0x8e, 0x44,
+ 0x2f, 0x90, 0x85, 0x4f, 0xb8, 0x42, 0x46, 0x60,
0x21, 0xb8, 0x42, 0x38, 0x86, 0x9e, 0x90, 0xce,
0x90, 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94,
0x84, 0x92, 0x42, 0xaf, 0xbf, 0xff, 0xca, 0x20,
0xc1, 0x8c, 0xbf, 0x08, 0x80, 0x9b, 0x57, 0xf7,
0x87, 0x44, 0xd5, 0xa9, 0x88, 0x60, 0x22, 0xe6,
- 0x18, 0x30, 0x08, 0x41, 0x22, 0xac, 0x82, 0x90,
- 0x1f, 0x41, 0x8b, 0x49, 0x03, 0xea, 0x84, 0x8c,
- 0x82, 0x88, 0x86, 0x89, 0x57, 0x65, 0xd4, 0x80,
- 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00,
- 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b,
- 0x03, 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, 0x81,
- 0x98, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80,
- 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80,
- 0x9e, 0x80, 0x98, 0x07, 0x47, 0x33, 0x9e, 0x41,
- 0xe0, 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, 0x40,
- 0x9d, 0x91, 0xab, 0x44, 0xf3, 0x30, 0x18, 0x08,
- 0x8e, 0x80, 0x40, 0xc4, 0xba, 0xc3, 0x30, 0x44,
- 0xb3, 0x18, 0x9a, 0x01, 0x00, 0x08, 0x80, 0x89,
- 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x02,
- 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, 0x80, 0x89,
- 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, 0x51, 0x43,
- 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x38, 0x86, 0x40,
- 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x4c,
- 0x1e, 0x42, 0x1d, 0x45, 0xe1, 0x53, 0x4a,
+ 0x18, 0x30, 0x08, 0x41, 0x22, 0x8e, 0x80, 0x9c,
+ 0x11, 0x80, 0x8d, 0x1f, 0x41, 0x8b, 0x49, 0x03,
+ 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86, 0x89, 0x57,
+ 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b,
+ 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f,
+ 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80,
+ 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e,
+ 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e,
+ 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x07, 0x47,
+ 0x33, 0x9e, 0x2d, 0x41, 0x04, 0xbd, 0x40, 0x91,
+ 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, 0x40, 0x9d,
+ 0x91, 0xab, 0x41, 0xe3, 0x9b, 0x42, 0xf3, 0x30,
+ 0x18, 0x08, 0x8e, 0x80, 0x40, 0xc4, 0xba, 0xc3,
+ 0x30, 0x44, 0xb3, 0x18, 0x9a, 0x01, 0x00, 0x08,
+ 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00,
+ 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00,
+ 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90,
+ 0x51, 0x43, 0x60, 0xa6, 0xdf, 0x9f, 0x50, 0x39,
+ 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d,
+ 0x30, 0x4c, 0x1e, 0x42, 0x1d, 0x45, 0xe1, 0x53,
+ 0x4a, 0x84, 0x50, 0x5f,
};
-static const uint8_t unicode_prop_ID_Start_index[102] = {
- 0xf6, 0x03, 0x20, 0xa6, 0x07, 0x00, 0xa9, 0x09,
- 0x20, 0xb1, 0x0a, 0x00, 0xba, 0x0b, 0x20, 0x3b,
- 0x0d, 0x20, 0xc7, 0x0e, 0x20, 0x49, 0x12, 0x00,
- 0x9b, 0x16, 0x00, 0xac, 0x19, 0x00, 0xc0, 0x1d,
- 0x80, 0x80, 0x20, 0x20, 0x70, 0x2d, 0x00, 0x00,
- 0x32, 0x00, 0xda, 0xa7, 0x00, 0x4c, 0xaa, 0x20,
- 0xc7, 0xd7, 0x20, 0xfc, 0xfd, 0x20, 0x9d, 0x02,
- 0x21, 0x96, 0x05, 0x01, 0xf3, 0x08, 0x01, 0xb3,
- 0x0c, 0x21, 0x73, 0x11, 0x61, 0x3e, 0x13, 0x01,
- 0x47, 0x17, 0x21, 0x9e, 0x1a, 0x01, 0x9a, 0x23,
- 0x01, 0x78, 0x6b, 0x01, 0xfc, 0xb2, 0x61, 0x3a,
- 0xd5, 0x01, 0x2d, 0xe1, 0x41, 0x33, 0xee, 0x01,
- 0xe0, 0xa6, 0x62, 0x4b, 0x13, 0x03,
+static const uint8_t unicode_prop_ID_Start_index[105] = {
+ 0xf6, 0x03, 0x20, // 003F6 at 33
+ 0xa6, 0x07, 0x00, // 007A6 at 64
+ 0xa9, 0x09, 0x20, // 009A9 at 97
+ 0xb1, 0x0a, 0x00, // 00AB1 at 128
+ 0xba, 0x0b, 0x20, // 00BBA at 161
+ 0x3b, 0x0d, 0x20, // 00D3B at 193
+ 0xc7, 0x0e, 0x20, // 00EC7 at 225
+ 0x49, 0x12, 0x00, // 01249 at 256
+ 0x9b, 0x16, 0x00, // 0169B at 288
+ 0xac, 0x19, 0x00, // 019AC at 320
+ 0xc0, 0x1d, 0x80, // 01DC0 at 356
+ 0x80, 0x20, 0x20, // 02080 at 385
+ 0x70, 0x2d, 0x00, // 02D70 at 416
+ 0x00, 0x32, 0x00, // 03200 at 448
+ 0xda, 0xa7, 0x00, // 0A7DA at 480
+ 0x4c, 0xaa, 0x20, // 0AA4C at 513
+ 0xc7, 0xd7, 0x20, // 0D7C7 at 545
+ 0xfc, 0xfd, 0x20, // 0FDFC at 577
+ 0x9d, 0x02, 0x21, // 1029D at 609
+ 0x96, 0x05, 0x01, // 10596 at 640
+ 0xf3, 0x08, 0x01, // 108F3 at 672
+ 0xb3, 0x0c, 0x21, // 10CB3 at 705
+ 0x73, 0x11, 0x61, // 11173 at 739
+ 0x34, 0x13, 0x01, // 11334 at 768
+ 0x1b, 0x17, 0x21, // 1171B at 801
+ 0x8a, 0x1a, 0x01, // 11A8A at 832
+ 0x34, 0x1f, 0x21, // 11F34 at 865
+ 0xbf, 0x6a, 0x01, // 16ABF at 896
+ 0x23, 0xb1, 0xa1, // 1B123 at 933
+ 0xad, 0xd4, 0x01, // 1D4AD at 960
+ 0x6f, 0xd7, 0x01, // 1D76F at 992
+ 0xff, 0xe7, 0x61, // 1E7FF at 1027
+ 0x5e, 0xee, 0x01, // 1EE5E at 1056
+ 0xe1, 0xeb, 0x22, // 2EBE1 at 1089
+ 0xb0, 0x23, 0x03, // 323B0 at 1120 (upper bound)
};
-static const uint8_t unicode_prop_ID_Continue1_table[640] = {
+static const uint8_t unicode_prop_ID_Continue1_table[660] = {
0xaf, 0x89, 0xa4, 0x80, 0xd6, 0x80, 0x42, 0x47,
0xef, 0x96, 0x80, 0x40, 0xfa, 0x84, 0x41, 0x08,
0xac, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf,
@@ -470,85 +517,101 @@ static const uint8_t unicode_prop_ID_Continue1_table[640] = {
0xba, 0x22, 0x10, 0x83, 0x88, 0x80, 0x8d, 0x89,
0x8f, 0x84, 0xb6, 0x00, 0x30, 0x10, 0x1e, 0x81,
0x8a, 0x09, 0x89, 0x90, 0x82, 0xb7, 0x00, 0x30,
- 0x10, 0x1e, 0x81, 0x8a, 0x09, 0x89, 0x8f, 0x83,
- 0xb6, 0x08, 0x30, 0x10, 0x83, 0x88, 0x80, 0x89,
- 0x09, 0x89, 0x90, 0x82, 0xc5, 0x03, 0x28, 0x00,
- 0x3d, 0x89, 0x09, 0xbc, 0x01, 0x86, 0x8b, 0x38,
- 0x89, 0xd6, 0x01, 0x88, 0x8a, 0x29, 0x89, 0xbd,
- 0x0d, 0x89, 0x8a, 0x00, 0x00, 0x03, 0x81, 0xb0,
- 0x93, 0x01, 0x84, 0x8a, 0x80, 0xa3, 0x88, 0x80,
- 0xe3, 0x93, 0x80, 0x89, 0x8b, 0x1b, 0x10, 0x11,
- 0x32, 0x83, 0x8c, 0x8b, 0x80, 0x8e, 0x42, 0xbe,
- 0x82, 0x88, 0x88, 0x43, 0x9f, 0x83, 0x9b, 0x82,
- 0x9c, 0x81, 0x9d, 0x81, 0xbf, 0x9f, 0x88, 0x01,
- 0x89, 0xa0, 0x10, 0x8a, 0x40, 0x8e, 0x80, 0xf5,
- 0x8b, 0x83, 0x8b, 0x89, 0x89, 0xff, 0x8a, 0xbb,
- 0x84, 0xb8, 0x89, 0x80, 0x9c, 0x81, 0x8a, 0x85,
- 0x89, 0x95, 0x8d, 0x80, 0x8f, 0xb0, 0x84, 0xae,
- 0x90, 0x8a, 0x89, 0x90, 0x88, 0x8b, 0x82, 0x9d,
- 0x8c, 0x81, 0x89, 0xab, 0x8d, 0xaf, 0x93, 0x87,
- 0x89, 0x85, 0x89, 0xf5, 0x10, 0x94, 0x18, 0x28,
- 0x0a, 0x40, 0xc5, 0xbf, 0x42, 0x3e, 0x81, 0x92,
- 0x80, 0xfa, 0x8c, 0x18, 0x82, 0x8b, 0x4b, 0xfd,
- 0x82, 0x40, 0x8c, 0x80, 0xdf, 0x9f, 0x42, 0x29,
- 0x85, 0xe8, 0x81, 0x60, 0x75, 0x84, 0x89, 0xc4,
- 0x03, 0x89, 0x9f, 0x81, 0xcf, 0x81, 0x41, 0x0f,
- 0x02, 0x03, 0x80, 0x96, 0x23, 0x80, 0xd2, 0x81,
- 0xb1, 0x91, 0x89, 0x89, 0x85, 0x91, 0x8c, 0x8a,
- 0x9b, 0x87, 0x98, 0x8c, 0xab, 0x83, 0xae, 0x8d,
- 0x8e, 0x89, 0x8a, 0x80, 0x89, 0x89, 0xae, 0x8d,
- 0x8b, 0x07, 0x09, 0x89, 0xa0, 0x82, 0xb1, 0x00,
- 0x11, 0x0c, 0x08, 0x80, 0xa8, 0x24, 0x81, 0x40,
- 0xeb, 0x38, 0x09, 0x89, 0x60, 0x4f, 0x23, 0x80,
- 0x42, 0xe0, 0x8f, 0x8f, 0x8f, 0x11, 0x97, 0x82,
- 0x40, 0xbf, 0x89, 0xa4, 0x80, 0x42, 0xbc, 0x80,
- 0x40, 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41, 0x24,
- 0x89, 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7, 0x13,
- 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x1f, 0x89,
- 0x41, 0x70, 0x81, 0x40, 0x98, 0x8a, 0xb0, 0x83,
- 0xf9, 0x82, 0xb4, 0x8e, 0x9e, 0x8a, 0x09, 0x89,
- 0x83, 0xac, 0x8a, 0x30, 0xac, 0x89, 0x2a, 0xa3,
- 0x8d, 0x80, 0x89, 0x21, 0xab, 0x80, 0x8b, 0x82,
- 0xaf, 0x8d, 0x3b, 0x80, 0x8b, 0xd1, 0x8b, 0x28,
- 0x40, 0x9f, 0x8b, 0x84, 0x89, 0x2b, 0xb6, 0x08,
- 0x31, 0x09, 0x82, 0x88, 0x80, 0x89, 0x09, 0x32,
- 0x84, 0x40, 0xbf, 0x91, 0x88, 0x89, 0x18, 0xd0,
- 0x93, 0x8b, 0x89, 0x40, 0xd4, 0x31, 0x88, 0x9a,
- 0x81, 0xd1, 0x90, 0x8e, 0x89, 0xd0, 0x8c, 0x87,
- 0x89, 0xd2, 0x8e, 0x83, 0x89, 0x40, 0xf1, 0x8e,
- 0x40, 0xa4, 0x89, 0xc5, 0x28, 0x09, 0x18, 0x00,
- 0x81, 0x8b, 0x89, 0xf6, 0x31, 0x32, 0x80, 0x9b,
- 0x89, 0xa7, 0x30, 0x1f, 0x80, 0x88, 0x8a, 0xad,
- 0x8f, 0x41, 0x94, 0x38, 0x87, 0x8f, 0x89, 0xb7,
- 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08, 0x30,
- 0x07, 0x89, 0xaf, 0x20, 0x08, 0x27, 0x89, 0x41,
- 0x48, 0x83, 0x60, 0x4b, 0x68, 0x89, 0xd5, 0x89,
- 0xa5, 0x84, 0xba, 0x86, 0x98, 0x89, 0x43, 0xf4,
- 0x00, 0xb6, 0x33, 0xd0, 0x80, 0x8a, 0x81, 0x60,
- 0x4c, 0xaa, 0x81, 0x52, 0x60, 0xad, 0x81, 0x96,
- 0x42, 0x1d, 0x22, 0x2f, 0x39, 0x86, 0x9d, 0x83,
- 0x40, 0x93, 0x82, 0x45, 0x88, 0xb1, 0x41, 0xff,
- 0xb6, 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20,
- 0x8e, 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04,
- 0x41, 0x04, 0x86, 0x88, 0x89, 0x41, 0x63, 0x80,
- 0xbc, 0x8d, 0x45, 0xd5, 0x86, 0xec, 0x34, 0x89,
- 0x52, 0x95, 0x89, 0x6c, 0x05, 0x05, 0x40, 0xef,
+ 0x10, 0x1e, 0x81, 0x8a, 0x09, 0x89, 0x10, 0x8b,
+ 0x83, 0xb6, 0x08, 0x30, 0x10, 0x83, 0x88, 0x80,
+ 0x89, 0x09, 0x89, 0x90, 0x82, 0xc5, 0x03, 0x28,
+ 0x00, 0x3d, 0x89, 0x09, 0xbc, 0x01, 0x86, 0x8b,
+ 0x38, 0x89, 0xd6, 0x01, 0x88, 0x8a, 0x30, 0x89,
+ 0xbd, 0x0d, 0x89, 0x8a, 0x00, 0x00, 0x03, 0x81,
+ 0xb0, 0x93, 0x01, 0x84, 0x8a, 0x80, 0xa3, 0x88,
+ 0x80, 0xe3, 0x93, 0x80, 0x89, 0x8b, 0x1b, 0x10,
+ 0x11, 0x32, 0x83, 0x8c, 0x8b, 0x80, 0x8e, 0x42,
+ 0xbe, 0x82, 0x88, 0x88, 0x43, 0x9f, 0x83, 0x9b,
+ 0x82, 0x9c, 0x81, 0x9d, 0x81, 0xbf, 0x9f, 0x88,
+ 0x01, 0x89, 0xa0, 0x10, 0x8a, 0x40, 0x8e, 0x80,
+ 0xf5, 0x8b, 0x83, 0x8b, 0x89, 0x89, 0xff, 0x8a,
+ 0xbb, 0x84, 0xb8, 0x89, 0x80, 0x9c, 0x81, 0x8a,
+ 0x85, 0x89, 0x95, 0x8d, 0x80, 0x8f, 0xb0, 0x84,
+ 0xae, 0x90, 0x8a, 0x89, 0x90, 0x88, 0x8b, 0x82,
+ 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x8d, 0xaf, 0x93,
+ 0x87, 0x89, 0x85, 0x89, 0xf5, 0x10, 0x94, 0x18,
+ 0x28, 0x0a, 0x40, 0xc5, 0xbf, 0x42, 0x3e, 0x81,
+ 0x92, 0x80, 0xfa, 0x8c, 0x18, 0x82, 0x8b, 0x4b,
+ 0xfd, 0x82, 0x40, 0x8c, 0x80, 0xdf, 0x9f, 0x42,
+ 0x29, 0x85, 0xe8, 0x81, 0x60, 0x75, 0x84, 0x89,
+ 0xc4, 0x03, 0x89, 0x9f, 0x81, 0xcf, 0x81, 0x41,
+ 0x0f, 0x02, 0x03, 0x80, 0x96, 0x23, 0x80, 0xd2,
+ 0x81, 0xb1, 0x91, 0x89, 0x89, 0x85, 0x91, 0x8c,
+ 0x8a, 0x9b, 0x87, 0x98, 0x8c, 0xab, 0x83, 0xae,
+ 0x8d, 0x8e, 0x89, 0x8a, 0x80, 0x89, 0x89, 0xae,
+ 0x8d, 0x8b, 0x07, 0x09, 0x89, 0xa0, 0x82, 0xb1,
+ 0x00, 0x11, 0x0c, 0x08, 0x80, 0xa8, 0x24, 0x81,
+ 0x40, 0xeb, 0x38, 0x09, 0x89, 0x60, 0x4f, 0x23,
+ 0x80, 0x42, 0xe0, 0x8f, 0x8f, 0x8f, 0x11, 0x97,
+ 0x82, 0x40, 0xbf, 0x89, 0xa4, 0x80, 0x42, 0xbc,
+ 0x80, 0x40, 0xe1, 0x80, 0x40, 0x94, 0x84, 0x41,
+ 0x24, 0x89, 0x45, 0x56, 0x10, 0x0c, 0x83, 0xa7,
+ 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x1f,
+ 0x89, 0x41, 0x70, 0x81, 0xcf, 0x82, 0xc5, 0x8a,
+ 0xb0, 0x83, 0xf9, 0x82, 0xb4, 0x8e, 0x9e, 0x8a,
+ 0x09, 0x89, 0x83, 0xac, 0x8a, 0x30, 0xac, 0x89,
+ 0x2a, 0xa3, 0x8d, 0x80, 0x89, 0x21, 0xab, 0x80,
+ 0x8b, 0x82, 0xaf, 0x8d, 0x3b, 0x80, 0x8b, 0xd1,
+ 0x8b, 0x28, 0x08, 0x40, 0x9c, 0x8b, 0x84, 0x89,
+ 0x2b, 0xb6, 0x08, 0x31, 0x09, 0x82, 0x88, 0x80,
+ 0x89, 0x09, 0x32, 0x84, 0x40, 0xbf, 0x91, 0x88,
+ 0x89, 0x18, 0xd0, 0x93, 0x8b, 0x89, 0x40, 0xd4,
+ 0x31, 0x88, 0x9a, 0x81, 0xd1, 0x90, 0x8e, 0x89,
+ 0xd0, 0x8c, 0x87, 0x89, 0xd2, 0x8e, 0x83, 0x89,
+ 0x40, 0xf1, 0x8e, 0x40, 0xa4, 0x89, 0xc5, 0x28,
+ 0x09, 0x18, 0x00, 0x81, 0x8b, 0x89, 0xf6, 0x31,
+ 0x32, 0x80, 0x9b, 0x89, 0xa7, 0x30, 0x1f, 0x80,
+ 0x88, 0x8a, 0xad, 0x8f, 0x41, 0x94, 0x38, 0x87,
+ 0x8f, 0x89, 0xb7, 0x95, 0x80, 0x8d, 0xf9, 0x2a,
+ 0x00, 0x08, 0x30, 0x07, 0x89, 0xaf, 0x20, 0x08,
+ 0x27, 0x89, 0x41, 0x48, 0x83, 0x88, 0x08, 0x80,
+ 0xaf, 0x32, 0x84, 0x8c, 0x89, 0x54, 0xe5, 0x05,
+ 0x8e, 0x60, 0x36, 0x09, 0x89, 0xd5, 0x89, 0xa5,
+ 0x84, 0xba, 0x86, 0x98, 0x89, 0x43, 0xf4, 0x00,
+ 0xb6, 0x33, 0xd0, 0x80, 0x8a, 0x81, 0x60, 0x4c,
+ 0xaa, 0x81, 0x52, 0x60, 0xad, 0x81, 0x96, 0x42,
+ 0x1d, 0x22, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x40,
+ 0x93, 0x82, 0x45, 0x88, 0xb1, 0x41, 0xff, 0xb6,
+ 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e,
+ 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0xe3,
+ 0x80, 0x40, 0x9f, 0x86, 0x88, 0x89, 0x41, 0x63,
+ 0x80, 0xbc, 0x8d, 0x41, 0xf1, 0x8d, 0x43, 0xd5,
+ 0x86, 0xec, 0x34, 0x89, 0x52, 0x95, 0x89, 0x6c,
+ 0x05, 0x05, 0x40, 0xef,
};
-static const uint8_t unicode_prop_ID_Continue1_index[60] = {
- 0xfa, 0x06, 0x00, 0x70, 0x09, 0x00, 0xf0, 0x0a,
- 0x40, 0x57, 0x0c, 0x00, 0xf0, 0x0d, 0x40, 0xc7,
- 0x0f, 0x00, 0xea, 0x17, 0x20, 0x45, 0x1b, 0x20,
- 0x55, 0x20, 0x20, 0x0c, 0xa8, 0x60, 0x37, 0xaa,
- 0x00, 0x50, 0xfe, 0x00, 0x3a, 0x0d, 0x01, 0x83,
- 0x11, 0x01, 0xc4, 0x14, 0x21, 0x44, 0x19, 0x21,
- 0x5a, 0x1d, 0x41, 0x9f, 0xbc, 0x61, 0xb0, 0xda,
- 0x21, 0xf0, 0x01, 0x0e,
+static const uint8_t unicode_prop_ID_Continue1_index[63] = {
+ 0xfa, 0x06, 0x00, // 006FA at 32
+ 0x70, 0x09, 0x00, // 00970 at 64
+ 0xf0, 0x0a, 0x40, // 00AF0 at 98
+ 0x57, 0x0c, 0x00, // 00C57 at 128
+ 0xf0, 0x0d, 0x60, // 00DF0 at 163
+ 0xc7, 0x0f, 0x20, // 00FC7 at 193
+ 0xea, 0x17, 0x40, // 017EA at 226
+ 0x05, 0x1b, 0x00, // 01B05 at 256
+ 0x41, 0x20, 0x00, // 02041 at 288
+ 0x0c, 0xa8, 0x80, // 0A80C at 324
+ 0x37, 0xaa, 0x20, // 0AA37 at 353
+ 0x50, 0xfe, 0x20, // 0FE50 at 385
+ 0x3a, 0x0d, 0x21, // 10D3A at 417
+ 0x74, 0x11, 0x01, // 11174 at 448
+ 0x5a, 0x14, 0x21, // 1145A at 481
+ 0x44, 0x19, 0x81, // 11944 at 516
+ 0x5a, 0x1d, 0xa1, // 11D5A at 549
+ 0xf5, 0x6a, 0x21, // 16AF5 at 577
+ 0x45, 0xd2, 0x41, // 1D245 at 610
+ 0xaf, 0xe2, 0x21, // 1E2AF at 641
+ 0xf0, 0x01, 0x0e, // E01F0 at 672 (upper bound)
};
#ifdef CONFIG_ALL_UNICODE
-static const uint8_t unicode_cc_table[881] = {
+static const uint8_t unicode_cc_table[899] = {
0xb2, 0xcf, 0xd4, 0x00, 0xe8, 0x03, 0xdc, 0x00,
0xe8, 0x00, 0xd8, 0x04, 0xdc, 0x01, 0xca, 0x03,
0xdc, 0x01, 0xca, 0x0a, 0xdc, 0x04, 0x01, 0x03,
@@ -631,52 +694,72 @@ static const uint8_t unicode_cc_table[881] = {
0xb6, 0x61, 0x00, 0xdc, 0x80, 0xc0, 0xa7, 0xc0,
0x00, 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, 0xb0,
0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb1,
- 0x52, 0xc1, 0xb0, 0x68, 0x01, 0xdc, 0xc2, 0x00,
- 0xdc, 0xc0, 0x03, 0xdc, 0xb0, 0x00, 0xc0, 0x00,
- 0xdc, 0xc0, 0x00, 0xdc, 0xb0, 0x8f, 0x00, 0x09,
- 0xa8, 0x00, 0x09, 0x8d, 0x00, 0x09, 0xb0, 0x08,
- 0x00, 0x09, 0x00, 0x07, 0xb0, 0x14, 0xc2, 0xaf,
- 0x01, 0x09, 0xb0, 0x0d, 0x00, 0x07, 0xb0, 0x1b,
- 0x00, 0x09, 0x88, 0x00, 0x07, 0xb0, 0x39, 0x00,
- 0x09, 0x00, 0x07, 0xb0, 0x81, 0x00, 0x07, 0x00,
- 0x09, 0xb0, 0x1f, 0x01, 0x07, 0x8f, 0x00, 0x09,
- 0x97, 0xc6, 0x82, 0xc4, 0xb0, 0x9c, 0x00, 0x09,
- 0x82, 0x00, 0x07, 0x96, 0xc0, 0xb0, 0x32, 0x00,
- 0x09, 0x00, 0x07, 0xb0, 0xca, 0x00, 0x09, 0x00,
- 0x07, 0xb0, 0x4d, 0x00, 0x09, 0xb0, 0x45, 0x00,
- 0x09, 0x00, 0x07, 0xb0, 0x42, 0x00, 0x09, 0xb0,
- 0xdc, 0x00, 0x09, 0x00, 0x07, 0xb0, 0xd1, 0x01,
- 0x09, 0x83, 0x00, 0x07, 0xb0, 0x6b, 0x00, 0x09,
- 0xb0, 0x22, 0x00, 0x09, 0x91, 0x00, 0x09, 0xb0,
- 0x20, 0x00, 0x09, 0xb1, 0x74, 0x00, 0x09, 0xb0,
- 0xd1, 0x00, 0x07, 0x80, 0x01, 0x09, 0xb0, 0x20,
- 0x00, 0x09, 0xb8, 0x45, 0x27, 0x04, 0x01, 0xb0,
+ 0x52, 0xc1, 0xb0, 0x1f, 0x02, 0xdc, 0xb0, 0x15,
+ 0x01, 0xdc, 0xc2, 0x00, 0xdc, 0xc0, 0x03, 0xdc,
+ 0xb0, 0x00, 0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc,
+ 0xb0, 0x8f, 0x00, 0x09, 0xa8, 0x00, 0x09, 0x8d,
+ 0x00, 0x09, 0xb0, 0x08, 0x00, 0x09, 0x00, 0x07,
+ 0xb0, 0x14, 0xc2, 0xaf, 0x01, 0x09, 0xb0, 0x0d,
+ 0x00, 0x07, 0xb0, 0x1b, 0x00, 0x09, 0x88, 0x00,
+ 0x07, 0xb0, 0x39, 0x00, 0x09, 0x00, 0x07, 0xb0,
+ 0x81, 0x00, 0x07, 0x00, 0x09, 0xb0, 0x1f, 0x01,
+ 0x07, 0x8f, 0x00, 0x09, 0x97, 0xc6, 0x82, 0xc4,
+ 0xb0, 0x9c, 0x00, 0x09, 0x82, 0x00, 0x07, 0x96,
+ 0xc0, 0xb0, 0x32, 0x00, 0x09, 0x00, 0x07, 0xb0,
+ 0xca, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00,
+ 0x09, 0xb0, 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0,
+ 0x42, 0x00, 0x09, 0xb0, 0xdc, 0x00, 0x09, 0x00,
+ 0x07, 0xb0, 0xd1, 0x01, 0x09, 0x83, 0x00, 0x07,
+ 0xb0, 0x6b, 0x00, 0x09, 0xb0, 0x22, 0x00, 0x09,
+ 0x91, 0x00, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1,
+ 0x74, 0x00, 0x09, 0xb0, 0xd1, 0x00, 0x07, 0x80,
+ 0x01, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb1, 0x78,
+ 0x01, 0x09, 0xb8, 0x43, 0x7c, 0x04, 0x01, 0xb0,
0x0a, 0xc6, 0xb4, 0x88, 0x01, 0x06, 0xb8, 0x44,
0x7b, 0x00, 0x01, 0xb8, 0x0c, 0x95, 0x01, 0xd8,
0x02, 0x01, 0x82, 0x00, 0xe2, 0x04, 0xd8, 0x87,
0x07, 0xdc, 0x81, 0xc4, 0x01, 0xdc, 0x9d, 0xc3,
0xb0, 0x63, 0xc2, 0xb8, 0x05, 0x8a, 0xc6, 0x80,
0xd0, 0x81, 0xc6, 0x80, 0xc1, 0x80, 0xc4, 0xb0,
- 0xd4, 0xc6, 0xb1, 0x46, 0xc0, 0xb0, 0x0c, 0xc3,
- 0xb5, 0xaf, 0x06, 0xdc, 0xb0, 0x3c, 0xc5, 0x00,
- 0x07,
+ 0x33, 0xc0, 0xb0, 0x6f, 0xc6, 0xb1, 0x46, 0xc0,
+ 0xb0, 0x0c, 0xc3, 0xb1, 0xcb, 0x01, 0xe8, 0x00,
+ 0xdc, 0xc0, 0xb3, 0xaf, 0x06, 0xdc, 0xb0, 0x3c,
+ 0xc5, 0x00, 0x07,
};
-static const uint8_t unicode_cc_index[84] = {
- 0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05,
- 0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0x9c,
- 0x08, 0x00, 0x4d, 0x09, 0x00, 0x3c, 0x0b, 0x00,
- 0x3d, 0x0d, 0x00, 0x36, 0x0f, 0x00, 0x38, 0x10,
- 0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xd3,
- 0x1c, 0x00, 0xcf, 0x1d, 0x00, 0xe2, 0x20, 0x00,
- 0x2e, 0x30, 0x20, 0x2b, 0xa9, 0x20, 0xed, 0xab,
- 0x00, 0x39, 0x0a, 0x01, 0x84, 0x0f, 0x21, 0xc0,
- 0x11, 0x01, 0x43, 0x14, 0x01, 0x39, 0x18, 0x21,
- 0x42, 0x1d, 0x21, 0x67, 0xd1, 0x01, 0x30, 0xe1,
- 0x21, 0x4b, 0xe9, 0x01,
+static const uint8_t unicode_cc_index[87] = {
+ 0x4d, 0x03, 0x00, // 0034D at 32
+ 0x97, 0x05, 0x20, // 00597 at 65
+ 0xc6, 0x05, 0x00, // 005C6 at 96
+ 0xe7, 0x06, 0x00, // 006E7 at 128
+ 0x45, 0x07, 0x00, // 00745 at 160
+ 0x9c, 0x08, 0x00, // 0089C at 192
+ 0x4d, 0x09, 0x00, // 0094D at 224
+ 0x3c, 0x0b, 0x00, // 00B3C at 256
+ 0x3d, 0x0d, 0x00, // 00D3D at 288
+ 0x36, 0x0f, 0x00, // 00F36 at 320
+ 0x38, 0x10, 0x20, // 01038 at 353
+ 0x3a, 0x19, 0x00, // 0193A at 384
+ 0xcb, 0x1a, 0x20, // 01ACB at 417
+ 0xd3, 0x1c, 0x00, // 01CD3 at 448
+ 0xcf, 0x1d, 0x00, // 01DCF at 480
+ 0xe2, 0x20, 0x00, // 020E2 at 512
+ 0x2e, 0x30, 0x20, // 0302E at 545
+ 0x2b, 0xa9, 0x20, // 0A92B at 577
+ 0xed, 0xab, 0x00, // 0ABED at 608
+ 0x39, 0x0a, 0x01, // 10A39 at 640
+ 0x51, 0x0f, 0x01, // 10F51 at 672
+ 0x73, 0x11, 0x01, // 11173 at 704
+ 0x75, 0x13, 0x01, // 11375 at 736
+ 0x2b, 0x17, 0x21, // 1172B at 769
+ 0x3f, 0x1c, 0x21, // 11C3F at 801
+ 0x9e, 0xbc, 0x21, // 1BC9E at 833
+ 0x08, 0xe0, 0x01, // 1E008 at 864
+ 0x44, 0xe9, 0x01, // 1E944 at 896
+ 0x4b, 0xe9, 0x01, // 1E94B at 928 (upper bound)
};
-static const uint32_t unicode_decomp_table1[693] = {
+static const uint32_t unicode_decomp_table1[699] = {
0x00280081, 0x002a0097, 0x002a8081, 0x002bc097,
0x002c8115, 0x002d0097, 0x002d4081, 0x002e0097,
0x002e4115, 0x002f0199, 0x00302016, 0x00400842,
@@ -840,20 +923,21 @@ static const uint32_t unicode_decomp_table1[693] = {
0x75e24081, 0x75e2832d, 0x75e4089f, 0x75e84081,
0x75e8839f, 0x75ea4081, 0x75ea8c9f, 0x75f0c081,
0x75f1042d, 0x75f3851f, 0x75f6051f, 0x75f8851f,
- 0x75fb051f, 0x75fd851f, 0x7b80022d, 0x7b814dad,
- 0x7b884203, 0x7b89c081, 0x7b8a452d, 0x7b8d0403,
- 0x7b908081, 0x7b91dc03, 0x7ba0052d, 0x7ba2c8ad,
- 0x7ba84483, 0x7baac8ad, 0x7c400097, 0x7c404521,
- 0x7c440d25, 0x7c4a8087, 0x7c4ac115, 0x7c4b4117,
- 0x7c4c0d1f, 0x7c528217, 0x7c538099, 0x7c53c097,
- 0x7c5a8197, 0x7c640097, 0x7c80012f, 0x7c808081,
- 0x7c841603, 0x7c9004c1, 0x7c940103, 0x7efc051f,
- 0xbe0001ac, 0xbe00d110, 0xbe0947ac, 0xbe0d3910,
- 0xbe29872c, 0xbe2d022c, 0xbe2e3790, 0xbe49ff90,
- 0xbe69bc10,
+ 0x75fb051f, 0x75fd851f, 0x780c049f, 0x780e419f,
+ 0x780f059f, 0x7811c203, 0x7812d0ad, 0x781b0103,
+ 0x7b80022d, 0x7b814dad, 0x7b884203, 0x7b89c081,
+ 0x7b8a452d, 0x7b8d0403, 0x7b908081, 0x7b91dc03,
+ 0x7ba0052d, 0x7ba2c8ad, 0x7ba84483, 0x7baac8ad,
+ 0x7c400097, 0x7c404521, 0x7c440d25, 0x7c4a8087,
+ 0x7c4ac115, 0x7c4b4117, 0x7c4c0d1f, 0x7c528217,
+ 0x7c538099, 0x7c53c097, 0x7c5a8197, 0x7c640097,
+ 0x7c80012f, 0x7c808081, 0x7c841603, 0x7c9004c1,
+ 0x7c940103, 0x7efc051f, 0xbe0001ac, 0xbe00d110,
+ 0xbe0947ac, 0xbe0d3910, 0xbe29872c, 0xbe2d022c,
+ 0xbe2e3790, 0xbe49ff90, 0xbe69bc10,
};
-static const uint16_t unicode_decomp_table2[693] = {
+static const uint16_t unicode_decomp_table2[699] = {
0x0020, 0x0000, 0x0061, 0x0002, 0x0004, 0x0006, 0x03bc, 0x0008,
0x000a, 0x000c, 0x0015, 0x0095, 0x00a5, 0x00b9, 0x00c1, 0x00c3,
0x00c7, 0x00cb, 0x00d1, 0x00d7, 0x00dd, 0x00e0, 0x00e6, 0x00f8,
@@ -935,15 +1019,16 @@ static const uint16_t unicode_decomp_table2[693] = {
0x2207, 0x1dc8, 0x2202, 0x1dca, 0x1dd2, 0x03f4, 0x1dd4, 0x2207,
0x1dd6, 0x2202, 0x1dd8, 0x1de0, 0x03f4, 0x1de2, 0x2207, 0x1de4,
0x2202, 0x1de6, 0x1dee, 0x03f4, 0x1df0, 0x2207, 0x1df2, 0x2202,
- 0x1df4, 0x1dfe, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0e,
- 0x1e2b, 0x062d, 0x1e33, 0x1e3f, 0x062c, 0x1e4f, 0x1ebf, 0x1ecb,
- 0x1ede, 0x1ef0, 0x1f03, 0x1f05, 0x1f09, 0x1f0f, 0x1f15, 0x1f17,
- 0x1f1b, 0x1f1d, 0x1f25, 0x1f28, 0x1f2a, 0x1f30, 0x1f32, 0x30b5,
- 0x1f38, 0x1f90, 0x1fa6, 0x1faa, 0x1fac, 0x1fb1, 0x1ffe, 0x200f,
- 0x2110, 0x2120, 0x2126, 0x2220, 0x233e,
+ 0x1df4, 0x1dfe, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a,
+ 0x1e0c, 0x1e0e, 0x1e16, 0x1e39, 0x1e3d, 0x1e43, 0x1e60, 0x062d,
+ 0x1e68, 0x1e74, 0x062c, 0x1e84, 0x1ef4, 0x1f00, 0x1f13, 0x1f25,
+ 0x1f38, 0x1f3a, 0x1f3e, 0x1f44, 0x1f4a, 0x1f4c, 0x1f50, 0x1f52,
+ 0x1f5a, 0x1f5d, 0x1f5f, 0x1f65, 0x1f67, 0x30b5, 0x1f6d, 0x1fc5,
+ 0x1fdb, 0x1fdf, 0x1fe1, 0x1fe6, 0x2033, 0x2044, 0x2145, 0x2155,
+ 0x215b, 0x2255, 0x2373,
};
-static const uint8_t unicode_decomp_data[9292] = {
+static const uint8_t unicode_decomp_data[9345] = {
0x20, 0x88, 0x20, 0x84, 0x32, 0x33, 0x20, 0x81,
0x20, 0xa7, 0x31, 0x6f, 0x31, 0xd0, 0x34, 0x31,
0xd0, 0x32, 0x33, 0xd0, 0x34, 0x41, 0x80, 0x41,
@@ -1905,207 +1990,214 @@ static const uint8_t unicode_decomp_data[9292] = {
0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00,
0x1f, 0x04, 0x20, 0x05, 0x0b, 0x0c, 0x30, 0x00,
0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00,
- 0x27, 0x06, 0x00, 0x01, 0x05, 0x08, 0x2a, 0x06,
- 0x1e, 0x08, 0x03, 0x0d, 0x20, 0x19, 0x1a, 0x1b,
- 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a,
- 0x00, 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x44,
- 0x90, 0x77, 0x45, 0x28, 0x06, 0x2c, 0x06, 0x00,
- 0x00, 0x47, 0x06, 0x33, 0x06, 0x17, 0x10, 0x11,
- 0x12, 0x13, 0x00, 0x06, 0x0e, 0x02, 0x0f, 0x34,
- 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00,
- 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x2d,
- 0x06, 0x00, 0x00, 0x4a, 0x06, 0x00, 0x00, 0x44,
- 0x06, 0x00, 0x00, 0x46, 0x06, 0x33, 0x06, 0x39,
- 0x06, 0x00, 0x00, 0x35, 0x06, 0x42, 0x06, 0x00,
- 0x00, 0x34, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2e,
- 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a,
- 0x06, 0x00, 0x00, 0xba, 0x06, 0x00, 0x00, 0x6f,
- 0x06, 0x00, 0x00, 0x28, 0x06, 0x2c, 0x06, 0x00,
- 0x00, 0x47, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2d,
- 0x06, 0x37, 0x06, 0x4a, 0x06, 0x43, 0x06, 0x00,
- 0x00, 0x45, 0x06, 0x46, 0x06, 0x33, 0x06, 0x39,
- 0x06, 0x41, 0x06, 0x35, 0x06, 0x42, 0x06, 0x00,
- 0x00, 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e,
- 0x06, 0x00, 0x00, 0x36, 0x06, 0x38, 0x06, 0x3a,
- 0x06, 0x6e, 0x06, 0x00, 0x00, 0xa1, 0x06, 0x27,
- 0x06, 0x00, 0x01, 0x05, 0x08, 0x20, 0x21, 0x0b,
- 0x06, 0x10, 0x23, 0x2a, 0x06, 0x1a, 0x1b, 0x1c,
- 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00,
- 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x28, 0x06,
- 0x2c, 0x06, 0x2f, 0x06, 0x00, 0x00, 0x48, 0x06,
- 0x32, 0x06, 0x2d, 0x06, 0x37, 0x06, 0x4a, 0x06,
+ 0x30, 0x04, 0x3a, 0x04, 0x3e, 0x04, 0x4b, 0x04,
+ 0x4d, 0x04, 0x4e, 0x04, 0x89, 0xa6, 0x30, 0x04,
+ 0xa9, 0x26, 0x28, 0xb9, 0x7f, 0x9f, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a,
+ 0x0b, 0x0e, 0x0f, 0x11, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x1a, 0x1b, 0x61, 0x26, 0x25, 0x2f,
+ 0x7b, 0x51, 0xa6, 0xb1, 0x04, 0x27, 0x06, 0x00,
+ 0x01, 0x05, 0x08, 0x2a, 0x06, 0x1e, 0x08, 0x03,
+ 0x0d, 0x20, 0x19, 0x1a, 0x1b, 0x1c, 0x09, 0x0f,
+ 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04,
+ 0x06, 0x0c, 0x0e, 0x10, 0x44, 0x90, 0x77, 0x45,
+ 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06,
+ 0x33, 0x06, 0x17, 0x10, 0x11, 0x12, 0x13, 0x00,
+ 0x06, 0x0e, 0x02, 0x0f, 0x34, 0x06, 0x2a, 0x06,
+ 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00, 0x36, 0x06,
+ 0x00, 0x00, 0x3a, 0x06, 0x2d, 0x06, 0x00, 0x00,
+ 0x4a, 0x06, 0x00, 0x00, 0x44, 0x06, 0x00, 0x00,
+ 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, 0x00, 0x00,
+ 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x2e, 0x06, 0x00, 0x00,
+ 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x00, 0x00,
+ 0xba, 0x06, 0x00, 0x00, 0x6f, 0x06, 0x00, 0x00,
+ 0x28, 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x37, 0x06,
+ 0x4a, 0x06, 0x43, 0x06, 0x00, 0x00, 0x45, 0x06,
+ 0x46, 0x06, 0x33, 0x06, 0x39, 0x06, 0x41, 0x06,
+ 0x35, 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06,
+ 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00,
+ 0x36, 0x06, 0x38, 0x06, 0x3a, 0x06, 0x6e, 0x06,
+ 0x00, 0x00, 0xa1, 0x06, 0x27, 0x06, 0x00, 0x01,
+ 0x05, 0x08, 0x20, 0x21, 0x0b, 0x06, 0x10, 0x23,
0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17,
0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06,
- 0x0c, 0x0e, 0x10, 0x30, 0x2e, 0x30, 0x00, 0x2c,
- 0x00, 0x28, 0x00, 0x41, 0x00, 0x29, 0x00, 0x14,
- 0x30, 0x53, 0x00, 0x15, 0x30, 0x43, 0x52, 0x43,
- 0x44, 0x57, 0x5a, 0x41, 0x00, 0x48, 0x56, 0x4d,
- 0x56, 0x53, 0x44, 0x53, 0x53, 0x50, 0x50, 0x56,
- 0x57, 0x43, 0x4d, 0x43, 0x4d, 0x44, 0x4d, 0x52,
- 0x44, 0x4a, 0x4b, 0x30, 0x30, 0x00, 0x68, 0x68,
- 0x4b, 0x62, 0x57, 0x5b, 0xcc, 0x53, 0xc7, 0x30,
- 0x8c, 0x4e, 0x1a, 0x59, 0xe3, 0x89, 0x29, 0x59,
- 0xa4, 0x4e, 0x20, 0x66, 0x21, 0x71, 0x99, 0x65,
- 0x4d, 0x52, 0x8c, 0x5f, 0x8d, 0x51, 0xb0, 0x65,
- 0x1d, 0x52, 0x42, 0x7d, 0x1f, 0x75, 0xa9, 0x8c,
- 0xf0, 0x58, 0x39, 0x54, 0x14, 0x6f, 0x95, 0x62,
- 0x55, 0x63, 0x00, 0x4e, 0x09, 0x4e, 0x4a, 0x90,
- 0xe6, 0x5d, 0x2d, 0x4e, 0xf3, 0x53, 0x07, 0x63,
- 0x70, 0x8d, 0x53, 0x62, 0x81, 0x79, 0x7a, 0x7a,
- 0x08, 0x54, 0x80, 0x6e, 0x09, 0x67, 0x08, 0x67,
- 0x33, 0x75, 0x72, 0x52, 0xb6, 0x55, 0x4d, 0x91,
- 0x14, 0x30, 0x15, 0x30, 0x2c, 0x67, 0x09, 0x4e,
- 0x8c, 0x4e, 0x89, 0x5b, 0xb9, 0x70, 0x53, 0x62,
- 0xd7, 0x76, 0xdd, 0x52, 0x57, 0x65, 0x97, 0x5f,
- 0xef, 0x53, 0x30, 0x00, 0x38, 0x4e, 0x05, 0x00,
- 0x09, 0x22, 0x01, 0x60, 0x4f, 0xae, 0x4f, 0xbb,
- 0x4f, 0x02, 0x50, 0x7a, 0x50, 0x99, 0x50, 0xe7,
- 0x50, 0xcf, 0x50, 0x9e, 0x34, 0x3a, 0x06, 0x4d,
- 0x51, 0x54, 0x51, 0x64, 0x51, 0x77, 0x51, 0x1c,
- 0x05, 0xb9, 0x34, 0x67, 0x51, 0x8d, 0x51, 0x4b,
- 0x05, 0x97, 0x51, 0xa4, 0x51, 0xcc, 0x4e, 0xac,
- 0x51, 0xb5, 0x51, 0xdf, 0x91, 0xf5, 0x51, 0x03,
- 0x52, 0xdf, 0x34, 0x3b, 0x52, 0x46, 0x52, 0x72,
- 0x52, 0x77, 0x52, 0x15, 0x35, 0x02, 0x00, 0x20,
- 0x80, 0x80, 0x00, 0x08, 0x00, 0x00, 0xc7, 0x52,
- 0x00, 0x02, 0x1d, 0x33, 0x3e, 0x3f, 0x50, 0x82,
- 0x8a, 0x93, 0xac, 0xb6, 0xb8, 0xb8, 0xb8, 0x2c,
- 0x0a, 0x70, 0x70, 0xca, 0x53, 0xdf, 0x53, 0x63,
- 0x0b, 0xeb, 0x53, 0xf1, 0x53, 0x06, 0x54, 0x9e,
- 0x54, 0x38, 0x54, 0x48, 0x54, 0x68, 0x54, 0xa2,
- 0x54, 0xf6, 0x54, 0x10, 0x55, 0x53, 0x55, 0x63,
- 0x55, 0x84, 0x55, 0x84, 0x55, 0x99, 0x55, 0xab,
- 0x55, 0xb3, 0x55, 0xc2, 0x55, 0x16, 0x57, 0x06,
- 0x56, 0x17, 0x57, 0x51, 0x56, 0x74, 0x56, 0x07,
- 0x52, 0xee, 0x58, 0xce, 0x57, 0xf4, 0x57, 0x0d,
- 0x58, 0x8b, 0x57, 0x32, 0x58, 0x31, 0x58, 0xac,
- 0x58, 0xe4, 0x14, 0xf2, 0x58, 0xf7, 0x58, 0x06,
- 0x59, 0x1a, 0x59, 0x22, 0x59, 0x62, 0x59, 0xa8,
- 0x16, 0xea, 0x16, 0xec, 0x59, 0x1b, 0x5a, 0x27,
- 0x5a, 0xd8, 0x59, 0x66, 0x5a, 0xee, 0x36, 0xfc,
- 0x36, 0x08, 0x5b, 0x3e, 0x5b, 0x3e, 0x5b, 0xc8,
- 0x19, 0xc3, 0x5b, 0xd8, 0x5b, 0xe7, 0x5b, 0xf3,
- 0x5b, 0x18, 0x1b, 0xff, 0x5b, 0x06, 0x5c, 0x53,
- 0x5f, 0x22, 0x5c, 0x81, 0x37, 0x60, 0x5c, 0x6e,
- 0x5c, 0xc0, 0x5c, 0x8d, 0x5c, 0xe4, 0x1d, 0x43,
- 0x5d, 0xe6, 0x1d, 0x6e, 0x5d, 0x6b, 0x5d, 0x7c,
- 0x5d, 0xe1, 0x5d, 0xe2, 0x5d, 0x2f, 0x38, 0xfd,
- 0x5d, 0x28, 0x5e, 0x3d, 0x5e, 0x69, 0x5e, 0x62,
- 0x38, 0x83, 0x21, 0x7c, 0x38, 0xb0, 0x5e, 0xb3,
- 0x5e, 0xb6, 0x5e, 0xca, 0x5e, 0x92, 0xa3, 0xfe,
- 0x5e, 0x31, 0x23, 0x31, 0x23, 0x01, 0x82, 0x22,
- 0x5f, 0x22, 0x5f, 0xc7, 0x38, 0xb8, 0x32, 0xda,
- 0x61, 0x62, 0x5f, 0x6b, 0x5f, 0xe3, 0x38, 0x9a,
- 0x5f, 0xcd, 0x5f, 0xd7, 0x5f, 0xf9, 0x5f, 0x81,
- 0x60, 0x3a, 0x39, 0x1c, 0x39, 0x94, 0x60, 0xd4,
- 0x26, 0xc7, 0x60, 0x02, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00,
- 0x00, 0x02, 0x08, 0x00, 0x80, 0x08, 0x00, 0x00,
- 0x08, 0x80, 0x28, 0x80, 0x02, 0x00, 0x00, 0x02,
- 0x48, 0x61, 0x00, 0x04, 0x06, 0x04, 0x32, 0x46,
- 0x6a, 0x5c, 0x67, 0x96, 0xaa, 0xae, 0xc8, 0xd3,
- 0x5d, 0x62, 0x00, 0x54, 0x77, 0xf3, 0x0c, 0x2b,
- 0x3d, 0x63, 0xfc, 0x62, 0x68, 0x63, 0x83, 0x63,
- 0xe4, 0x63, 0xf1, 0x2b, 0x22, 0x64, 0xc5, 0x63,
- 0xa9, 0x63, 0x2e, 0x3a, 0x69, 0x64, 0x7e, 0x64,
- 0x9d, 0x64, 0x77, 0x64, 0x6c, 0x3a, 0x4f, 0x65,
- 0x6c, 0x65, 0x0a, 0x30, 0xe3, 0x65, 0xf8, 0x66,
- 0x49, 0x66, 0x19, 0x3b, 0x91, 0x66, 0x08, 0x3b,
- 0xe4, 0x3a, 0x92, 0x51, 0x95, 0x51, 0x00, 0x67,
- 0x9c, 0x66, 0xad, 0x80, 0xd9, 0x43, 0x17, 0x67,
- 0x1b, 0x67, 0x21, 0x67, 0x5e, 0x67, 0x53, 0x67,
- 0xc3, 0x33, 0x49, 0x3b, 0xfa, 0x67, 0x85, 0x67,
- 0x52, 0x68, 0x85, 0x68, 0x6d, 0x34, 0x8e, 0x68,
- 0x1f, 0x68, 0x14, 0x69, 0x9d, 0x3b, 0x42, 0x69,
- 0xa3, 0x69, 0xea, 0x69, 0xa8, 0x6a, 0xa3, 0x36,
- 0xdb, 0x6a, 0x18, 0x3c, 0x21, 0x6b, 0xa7, 0x38,
- 0x54, 0x6b, 0x4e, 0x3c, 0x72, 0x6b, 0x9f, 0x6b,
- 0xba, 0x6b, 0xbb, 0x6b, 0x8d, 0x3a, 0x0b, 0x1d,
- 0xfa, 0x3a, 0x4e, 0x6c, 0xbc, 0x3c, 0xbf, 0x6c,
- 0xcd, 0x6c, 0x67, 0x6c, 0x16, 0x6d, 0x3e, 0x6d,
- 0x77, 0x6d, 0x41, 0x6d, 0x69, 0x6d, 0x78, 0x6d,
- 0x85, 0x6d, 0x1e, 0x3d, 0x34, 0x6d, 0x2f, 0x6e,
- 0x6e, 0x6e, 0x33, 0x3d, 0xcb, 0x6e, 0xc7, 0x6e,
- 0xd1, 0x3e, 0xf9, 0x6d, 0x6e, 0x6f, 0x5e, 0x3f,
- 0x8e, 0x3f, 0xc6, 0x6f, 0x39, 0x70, 0x1e, 0x70,
- 0x1b, 0x70, 0x96, 0x3d, 0x4a, 0x70, 0x7d, 0x70,
- 0x77, 0x70, 0xad, 0x70, 0x25, 0x05, 0x45, 0x71,
- 0x63, 0x42, 0x9c, 0x71, 0xab, 0x43, 0x28, 0x72,
- 0x35, 0x72, 0x50, 0x72, 0x08, 0x46, 0x80, 0x72,
- 0x95, 0x72, 0x35, 0x47, 0x02, 0x20, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00,
- 0x00, 0x02, 0x02, 0x80, 0x8a, 0x00, 0x00, 0x20,
- 0x00, 0x08, 0x0a, 0x00, 0x80, 0x88, 0x80, 0x20,
- 0x14, 0x48, 0x7a, 0x73, 0x8b, 0x73, 0xac, 0x3e,
- 0xa5, 0x73, 0xb8, 0x3e, 0xb8, 0x3e, 0x47, 0x74,
- 0x5c, 0x74, 0x71, 0x74, 0x85, 0x74, 0xca, 0x74,
- 0x1b, 0x3f, 0x24, 0x75, 0x36, 0x4c, 0x3e, 0x75,
- 0x92, 0x4c, 0x70, 0x75, 0x9f, 0x21, 0x10, 0x76,
- 0xa1, 0x4f, 0xb8, 0x4f, 0x44, 0x50, 0xfc, 0x3f,
- 0x08, 0x40, 0xf4, 0x76, 0xf3, 0x50, 0xf2, 0x50,
- 0x19, 0x51, 0x33, 0x51, 0x1e, 0x77, 0x1f, 0x77,
- 0x1f, 0x77, 0x4a, 0x77, 0x39, 0x40, 0x8b, 0x77,
- 0x46, 0x40, 0x96, 0x40, 0x1d, 0x54, 0x4e, 0x78,
- 0x8c, 0x78, 0xcc, 0x78, 0xe3, 0x40, 0x26, 0x56,
- 0x56, 0x79, 0x9a, 0x56, 0xc5, 0x56, 0x8f, 0x79,
- 0xeb, 0x79, 0x2f, 0x41, 0x40, 0x7a, 0x4a, 0x7a,
- 0x4f, 0x7a, 0x7c, 0x59, 0xa7, 0x5a, 0xa7, 0x5a,
- 0xee, 0x7a, 0x02, 0x42, 0xab, 0x5b, 0xc6, 0x7b,
- 0xc9, 0x7b, 0x27, 0x42, 0x80, 0x5c, 0xd2, 0x7c,
- 0xa0, 0x42, 0xe8, 0x7c, 0xe3, 0x7c, 0x00, 0x7d,
- 0x86, 0x5f, 0x63, 0x7d, 0x01, 0x43, 0xc7, 0x7d,
- 0x02, 0x7e, 0x45, 0x7e, 0x34, 0x43, 0x28, 0x62,
- 0x47, 0x62, 0x59, 0x43, 0xd9, 0x62, 0x7a, 0x7f,
- 0x3e, 0x63, 0x95, 0x7f, 0xfa, 0x7f, 0x05, 0x80,
- 0xda, 0x64, 0x23, 0x65, 0x60, 0x80, 0xa8, 0x65,
- 0x70, 0x80, 0x5f, 0x33, 0xd5, 0x43, 0xb2, 0x80,
- 0x03, 0x81, 0x0b, 0x44, 0x3e, 0x81, 0xb5, 0x5a,
- 0xa7, 0x67, 0xb5, 0x67, 0x93, 0x33, 0x9c, 0x33,
- 0x01, 0x82, 0x04, 0x82, 0x9e, 0x8f, 0x6b, 0x44,
- 0x91, 0x82, 0x8b, 0x82, 0x9d, 0x82, 0xb3, 0x52,
- 0xb1, 0x82, 0xb3, 0x82, 0xbd, 0x82, 0xe6, 0x82,
- 0x3c, 0x6b, 0xe5, 0x82, 0x1d, 0x83, 0x63, 0x83,
- 0xad, 0x83, 0x23, 0x83, 0xbd, 0x83, 0xe7, 0x83,
- 0x57, 0x84, 0x53, 0x83, 0xca, 0x83, 0xcc, 0x83,
- 0xdc, 0x83, 0x36, 0x6c, 0x6b, 0x6d, 0x02, 0x00,
- 0x00, 0x20, 0x22, 0x2a, 0xa0, 0x0a, 0x00, 0x20,
- 0x80, 0x28, 0x00, 0xa8, 0x20, 0x20, 0x00, 0x02,
- 0x80, 0x22, 0x02, 0x8a, 0x08, 0x00, 0xaa, 0x00,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x28, 0xd5, 0x6c,
- 0x2b, 0x45, 0xf1, 0x84, 0xf3, 0x84, 0x16, 0x85,
- 0xca, 0x73, 0x64, 0x85, 0x2c, 0x6f, 0x5d, 0x45,
- 0x61, 0x45, 0xb1, 0x6f, 0xd2, 0x70, 0x6b, 0x45,
- 0x50, 0x86, 0x5c, 0x86, 0x67, 0x86, 0x69, 0x86,
- 0xa9, 0x86, 0x88, 0x86, 0x0e, 0x87, 0xe2, 0x86,
- 0x79, 0x87, 0x28, 0x87, 0x6b, 0x87, 0x86, 0x87,
- 0xd7, 0x45, 0xe1, 0x87, 0x01, 0x88, 0xf9, 0x45,
- 0x60, 0x88, 0x63, 0x88, 0x67, 0x76, 0xd7, 0x88,
- 0xde, 0x88, 0x35, 0x46, 0xfa, 0x88, 0xbb, 0x34,
- 0xae, 0x78, 0x66, 0x79, 0xbe, 0x46, 0xc7, 0x46,
- 0xa0, 0x8a, 0xed, 0x8a, 0x8a, 0x8b, 0x55, 0x8c,
- 0xa8, 0x7c, 0xab, 0x8c, 0xc1, 0x8c, 0x1b, 0x8d,
- 0x77, 0x8d, 0x2f, 0x7f, 0x04, 0x08, 0xcb, 0x8d,
- 0xbc, 0x8d, 0xf0, 0x8d, 0xde, 0x08, 0xd4, 0x8e,
- 0x38, 0x8f, 0xd2, 0x85, 0xed, 0x85, 0x94, 0x90,
- 0xf1, 0x90, 0x11, 0x91, 0x2e, 0x87, 0x1b, 0x91,
- 0x38, 0x92, 0xd7, 0x92, 0xd8, 0x92, 0x7c, 0x92,
- 0xf9, 0x93, 0x15, 0x94, 0xfa, 0x8b, 0x8b, 0x95,
- 0x95, 0x49, 0xb7, 0x95, 0x77, 0x8d, 0xe6, 0x49,
- 0xc3, 0x96, 0xb2, 0x5d, 0x23, 0x97, 0x45, 0x91,
- 0x1a, 0x92, 0x6e, 0x4a, 0x76, 0x4a, 0xe0, 0x97,
- 0x0a, 0x94, 0xb2, 0x4a, 0x96, 0x94, 0x0b, 0x98,
- 0x0b, 0x98, 0x29, 0x98, 0xb6, 0x95, 0xe2, 0x98,
- 0x33, 0x4b, 0x29, 0x99, 0xa7, 0x99, 0xc2, 0x99,
- 0xfe, 0x99, 0xce, 0x4b, 0x30, 0x9b, 0x12, 0x9b,
- 0x40, 0x9c, 0xfd, 0x9c, 0xce, 0x4c, 0xed, 0x4c,
- 0x67, 0x9d, 0xce, 0xa0, 0xf8, 0x4c, 0x05, 0xa1,
- 0x0e, 0xa2, 0x91, 0xa2, 0xbb, 0x9e, 0x56, 0x4d,
- 0xf9, 0x9e, 0xfe, 0x9e, 0x05, 0x9f, 0x0f, 0x9f,
- 0x16, 0x9f, 0x3b, 0x9f, 0x00, 0xa6, 0x02, 0x88,
- 0xa0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x28,
- 0x00, 0x08, 0xa0, 0x80, 0xa0, 0x80, 0x00, 0x80,
- 0x80, 0x00, 0x0a, 0x88, 0x80, 0x00, 0x80, 0x00,
- 0x20, 0x2a, 0x00, 0x80,
+ 0x0c, 0x0e, 0x10, 0x28, 0x06, 0x2c, 0x06, 0x2f,
+ 0x06, 0x00, 0x00, 0x48, 0x06, 0x32, 0x06, 0x2d,
+ 0x06, 0x37, 0x06, 0x4a, 0x06, 0x2a, 0x06, 0x1a,
+ 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07,
+ 0x0a, 0x00, 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10,
+ 0x30, 0x2e, 0x30, 0x00, 0x2c, 0x00, 0x28, 0x00,
+ 0x41, 0x00, 0x29, 0x00, 0x14, 0x30, 0x53, 0x00,
+ 0x15, 0x30, 0x43, 0x52, 0x43, 0x44, 0x57, 0x5a,
+ 0x41, 0x00, 0x48, 0x56, 0x4d, 0x56, 0x53, 0x44,
+ 0x53, 0x53, 0x50, 0x50, 0x56, 0x57, 0x43, 0x4d,
+ 0x43, 0x4d, 0x44, 0x4d, 0x52, 0x44, 0x4a, 0x4b,
+ 0x30, 0x30, 0x00, 0x68, 0x68, 0x4b, 0x62, 0x57,
+ 0x5b, 0xcc, 0x53, 0xc7, 0x30, 0x8c, 0x4e, 0x1a,
+ 0x59, 0xe3, 0x89, 0x29, 0x59, 0xa4, 0x4e, 0x20,
+ 0x66, 0x21, 0x71, 0x99, 0x65, 0x4d, 0x52, 0x8c,
+ 0x5f, 0x8d, 0x51, 0xb0, 0x65, 0x1d, 0x52, 0x42,
+ 0x7d, 0x1f, 0x75, 0xa9, 0x8c, 0xf0, 0x58, 0x39,
+ 0x54, 0x14, 0x6f, 0x95, 0x62, 0x55, 0x63, 0x00,
+ 0x4e, 0x09, 0x4e, 0x4a, 0x90, 0xe6, 0x5d, 0x2d,
+ 0x4e, 0xf3, 0x53, 0x07, 0x63, 0x70, 0x8d, 0x53,
+ 0x62, 0x81, 0x79, 0x7a, 0x7a, 0x08, 0x54, 0x80,
+ 0x6e, 0x09, 0x67, 0x08, 0x67, 0x33, 0x75, 0x72,
+ 0x52, 0xb6, 0x55, 0x4d, 0x91, 0x14, 0x30, 0x15,
+ 0x30, 0x2c, 0x67, 0x09, 0x4e, 0x8c, 0x4e, 0x89,
+ 0x5b, 0xb9, 0x70, 0x53, 0x62, 0xd7, 0x76, 0xdd,
+ 0x52, 0x57, 0x65, 0x97, 0x5f, 0xef, 0x53, 0x30,
+ 0x00, 0x38, 0x4e, 0x05, 0x00, 0x09, 0x22, 0x01,
+ 0x60, 0x4f, 0xae, 0x4f, 0xbb, 0x4f, 0x02, 0x50,
+ 0x7a, 0x50, 0x99, 0x50, 0xe7, 0x50, 0xcf, 0x50,
+ 0x9e, 0x34, 0x3a, 0x06, 0x4d, 0x51, 0x54, 0x51,
+ 0x64, 0x51, 0x77, 0x51, 0x1c, 0x05, 0xb9, 0x34,
+ 0x67, 0x51, 0x8d, 0x51, 0x4b, 0x05, 0x97, 0x51,
+ 0xa4, 0x51, 0xcc, 0x4e, 0xac, 0x51, 0xb5, 0x51,
+ 0xdf, 0x91, 0xf5, 0x51, 0x03, 0x52, 0xdf, 0x34,
+ 0x3b, 0x52, 0x46, 0x52, 0x72, 0x52, 0x77, 0x52,
+ 0x15, 0x35, 0x02, 0x00, 0x20, 0x80, 0x80, 0x00,
+ 0x08, 0x00, 0x00, 0xc7, 0x52, 0x00, 0x02, 0x1d,
+ 0x33, 0x3e, 0x3f, 0x50, 0x82, 0x8a, 0x93, 0xac,
+ 0xb6, 0xb8, 0xb8, 0xb8, 0x2c, 0x0a, 0x70, 0x70,
+ 0xca, 0x53, 0xdf, 0x53, 0x63, 0x0b, 0xeb, 0x53,
+ 0xf1, 0x53, 0x06, 0x54, 0x9e, 0x54, 0x38, 0x54,
+ 0x48, 0x54, 0x68, 0x54, 0xa2, 0x54, 0xf6, 0x54,
+ 0x10, 0x55, 0x53, 0x55, 0x63, 0x55, 0x84, 0x55,
+ 0x84, 0x55, 0x99, 0x55, 0xab, 0x55, 0xb3, 0x55,
+ 0xc2, 0x55, 0x16, 0x57, 0x06, 0x56, 0x17, 0x57,
+ 0x51, 0x56, 0x74, 0x56, 0x07, 0x52, 0xee, 0x58,
+ 0xce, 0x57, 0xf4, 0x57, 0x0d, 0x58, 0x8b, 0x57,
+ 0x32, 0x58, 0x31, 0x58, 0xac, 0x58, 0xe4, 0x14,
+ 0xf2, 0x58, 0xf7, 0x58, 0x06, 0x59, 0x1a, 0x59,
+ 0x22, 0x59, 0x62, 0x59, 0xa8, 0x16, 0xea, 0x16,
+ 0xec, 0x59, 0x1b, 0x5a, 0x27, 0x5a, 0xd8, 0x59,
+ 0x66, 0x5a, 0xee, 0x36, 0xfc, 0x36, 0x08, 0x5b,
+ 0x3e, 0x5b, 0x3e, 0x5b, 0xc8, 0x19, 0xc3, 0x5b,
+ 0xd8, 0x5b, 0xe7, 0x5b, 0xf3, 0x5b, 0x18, 0x1b,
+ 0xff, 0x5b, 0x06, 0x5c, 0x53, 0x5f, 0x22, 0x5c,
+ 0x81, 0x37, 0x60, 0x5c, 0x6e, 0x5c, 0xc0, 0x5c,
+ 0x8d, 0x5c, 0xe4, 0x1d, 0x43, 0x5d, 0xe6, 0x1d,
+ 0x6e, 0x5d, 0x6b, 0x5d, 0x7c, 0x5d, 0xe1, 0x5d,
+ 0xe2, 0x5d, 0x2f, 0x38, 0xfd, 0x5d, 0x28, 0x5e,
+ 0x3d, 0x5e, 0x69, 0x5e, 0x62, 0x38, 0x83, 0x21,
+ 0x7c, 0x38, 0xb0, 0x5e, 0xb3, 0x5e, 0xb6, 0x5e,
+ 0xca, 0x5e, 0x92, 0xa3, 0xfe, 0x5e, 0x31, 0x23,
+ 0x31, 0x23, 0x01, 0x82, 0x22, 0x5f, 0x22, 0x5f,
+ 0xc7, 0x38, 0xb8, 0x32, 0xda, 0x61, 0x62, 0x5f,
+ 0x6b, 0x5f, 0xe3, 0x38, 0x9a, 0x5f, 0xcd, 0x5f,
+ 0xd7, 0x5f, 0xf9, 0x5f, 0x81, 0x60, 0x3a, 0x39,
+ 0x1c, 0x39, 0x94, 0x60, 0xd4, 0x26, 0xc7, 0x60,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x08,
+ 0x00, 0x80, 0x08, 0x00, 0x00, 0x08, 0x80, 0x28,
+ 0x80, 0x02, 0x00, 0x00, 0x02, 0x48, 0x61, 0x00,
+ 0x04, 0x06, 0x04, 0x32, 0x46, 0x6a, 0x5c, 0x67,
+ 0x96, 0xaa, 0xae, 0xc8, 0xd3, 0x5d, 0x62, 0x00,
+ 0x54, 0x77, 0xf3, 0x0c, 0x2b, 0x3d, 0x63, 0xfc,
+ 0x62, 0x68, 0x63, 0x83, 0x63, 0xe4, 0x63, 0xf1,
+ 0x2b, 0x22, 0x64, 0xc5, 0x63, 0xa9, 0x63, 0x2e,
+ 0x3a, 0x69, 0x64, 0x7e, 0x64, 0x9d, 0x64, 0x77,
+ 0x64, 0x6c, 0x3a, 0x4f, 0x65, 0x6c, 0x65, 0x0a,
+ 0x30, 0xe3, 0x65, 0xf8, 0x66, 0x49, 0x66, 0x19,
+ 0x3b, 0x91, 0x66, 0x08, 0x3b, 0xe4, 0x3a, 0x92,
+ 0x51, 0x95, 0x51, 0x00, 0x67, 0x9c, 0x66, 0xad,
+ 0x80, 0xd9, 0x43, 0x17, 0x67, 0x1b, 0x67, 0x21,
+ 0x67, 0x5e, 0x67, 0x53, 0x67, 0xc3, 0x33, 0x49,
+ 0x3b, 0xfa, 0x67, 0x85, 0x67, 0x52, 0x68, 0x85,
+ 0x68, 0x6d, 0x34, 0x8e, 0x68, 0x1f, 0x68, 0x14,
+ 0x69, 0x9d, 0x3b, 0x42, 0x69, 0xa3, 0x69, 0xea,
+ 0x69, 0xa8, 0x6a, 0xa3, 0x36, 0xdb, 0x6a, 0x18,
+ 0x3c, 0x21, 0x6b, 0xa7, 0x38, 0x54, 0x6b, 0x4e,
+ 0x3c, 0x72, 0x6b, 0x9f, 0x6b, 0xba, 0x6b, 0xbb,
+ 0x6b, 0x8d, 0x3a, 0x0b, 0x1d, 0xfa, 0x3a, 0x4e,
+ 0x6c, 0xbc, 0x3c, 0xbf, 0x6c, 0xcd, 0x6c, 0x67,
+ 0x6c, 0x16, 0x6d, 0x3e, 0x6d, 0x77, 0x6d, 0x41,
+ 0x6d, 0x69, 0x6d, 0x78, 0x6d, 0x85, 0x6d, 0x1e,
+ 0x3d, 0x34, 0x6d, 0x2f, 0x6e, 0x6e, 0x6e, 0x33,
+ 0x3d, 0xcb, 0x6e, 0xc7, 0x6e, 0xd1, 0x3e, 0xf9,
+ 0x6d, 0x6e, 0x6f, 0x5e, 0x3f, 0x8e, 0x3f, 0xc6,
+ 0x6f, 0x39, 0x70, 0x1e, 0x70, 0x1b, 0x70, 0x96,
+ 0x3d, 0x4a, 0x70, 0x7d, 0x70, 0x77, 0x70, 0xad,
+ 0x70, 0x25, 0x05, 0x45, 0x71, 0x63, 0x42, 0x9c,
+ 0x71, 0xab, 0x43, 0x28, 0x72, 0x35, 0x72, 0x50,
+ 0x72, 0x08, 0x46, 0x80, 0x72, 0x95, 0x72, 0x35,
+ 0x47, 0x02, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x02, 0x02,
+ 0x80, 0x8a, 0x00, 0x00, 0x20, 0x00, 0x08, 0x0a,
+ 0x00, 0x80, 0x88, 0x80, 0x20, 0x14, 0x48, 0x7a,
+ 0x73, 0x8b, 0x73, 0xac, 0x3e, 0xa5, 0x73, 0xb8,
+ 0x3e, 0xb8, 0x3e, 0x47, 0x74, 0x5c, 0x74, 0x71,
+ 0x74, 0x85, 0x74, 0xca, 0x74, 0x1b, 0x3f, 0x24,
+ 0x75, 0x36, 0x4c, 0x3e, 0x75, 0x92, 0x4c, 0x70,
+ 0x75, 0x9f, 0x21, 0x10, 0x76, 0xa1, 0x4f, 0xb8,
+ 0x4f, 0x44, 0x50, 0xfc, 0x3f, 0x08, 0x40, 0xf4,
+ 0x76, 0xf3, 0x50, 0xf2, 0x50, 0x19, 0x51, 0x33,
+ 0x51, 0x1e, 0x77, 0x1f, 0x77, 0x1f, 0x77, 0x4a,
+ 0x77, 0x39, 0x40, 0x8b, 0x77, 0x46, 0x40, 0x96,
+ 0x40, 0x1d, 0x54, 0x4e, 0x78, 0x8c, 0x78, 0xcc,
+ 0x78, 0xe3, 0x40, 0x26, 0x56, 0x56, 0x79, 0x9a,
+ 0x56, 0xc5, 0x56, 0x8f, 0x79, 0xeb, 0x79, 0x2f,
+ 0x41, 0x40, 0x7a, 0x4a, 0x7a, 0x4f, 0x7a, 0x7c,
+ 0x59, 0xa7, 0x5a, 0xa7, 0x5a, 0xee, 0x7a, 0x02,
+ 0x42, 0xab, 0x5b, 0xc6, 0x7b, 0xc9, 0x7b, 0x27,
+ 0x42, 0x80, 0x5c, 0xd2, 0x7c, 0xa0, 0x42, 0xe8,
+ 0x7c, 0xe3, 0x7c, 0x00, 0x7d, 0x86, 0x5f, 0x63,
+ 0x7d, 0x01, 0x43, 0xc7, 0x7d, 0x02, 0x7e, 0x45,
+ 0x7e, 0x34, 0x43, 0x28, 0x62, 0x47, 0x62, 0x59,
+ 0x43, 0xd9, 0x62, 0x7a, 0x7f, 0x3e, 0x63, 0x95,
+ 0x7f, 0xfa, 0x7f, 0x05, 0x80, 0xda, 0x64, 0x23,
+ 0x65, 0x60, 0x80, 0xa8, 0x65, 0x70, 0x80, 0x5f,
+ 0x33, 0xd5, 0x43, 0xb2, 0x80, 0x03, 0x81, 0x0b,
+ 0x44, 0x3e, 0x81, 0xb5, 0x5a, 0xa7, 0x67, 0xb5,
+ 0x67, 0x93, 0x33, 0x9c, 0x33, 0x01, 0x82, 0x04,
+ 0x82, 0x9e, 0x8f, 0x6b, 0x44, 0x91, 0x82, 0x8b,
+ 0x82, 0x9d, 0x82, 0xb3, 0x52, 0xb1, 0x82, 0xb3,
+ 0x82, 0xbd, 0x82, 0xe6, 0x82, 0x3c, 0x6b, 0xe5,
+ 0x82, 0x1d, 0x83, 0x63, 0x83, 0xad, 0x83, 0x23,
+ 0x83, 0xbd, 0x83, 0xe7, 0x83, 0x57, 0x84, 0x53,
+ 0x83, 0xca, 0x83, 0xcc, 0x83, 0xdc, 0x83, 0x36,
+ 0x6c, 0x6b, 0x6d, 0x02, 0x00, 0x00, 0x20, 0x22,
+ 0x2a, 0xa0, 0x0a, 0x00, 0x20, 0x80, 0x28, 0x00,
+ 0xa8, 0x20, 0x20, 0x00, 0x02, 0x80, 0x22, 0x02,
+ 0x8a, 0x08, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x28, 0xd5, 0x6c, 0x2b, 0x45, 0xf1,
+ 0x84, 0xf3, 0x84, 0x16, 0x85, 0xca, 0x73, 0x64,
+ 0x85, 0x2c, 0x6f, 0x5d, 0x45, 0x61, 0x45, 0xb1,
+ 0x6f, 0xd2, 0x70, 0x6b, 0x45, 0x50, 0x86, 0x5c,
+ 0x86, 0x67, 0x86, 0x69, 0x86, 0xa9, 0x86, 0x88,
+ 0x86, 0x0e, 0x87, 0xe2, 0x86, 0x79, 0x87, 0x28,
+ 0x87, 0x6b, 0x87, 0x86, 0x87, 0xd7, 0x45, 0xe1,
+ 0x87, 0x01, 0x88, 0xf9, 0x45, 0x60, 0x88, 0x63,
+ 0x88, 0x67, 0x76, 0xd7, 0x88, 0xde, 0x88, 0x35,
+ 0x46, 0xfa, 0x88, 0xbb, 0x34, 0xae, 0x78, 0x66,
+ 0x79, 0xbe, 0x46, 0xc7, 0x46, 0xa0, 0x8a, 0xed,
+ 0x8a, 0x8a, 0x8b, 0x55, 0x8c, 0xa8, 0x7c, 0xab,
+ 0x8c, 0xc1, 0x8c, 0x1b, 0x8d, 0x77, 0x8d, 0x2f,
+ 0x7f, 0x04, 0x08, 0xcb, 0x8d, 0xbc, 0x8d, 0xf0,
+ 0x8d, 0xde, 0x08, 0xd4, 0x8e, 0x38, 0x8f, 0xd2,
+ 0x85, 0xed, 0x85, 0x94, 0x90, 0xf1, 0x90, 0x11,
+ 0x91, 0x2e, 0x87, 0x1b, 0x91, 0x38, 0x92, 0xd7,
+ 0x92, 0xd8, 0x92, 0x7c, 0x92, 0xf9, 0x93, 0x15,
+ 0x94, 0xfa, 0x8b, 0x8b, 0x95, 0x95, 0x49, 0xb7,
+ 0x95, 0x77, 0x8d, 0xe6, 0x49, 0xc3, 0x96, 0xb2,
+ 0x5d, 0x23, 0x97, 0x45, 0x91, 0x1a, 0x92, 0x6e,
+ 0x4a, 0x76, 0x4a, 0xe0, 0x97, 0x0a, 0x94, 0xb2,
+ 0x4a, 0x96, 0x94, 0x0b, 0x98, 0x0b, 0x98, 0x29,
+ 0x98, 0xb6, 0x95, 0xe2, 0x98, 0x33, 0x4b, 0x29,
+ 0x99, 0xa7, 0x99, 0xc2, 0x99, 0xfe, 0x99, 0xce,
+ 0x4b, 0x30, 0x9b, 0x12, 0x9b, 0x40, 0x9c, 0xfd,
+ 0x9c, 0xce, 0x4c, 0xed, 0x4c, 0x67, 0x9d, 0xce,
+ 0xa0, 0xf8, 0x4c, 0x05, 0xa1, 0x0e, 0xa2, 0x91,
+ 0xa2, 0xbb, 0x9e, 0x56, 0x4d, 0xf9, 0x9e, 0xfe,
+ 0x9e, 0x05, 0x9f, 0x0f, 0x9f, 0x16, 0x9f, 0x3b,
+ 0x9f, 0x00, 0xa6, 0x02, 0x88, 0xa0, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x00, 0x28, 0x00, 0x08, 0xa0,
+ 0x80, 0xa0, 0x80, 0x00, 0x80, 0x80, 0x00, 0x0a,
+ 0x88, 0x80, 0x00, 0x80, 0x00, 0x20, 0x2a, 0x00,
+ 0x80,
};
static const uint16_t unicode_comp_table[945] = {
@@ -2313,7 +2405,7 @@ static const char unicode_gc_name_table[] =
"C,Other" "\0"
;
-static const uint8_t unicode_gc_table[3897] = {
+static const uint8_t unicode_gc_table[3948] = {
0xfa, 0x18, 0x17, 0x56, 0x0d, 0x56, 0x12, 0x13,
0x16, 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36,
0x4c, 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e,
@@ -2399,409 +2491,415 @@ static const uint8_t unicode_gc_table[3897] = {
0x85, 0x20, 0x06, 0x05, 0x07, 0x06, 0x87, 0x00,
0x06, 0x27, 0x00, 0x27, 0x26, 0xc0, 0x27, 0xa0,
0x25, 0x00, 0x25, 0x26, 0x20, 0xe9, 0x02, 0x00,
- 0x25, 0xe0, 0x05, 0x26, 0x27, 0xe5, 0x01, 0x00,
- 0x45, 0x00, 0xe5, 0x21, 0x26, 0x05, 0x47, 0x66,
- 0x00, 0x47, 0x00, 0x47, 0x06, 0x05, 0x0f, 0x60,
- 0x45, 0x07, 0xcb, 0x45, 0x26, 0x20, 0xe9, 0x02,
- 0xeb, 0x01, 0x0f, 0xa5, 0x00, 0x06, 0x27, 0x00,
- 0xe5, 0x0a, 0x40, 0xe5, 0x10, 0x00, 0xe5, 0x01,
- 0x00, 0x05, 0x20, 0xc5, 0x40, 0x06, 0x60, 0x47,
- 0x46, 0x00, 0x06, 0x00, 0xe7, 0x00, 0xa0, 0xe9,
- 0x02, 0x20, 0x27, 0x16, 0xe0, 0x04, 0xe5, 0x28,
- 0x06, 0x25, 0xc6, 0x60, 0x0d, 0xa5, 0x04, 0xe6,
- 0x00, 0x16, 0xe9, 0x02, 0x36, 0xe0, 0x1d, 0x25,
- 0x00, 0x05, 0x00, 0x85, 0x00, 0xe5, 0x10, 0x00,
- 0x05, 0x00, 0xe5, 0x02, 0x06, 0x25, 0xe6, 0x01,
- 0x05, 0x20, 0x85, 0x00, 0x04, 0x00, 0xa6, 0x20,
- 0xe9, 0x02, 0x20, 0x65, 0xe0, 0x18, 0x05, 0x4f,
- 0xf6, 0x07, 0x0f, 0x16, 0x4f, 0x26, 0xaf, 0xe9,
- 0x02, 0xeb, 0x02, 0x0f, 0x06, 0x0f, 0x06, 0x0f,
- 0x06, 0x12, 0x13, 0x12, 0x13, 0x27, 0xe5, 0x00,
- 0x00, 0xe5, 0x1c, 0x60, 0xe6, 0x06, 0x07, 0x86,
- 0x16, 0x26, 0x85, 0xe6, 0x03, 0x00, 0xe6, 0x1c,
- 0x00, 0xef, 0x00, 0x06, 0xaf, 0x00, 0x2f, 0x96,
- 0x6f, 0x36, 0xe0, 0x1d, 0xe5, 0x23, 0x27, 0x66,
- 0x07, 0xa6, 0x07, 0x26, 0x27, 0x26, 0x05, 0xe9,
- 0x02, 0xb6, 0xa5, 0x27, 0x26, 0x65, 0x46, 0x05,
- 0x47, 0x25, 0xc7, 0x45, 0x66, 0xe5, 0x05, 0x06,
- 0x27, 0x26, 0xa7, 0x06, 0x05, 0x07, 0xe9, 0x02,
- 0x47, 0x06, 0x2f, 0xe1, 0x1e, 0x00, 0x01, 0x80,
- 0x01, 0x20, 0xe2, 0x23, 0x16, 0x04, 0x42, 0xe5,
- 0x80, 0xc1, 0x00, 0x65, 0x20, 0xc5, 0x00, 0x05,
- 0x00, 0x65, 0x20, 0xe5, 0x21, 0x00, 0x65, 0x20,
- 0xe5, 0x19, 0x00, 0x65, 0x20, 0xc5, 0x00, 0x05,
- 0x00, 0x65, 0x20, 0xe5, 0x07, 0x00, 0xe5, 0x31,
- 0x00, 0x65, 0x20, 0xe5, 0x3b, 0x20, 0x46, 0xf6,
- 0x01, 0xeb, 0x0c, 0x40, 0xe5, 0x08, 0xef, 0x02,
- 0xa0, 0xe1, 0x4e, 0x20, 0xa2, 0x20, 0x11, 0xe5,
- 0x81, 0xe4, 0x0f, 0x16, 0xe5, 0x09, 0x17, 0xe5,
- 0x12, 0x12, 0x13, 0x40, 0xe5, 0x43, 0x56, 0x4a,
- 0xe5, 0x00, 0xc0, 0xe5, 0x0a, 0x46, 0x07, 0xe0,
- 0x01, 0xe5, 0x0b, 0x26, 0x07, 0x36, 0xe0, 0x01,
- 0xe5, 0x0a, 0x26, 0xe0, 0x04, 0xe5, 0x05, 0x00,
- 0x45, 0x00, 0x26, 0xe0, 0x04, 0xe5, 0x2c, 0x26,
- 0x07, 0xc6, 0xe7, 0x00, 0x06, 0x27, 0xe6, 0x03,
- 0x56, 0x04, 0x56, 0x0d, 0x05, 0x06, 0x20, 0xe9,
- 0x02, 0xa0, 0xeb, 0x02, 0xa0, 0xb6, 0x11, 0x76,
- 0x46, 0x1b, 0x06, 0xe9, 0x02, 0xa0, 0xe5, 0x1b,
- 0x04, 0xe5, 0x2d, 0xc0, 0x85, 0x26, 0xe5, 0x1a,
- 0x06, 0x05, 0x80, 0xe5, 0x3e, 0xe0, 0x02, 0xe5,
- 0x17, 0x00, 0x46, 0x67, 0x26, 0x47, 0x60, 0x27,
- 0x06, 0xa7, 0x46, 0x60, 0x0f, 0x40, 0x36, 0xe9,
- 0x02, 0xe5, 0x16, 0x20, 0x85, 0xe0, 0x03, 0xe5,
- 0x24, 0x60, 0xe5, 0x12, 0xa0, 0xe9, 0x02, 0x0b,
- 0x40, 0xef, 0x1a, 0xe5, 0x0f, 0x26, 0x27, 0x06,
- 0x20, 0x36, 0xe5, 0x2d, 0x07, 0x06, 0x07, 0xc6,
- 0x00, 0x06, 0x07, 0x06, 0x27, 0xe6, 0x00, 0xa7,
- 0xe6, 0x02, 0x20, 0x06, 0xe9, 0x02, 0xa0, 0xe9,
- 0x02, 0xa0, 0xd6, 0x04, 0xb6, 0x20, 0xe6, 0x06,
- 0x08, 0xe6, 0x08, 0xe0, 0x29, 0x66, 0x07, 0xe5,
- 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87, 0x06,
- 0x27, 0xe5, 0x00, 0x40, 0xe9, 0x02, 0xd6, 0xef,
- 0x02, 0xe6, 0x01, 0xef, 0x01, 0x36, 0x00, 0x26,
- 0x07, 0xe5, 0x16, 0x07, 0x66, 0x27, 0x26, 0x07,
- 0x46, 0x25, 0xe9, 0x02, 0xe5, 0x24, 0x06, 0x07,
- 0x26, 0x47, 0x06, 0x07, 0x46, 0x27, 0xe0, 0x00,
- 0x76, 0xe5, 0x1c, 0xe7, 0x00, 0xe6, 0x00, 0x27,
- 0x26, 0x40, 0x96, 0xe9, 0x02, 0x40, 0x45, 0xe9,
- 0x02, 0xe5, 0x16, 0xa4, 0x36, 0xe2, 0x01, 0xc0,
- 0xe1, 0x23, 0x20, 0x41, 0xf6, 0x00, 0xe0, 0x00,
- 0x46, 0x16, 0xe6, 0x05, 0x07, 0xc6, 0x65, 0x06,
- 0xa5, 0x06, 0x25, 0x07, 0x26, 0x05, 0x80, 0xe2,
- 0x24, 0xe4, 0x37, 0xe2, 0x05, 0x04, 0xe2, 0x1a,
- 0xe4, 0x1d, 0xe6, 0x38, 0xff, 0x80, 0x0e, 0xe2,
- 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1, 0x00, 0xa2,
- 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1, 0x00, 0xe2,
- 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1, 0x20, 0xe2,
- 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06, 0x20, 0xe2,
- 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, 0x00, 0xe2,
- 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22, 0x61, 0x03,
- 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22, 0x61, 0x03,
- 0x4e, 0x62, 0x20, 0x22, 0x61, 0x00, 0x4e, 0xe2,
- 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00, 0x22, 0x61,
- 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b, 0xb1, 0x36,
- 0x14, 0x15, 0x12, 0x34, 0x15, 0x12, 0x14, 0xf6,
- 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6, 0x01, 0x14,
- 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12, 0x13, 0xf6,
- 0x03, 0x0c, 0x16, 0x10, 0xf6, 0x02, 0x17, 0x9b,
- 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20, 0xab, 0x4c,
- 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c, 0x12, 0x13,
- 0x00, 0xe4, 0x05, 0x40, 0xed, 0x19, 0xe0, 0x07,
- 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6, 0x04, 0xe0,
- 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f, 0x02, 0x41,
- 0x22, 0x41, 0x02, 0x0f, 0x01, 0x2f, 0x0c, 0x81,
- 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01, 0x0f, 0x61,
- 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02, 0x2f, 0x22,
- 0x21, 0x8c, 0x3f, 0x42, 0x0f, 0x0c, 0x2f, 0x02,
- 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f, 0x6a, 0x0b,
- 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f, 0x0c, 0x2f,
- 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, 0xef, 0x17, 0x2c,
- 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17, 0xec, 0x80,
- 0x84, 0xef, 0x00, 0x12, 0x13, 0x12, 0x13, 0xef,
- 0x0c, 0x2c, 0xcf, 0x12, 0x13, 0xef, 0x49, 0x0c,
- 0xef, 0x16, 0xec, 0x11, 0xef, 0x20, 0xac, 0xef,
- 0x3d, 0xe0, 0x11, 0xef, 0x03, 0xe0, 0x0d, 0xeb,
- 0x34, 0xef, 0x46, 0xeb, 0x0e, 0xef, 0x80, 0x2f,
- 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e, 0xec, 0x00,
- 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70, 0x12, 0x13,
- 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
- 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16, 0xef, 0x24,
- 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12, 0x13, 0x12,
- 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xec,
- 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, 0x12, 0x13,
+ 0x25, 0x07, 0xe0, 0x04, 0x26, 0x27, 0xe5, 0x01,
+ 0x00, 0x45, 0x00, 0xe5, 0x21, 0x26, 0x05, 0x47,
+ 0x66, 0x00, 0x47, 0x00, 0x47, 0x06, 0x05, 0x0f,
+ 0x60, 0x45, 0x07, 0xcb, 0x45, 0x26, 0x20, 0xe9,
+ 0x02, 0xeb, 0x01, 0x0f, 0xa5, 0x00, 0x06, 0x27,
+ 0x00, 0xe5, 0x0a, 0x40, 0xe5, 0x10, 0x00, 0xe5,
+ 0x01, 0x00, 0x05, 0x20, 0xc5, 0x40, 0x06, 0x60,
+ 0x47, 0x46, 0x00, 0x06, 0x00, 0xe7, 0x00, 0xa0,
+ 0xe9, 0x02, 0x20, 0x27, 0x16, 0xe0, 0x04, 0xe5,
+ 0x28, 0x06, 0x25, 0xc6, 0x60, 0x0d, 0xa5, 0x04,
+ 0xe6, 0x00, 0x16, 0xe9, 0x02, 0x36, 0xe0, 0x1d,
+ 0x25, 0x00, 0x05, 0x00, 0x85, 0x00, 0xe5, 0x10,
+ 0x00, 0x05, 0x00, 0xe5, 0x02, 0x06, 0x25, 0xe6,
+ 0x01, 0x05, 0x20, 0x85, 0x00, 0x04, 0x00, 0xc6,
+ 0x00, 0xe9, 0x02, 0x20, 0x65, 0xe0, 0x18, 0x05,
+ 0x4f, 0xf6, 0x07, 0x0f, 0x16, 0x4f, 0x26, 0xaf,
+ 0xe9, 0x02, 0xeb, 0x02, 0x0f, 0x06, 0x0f, 0x06,
+ 0x0f, 0x06, 0x12, 0x13, 0x12, 0x13, 0x27, 0xe5,
+ 0x00, 0x00, 0xe5, 0x1c, 0x60, 0xe6, 0x06, 0x07,
+ 0x86, 0x16, 0x26, 0x85, 0xe6, 0x03, 0x00, 0xe6,
+ 0x1c, 0x00, 0xef, 0x00, 0x06, 0xaf, 0x00, 0x2f,
+ 0x96, 0x6f, 0x36, 0xe0, 0x1d, 0xe5, 0x23, 0x27,
+ 0x66, 0x07, 0xa6, 0x07, 0x26, 0x27, 0x26, 0x05,
+ 0xe9, 0x02, 0xb6, 0xa5, 0x27, 0x26, 0x65, 0x46,
+ 0x05, 0x47, 0x25, 0xc7, 0x45, 0x66, 0xe5, 0x05,
+ 0x06, 0x27, 0x26, 0xa7, 0x06, 0x05, 0x07, 0xe9,
+ 0x02, 0x47, 0x06, 0x2f, 0xe1, 0x1e, 0x00, 0x01,
+ 0x80, 0x01, 0x20, 0xe2, 0x23, 0x16, 0x04, 0x42,
+ 0xe5, 0x80, 0xc1, 0x00, 0x65, 0x20, 0xc5, 0x00,
+ 0x05, 0x00, 0x65, 0x20, 0xe5, 0x21, 0x00, 0x65,
+ 0x20, 0xe5, 0x19, 0x00, 0x65, 0x20, 0xc5, 0x00,
+ 0x05, 0x00, 0x65, 0x20, 0xe5, 0x07, 0x00, 0xe5,
+ 0x31, 0x00, 0x65, 0x20, 0xe5, 0x3b, 0x20, 0x46,
+ 0xf6, 0x01, 0xeb, 0x0c, 0x40, 0xe5, 0x08, 0xef,
+ 0x02, 0xa0, 0xe1, 0x4e, 0x20, 0xa2, 0x20, 0x11,
+ 0xe5, 0x81, 0xe4, 0x0f, 0x16, 0xe5, 0x09, 0x17,
+ 0xe5, 0x12, 0x12, 0x13, 0x40, 0xe5, 0x43, 0x56,
+ 0x4a, 0xe5, 0x00, 0xc0, 0xe5, 0x0a, 0x46, 0x07,
+ 0xe0, 0x01, 0xe5, 0x0b, 0x26, 0x07, 0x36, 0xe0,
+ 0x01, 0xe5, 0x0a, 0x26, 0xe0, 0x04, 0xe5, 0x05,
+ 0x00, 0x45, 0x00, 0x26, 0xe0, 0x04, 0xe5, 0x2c,
+ 0x26, 0x07, 0xc6, 0xe7, 0x00, 0x06, 0x27, 0xe6,
+ 0x03, 0x56, 0x04, 0x56, 0x0d, 0x05, 0x06, 0x20,
+ 0xe9, 0x02, 0xa0, 0xeb, 0x02, 0xa0, 0xb6, 0x11,
+ 0x76, 0x46, 0x1b, 0x06, 0xe9, 0x02, 0xa0, 0xe5,
+ 0x1b, 0x04, 0xe5, 0x2d, 0xc0, 0x85, 0x26, 0xe5,
+ 0x1a, 0x06, 0x05, 0x80, 0xe5, 0x3e, 0xe0, 0x02,
+ 0xe5, 0x17, 0x00, 0x46, 0x67, 0x26, 0x47, 0x60,
+ 0x27, 0x06, 0xa7, 0x46, 0x60, 0x0f, 0x40, 0x36,
+ 0xe9, 0x02, 0xe5, 0x16, 0x20, 0x85, 0xe0, 0x03,
+ 0xe5, 0x24, 0x60, 0xe5, 0x12, 0xa0, 0xe9, 0x02,
+ 0x0b, 0x40, 0xef, 0x1a, 0xe5, 0x0f, 0x26, 0x27,
+ 0x06, 0x20, 0x36, 0xe5, 0x2d, 0x07, 0x06, 0x07,
+ 0xc6, 0x00, 0x06, 0x07, 0x06, 0x27, 0xe6, 0x00,
+ 0xa7, 0xe6, 0x02, 0x20, 0x06, 0xe9, 0x02, 0xa0,
+ 0xe9, 0x02, 0xa0, 0xd6, 0x04, 0xb6, 0x20, 0xe6,
+ 0x06, 0x08, 0xe6, 0x08, 0xe0, 0x29, 0x66, 0x07,
+ 0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87,
+ 0x06, 0x27, 0xe5, 0x00, 0x40, 0xe9, 0x02, 0xd6,
+ 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x36, 0x00,
+ 0x26, 0x07, 0xe5, 0x16, 0x07, 0x66, 0x27, 0x26,
+ 0x07, 0x46, 0x25, 0xe9, 0x02, 0xe5, 0x24, 0x06,
+ 0x07, 0x26, 0x47, 0x06, 0x07, 0x46, 0x27, 0xe0,
+ 0x00, 0x76, 0xe5, 0x1c, 0xe7, 0x00, 0xe6, 0x00,
+ 0x27, 0x26, 0x40, 0x96, 0xe9, 0x02, 0x40, 0x45,
+ 0xe9, 0x02, 0xe5, 0x16, 0xa4, 0x36, 0xe2, 0x01,
+ 0xc0, 0xe1, 0x23, 0x20, 0x41, 0xf6, 0x00, 0xe0,
+ 0x00, 0x46, 0x16, 0xe6, 0x05, 0x07, 0xc6, 0x65,
+ 0x06, 0xa5, 0x06, 0x25, 0x07, 0x26, 0x05, 0x80,
+ 0xe2, 0x24, 0xe4, 0x37, 0xe2, 0x05, 0x04, 0xe2,
+ 0x1a, 0xe4, 0x1d, 0xe6, 0x38, 0xff, 0x80, 0x0e,
+ 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1, 0x00,
+ 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1, 0x00,
+ 0xe2, 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1, 0x20,
+ 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06, 0x20,
+ 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, 0x00,
+ 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22, 0x61,
+ 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22, 0x61,
+ 0x03, 0x4e, 0x62, 0x20, 0x22, 0x61, 0x00, 0x4e,
+ 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00, 0x22,
+ 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b, 0xb1,
+ 0x36, 0x14, 0x15, 0x12, 0x34, 0x15, 0x12, 0x14,
+ 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6, 0x01,
+ 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12, 0x13,
+ 0xf6, 0x03, 0x0c, 0x16, 0x10, 0xf6, 0x02, 0x17,
+ 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20, 0xab,
+ 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c, 0x12,
+ 0x13, 0x00, 0xe4, 0x05, 0x40, 0xed, 0x19, 0xe0,
+ 0x07, 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6, 0x04,
+ 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f, 0x02,
+ 0x41, 0x22, 0x41, 0x02, 0x0f, 0x01, 0x2f, 0x0c,
+ 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01, 0x0f,
+ 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02, 0x2f,
+ 0x22, 0x21, 0x8c, 0x3f, 0x42, 0x0f, 0x0c, 0x2f,
+ 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f, 0x6a,
+ 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f, 0x0c,
+ 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, 0xef, 0x17,
+ 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17, 0xec,
+ 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, 0x12, 0x13,
+ 0xef, 0x0c, 0x2c, 0xcf, 0x12, 0x13, 0xef, 0x49,
+ 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, 0x20, 0xac,
+ 0xef, 0x3d, 0xe0, 0x11, 0xef, 0x03, 0xe0, 0x0d,
+ 0xeb, 0x34, 0xef, 0x46, 0xeb, 0x0e, 0xef, 0x80,
+ 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e, 0xec,
+ 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16, 0xef,
+ 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12, 0x13,
0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
- 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
- 0x12, 0x13, 0x12, 0x13, 0xec, 0x37, 0x12, 0x13,
- 0x12, 0x13, 0xec, 0x18, 0x12, 0x13, 0xec, 0x80,
- 0x7a, 0xef, 0x28, 0xec, 0x0d, 0x2f, 0xac, 0xef,
- 0x1f, 0x20, 0xef, 0x18, 0x00, 0xef, 0x61, 0xe1,
- 0x28, 0xe2, 0x28, 0x5f, 0x21, 0x22, 0xdf, 0x41,
- 0x02, 0x3f, 0x02, 0x3f, 0x82, 0x24, 0x41, 0x02,
- 0xff, 0x5a, 0x02, 0xaf, 0x7f, 0x46, 0x3f, 0x80,
- 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00, 0x02, 0x80,
- 0x02, 0x20, 0xe5, 0x30, 0xc0, 0x04, 0x16, 0xe0,
- 0x06, 0x06, 0xe5, 0x0f, 0xe0, 0x01, 0xc5, 0x00,
- 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00,
- 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xe6, 0x18,
- 0x36, 0x14, 0x15, 0x14, 0x15, 0x56, 0x14, 0x15,
- 0x16, 0x14, 0x15, 0xf6, 0x01, 0x11, 0x36, 0x11,
- 0x16, 0x14, 0x15, 0x36, 0x14, 0x15, 0x12, 0x13,
- 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x96, 0x04,
- 0xf6, 0x02, 0x31, 0x76, 0x11, 0x16, 0x12, 0xf6,
- 0x05, 0x2f, 0x56, 0x12, 0x13, 0x12, 0x13, 0x12,
- 0x13, 0x12, 0x13, 0x11, 0xe0, 0x1a, 0xef, 0x12,
- 0x00, 0xef, 0x51, 0xe0, 0x04, 0xef, 0x80, 0x4e,
- 0xe0, 0x12, 0xef, 0x04, 0x60, 0x17, 0x56, 0x0f,
- 0x04, 0x05, 0x0a, 0x12, 0x13, 0x12, 0x13, 0x12,
- 0x13, 0x12, 0x13, 0x12, 0x13, 0x2f, 0x12, 0x13,
- 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x11, 0x12,
- 0x33, 0x0f, 0xea, 0x01, 0x66, 0x27, 0x11, 0x84,
- 0x2f, 0x4a, 0x04, 0x05, 0x16, 0x2f, 0x00, 0xe5,
- 0x4e, 0x20, 0x26, 0x2e, 0x24, 0x05, 0x11, 0xe5,
- 0x52, 0x16, 0x44, 0x05, 0x80, 0xe5, 0x23, 0x00,
- 0xe5, 0x56, 0x00, 0x2f, 0x6b, 0xef, 0x02, 0xe5,
- 0x18, 0xef, 0x1c, 0xe0, 0x04, 0xe5, 0x08, 0xef,
- 0x17, 0x00, 0xeb, 0x02, 0xef, 0x16, 0xeb, 0x00,
- 0x0f, 0xeb, 0x07, 0xef, 0x18, 0xeb, 0x02, 0xef,
- 0x1f, 0xeb, 0x07, 0xef, 0x80, 0xb8, 0xe5, 0x99,
- 0x38, 0xef, 0x38, 0xe5, 0xc0, 0x11, 0x8d, 0x04,
- 0xe5, 0x83, 0xef, 0x40, 0xef, 0x2f, 0xe0, 0x01,
- 0xe5, 0x20, 0xa4, 0x36, 0xe5, 0x80, 0x84, 0x04,
- 0x56, 0xe5, 0x08, 0xe9, 0x02, 0x25, 0xe0, 0x0c,
- 0xff, 0x26, 0x05, 0x06, 0x48, 0x16, 0xe6, 0x02,
- 0x16, 0x04, 0xff, 0x14, 0x24, 0x26, 0xe5, 0x3e,
- 0xea, 0x02, 0x26, 0xb6, 0xe0, 0x00, 0xee, 0x0f,
- 0xe4, 0x01, 0x2e, 0xff, 0x06, 0x22, 0xff, 0x36,
- 0x04, 0xe2, 0x00, 0x9f, 0xff, 0x02, 0x04, 0x2e,
- 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d, 0x61, 0x02,
- 0x81, 0x02, 0xff, 0x07, 0x41, 0x02, 0x3f, 0x80,
- 0x3f, 0x00, 0x02, 0x00, 0x02, 0x7f, 0xe0, 0x10,
- 0x44, 0x3f, 0x05, 0x24, 0x02, 0xc5, 0x06, 0x45,
- 0x06, 0x65, 0x06, 0xe5, 0x0f, 0x27, 0x26, 0x07,
- 0x6f, 0x06, 0x40, 0xab, 0x2f, 0x0d, 0x0f, 0xa0,
- 0xe5, 0x2c, 0x76, 0xe0, 0x00, 0x27, 0xe5, 0x2a,
- 0xe7, 0x08, 0x26, 0xe0, 0x00, 0x36, 0xe9, 0x02,
- 0xa0, 0xe6, 0x0a, 0xa5, 0x56, 0x05, 0x16, 0x25,
- 0x06, 0xe9, 0x02, 0xe5, 0x14, 0xe6, 0x00, 0x36,
- 0xe5, 0x0f, 0xe6, 0x03, 0x27, 0xe0, 0x03, 0x16,
- 0xe5, 0x15, 0x40, 0x46, 0x07, 0xe5, 0x27, 0x06,
- 0x27, 0x66, 0x27, 0x26, 0x47, 0xf6, 0x05, 0x00,
- 0x04, 0xe9, 0x02, 0x60, 0x36, 0x85, 0x06, 0x04,
- 0xe5, 0x01, 0xe9, 0x02, 0x85, 0x00, 0xe5, 0x21,
- 0xa6, 0x27, 0x26, 0x27, 0x26, 0xe0, 0x01, 0x45,
- 0x06, 0xe5, 0x00, 0x06, 0x07, 0x20, 0xe9, 0x02,
- 0x20, 0x76, 0xe5, 0x08, 0x04, 0xa5, 0x4f, 0x05,
- 0x07, 0x06, 0x07, 0xe5, 0x2a, 0x06, 0x05, 0x46,
- 0x25, 0x26, 0x85, 0x26, 0x05, 0x06, 0x05, 0xe0,
- 0x10, 0x25, 0x04, 0x36, 0xe5, 0x03, 0x07, 0x26,
- 0x27, 0x36, 0x05, 0x24, 0x07, 0x06, 0xe0, 0x02,
- 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0xe0, 0x01, 0xc5,
- 0x00, 0xc5, 0x00, 0xe2, 0x23, 0x0e, 0x64, 0xe2,
- 0x01, 0x04, 0x2e, 0x60, 0xe2, 0x48, 0xe5, 0x1b,
- 0x27, 0x06, 0x27, 0x06, 0x27, 0x16, 0x07, 0x06,
- 0x20, 0xe9, 0x02, 0xa0, 0xe5, 0xab, 0x1c, 0xe0,
- 0x04, 0xe5, 0x0f, 0x60, 0xe5, 0x29, 0x60, 0xfc,
- 0x87, 0x78, 0xfd, 0x98, 0x78, 0xe5, 0x80, 0xe6,
- 0x20, 0xe5, 0x62, 0xe0, 0x1e, 0xc2, 0xe0, 0x04,
- 0x82, 0x80, 0x05, 0x06, 0xe5, 0x02, 0x0c, 0xe5,
- 0x05, 0x00, 0x85, 0x00, 0x05, 0x00, 0x25, 0x00,
- 0x25, 0x00, 0xe5, 0x64, 0xee, 0x09, 0xe0, 0x08,
- 0xe5, 0x80, 0xe3, 0x13, 0x12, 0xef, 0x08, 0xe5,
- 0x38, 0x20, 0xe5, 0x2e, 0xc0, 0x0f, 0xe0, 0x18,
- 0xe5, 0x04, 0x0d, 0x4f, 0xe6, 0x08, 0xd6, 0x12,
- 0x13, 0x16, 0xa0, 0xe6, 0x08, 0x16, 0x31, 0x30,
- 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
- 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
- 0x36, 0x12, 0x13, 0x76, 0x50, 0x56, 0x00, 0x76,
- 0x11, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x56,
- 0x0c, 0x11, 0x4c, 0x00, 0x16, 0x0d, 0x36, 0x60,
- 0x85, 0x00, 0xe5, 0x7f, 0x20, 0x1b, 0x00, 0x56,
- 0x0d, 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16, 0x11,
- 0x36, 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1, 0x12,
- 0x12, 0x16, 0x13, 0x0e, 0x10, 0x0e, 0xe2, 0x12,
- 0x12, 0x0c, 0x13, 0x0c, 0x12, 0x13, 0x16, 0x12,
- 0x13, 0x36, 0xe5, 0x02, 0x04, 0xe5, 0x25, 0x24,
- 0xe5, 0x17, 0x40, 0xa5, 0x20, 0xa5, 0x20, 0xa5,
- 0x20, 0x45, 0x40, 0x2d, 0x0c, 0x0e, 0x0f, 0x2d,
- 0x00, 0x0f, 0x6c, 0x2f, 0xe0, 0x02, 0x5b, 0x2f,
- 0x20, 0xe5, 0x04, 0x00, 0xe5, 0x12, 0x00, 0xe5,
- 0x0b, 0x00, 0x25, 0x00, 0xe5, 0x07, 0x20, 0xe5,
- 0x06, 0xe0, 0x1a, 0xe5, 0x73, 0x80, 0x56, 0x60,
- 0xeb, 0x25, 0x40, 0xef, 0x01, 0xea, 0x2d, 0x6b,
- 0xef, 0x09, 0x2b, 0x4f, 0x00, 0xef, 0x05, 0x40,
- 0x0f, 0xe0, 0x27, 0xef, 0x25, 0x06, 0xe0, 0x7a,
- 0xe5, 0x15, 0x40, 0xe5, 0x29, 0xe0, 0x07, 0x06,
- 0xeb, 0x13, 0x60, 0xe5, 0x18, 0x6b, 0xe0, 0x01,
- 0xe5, 0x0c, 0x0a, 0xe5, 0x00, 0x0a, 0x80, 0xe5,
- 0x1e, 0x86, 0x80, 0xe5, 0x16, 0x00, 0x16, 0xe5,
- 0x1c, 0x60, 0xe5, 0x00, 0x16, 0x8a, 0xe0, 0x22,
- 0xe1, 0x20, 0xe2, 0x20, 0xe5, 0x46, 0x20, 0xe9,
- 0x02, 0xa0, 0xe1, 0x1c, 0x60, 0xe2, 0x1c, 0x60,
- 0xe5, 0x20, 0xe0, 0x00, 0xe5, 0x2c, 0xe0, 0x03,
- 0x16, 0xe1, 0x03, 0x00, 0xe1, 0x07, 0x00, 0xc1,
- 0x00, 0x21, 0x00, 0xe2, 0x03, 0x00, 0xe2, 0x07,
- 0x00, 0xc2, 0x00, 0x22, 0xe0, 0x3b, 0xe5, 0x80,
- 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02, 0xe5,
- 0x00, 0xe0, 0x10, 0xa4, 0x00, 0xe4, 0x22, 0x00,
- 0xe4, 0x01, 0xe0, 0x3d, 0xa5, 0x20, 0x05, 0x00,
- 0xe5, 0x24, 0x00, 0x25, 0x40, 0x05, 0x20, 0xe5,
- 0x0f, 0x00, 0x16, 0xeb, 0x00, 0xe5, 0x0f, 0x2f,
- 0xcb, 0xe5, 0x17, 0xe0, 0x00, 0xeb, 0x01, 0xe0,
- 0x28, 0xe5, 0x0b, 0x00, 0x25, 0x80, 0x8b, 0xe5,
- 0x0e, 0xab, 0x40, 0x16, 0xe5, 0x12, 0x80, 0x16,
- 0xe0, 0x38, 0xe5, 0x30, 0x60, 0x2b, 0x25, 0xeb,
- 0x08, 0x20, 0xeb, 0x26, 0x05, 0x46, 0x00, 0x26,
- 0x80, 0x66, 0x65, 0x00, 0x45, 0x00, 0xe5, 0x15,
- 0x20, 0x46, 0x60, 0x06, 0xeb, 0x01, 0xc0, 0xf6,
- 0x01, 0xc0, 0xe5, 0x15, 0x2b, 0x16, 0xe5, 0x15,
- 0x4b, 0xe0, 0x18, 0xe5, 0x00, 0x0f, 0xe5, 0x14,
- 0x26, 0x60, 0x8b, 0xd6, 0xe0, 0x01, 0xe5, 0x2e,
- 0x40, 0xd6, 0xe5, 0x0e, 0x20, 0xeb, 0x00, 0xe5,
- 0x0b, 0x80, 0xeb, 0x00, 0xe5, 0x0a, 0xc0, 0x76,
- 0xe0, 0x04, 0xcb, 0xe0, 0x48, 0xe5, 0x41, 0xe0,
- 0x2f, 0xe1, 0x2b, 0xe0, 0x05, 0xe2, 0x2b, 0xc0,
- 0xab, 0xe5, 0x1c, 0x66, 0xe0, 0x00, 0xe9, 0x02,
- 0xe0, 0x80, 0x9e, 0xeb, 0x17, 0x00, 0xe5, 0x22,
- 0x00, 0x26, 0x11, 0x20, 0x25, 0xe0, 0x46, 0xe5,
- 0x15, 0xeb, 0x02, 0x05, 0xe0, 0x00, 0xe5, 0x0e,
- 0xe6, 0x03, 0x6b, 0x96, 0xe0, 0x0e, 0xe5, 0x0a,
- 0x66, 0x76, 0xe0, 0x1e, 0xe5, 0x0d, 0xcb, 0xe0,
- 0x0c, 0xe5, 0x0f, 0xe0, 0x01, 0x07, 0x06, 0x07,
- 0xe5, 0x2d, 0xe6, 0x07, 0xd6, 0x60, 0xeb, 0x0c,
- 0xe9, 0x02, 0x06, 0x25, 0x26, 0x05, 0xe0, 0x01,
- 0x46, 0x07, 0xe5, 0x25, 0x47, 0x66, 0x27, 0x26,
- 0x36, 0x1b, 0x76, 0x06, 0xe0, 0x02, 0x1b, 0x20,
- 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0, 0x46, 0xe5,
- 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00, 0xe9, 0x02,
- 0x76, 0x05, 0x27, 0x05, 0xe0, 0x00, 0xe5, 0x1b,
- 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26, 0x07, 0xe5,
- 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65, 0x76, 0x66,
- 0x16, 0x07, 0x06, 0xe9, 0x02, 0x05, 0x16, 0x05,
- 0x56, 0x00, 0xeb, 0x0c, 0xe0, 0x03, 0xe5, 0x0a,
- 0x00, 0xe5, 0x11, 0x47, 0x46, 0x27, 0x06, 0x07,
- 0x26, 0xb6, 0x06, 0xe0, 0x39, 0xc5, 0x00, 0x05,
- 0x00, 0x65, 0x00, 0xe5, 0x07, 0x00, 0xe5, 0x02,
- 0x16, 0xa0, 0xe5, 0x27, 0x06, 0x47, 0xe6, 0x00,
- 0x80, 0xe9, 0x02, 0xa0, 0x26, 0x27, 0x00, 0xe5,
- 0x00, 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5,
- 0x00, 0x25, 0x00, 0x85, 0x00, 0x26, 0x05, 0x27,
- 0x06, 0x67, 0x20, 0x27, 0x20, 0x47, 0x20, 0x05,
- 0xa0, 0x07, 0x80, 0x85, 0x27, 0x20, 0xc6, 0x40,
- 0x86, 0xe0, 0x80, 0x03, 0xe5, 0x2d, 0x47, 0xe6,
- 0x00, 0x27, 0x46, 0x07, 0x06, 0x65, 0x96, 0xe9,
- 0x02, 0x36, 0x00, 0x16, 0x06, 0x45, 0xe0, 0x16,
- 0xe5, 0x28, 0x47, 0xa6, 0x07, 0x06, 0x67, 0x26,
- 0x07, 0x26, 0x25, 0x16, 0x05, 0xe0, 0x00, 0xe9,
- 0x02, 0xe0, 0x80, 0x1e, 0xe5, 0x27, 0x47, 0x66,
- 0x20, 0x67, 0x26, 0x07, 0x26, 0xf6, 0x0f, 0x65,
- 0x26, 0xe0, 0x1a, 0xe5, 0x28, 0x47, 0xe6, 0x00,
- 0x27, 0x06, 0x07, 0x26, 0x56, 0x05, 0xe0, 0x03,
- 0xe9, 0x02, 0xa0, 0xf6, 0x05, 0xe0, 0x0b, 0xe5,
- 0x23, 0x06, 0x07, 0x06, 0x27, 0xa6, 0x07, 0x06,
- 0x05, 0x16, 0xa0, 0xe9, 0x02, 0xe0, 0x2e, 0xe5,
- 0x13, 0x20, 0x46, 0x27, 0x66, 0x07, 0x86, 0x60,
- 0xe9, 0x02, 0x2b, 0x56, 0x0f, 0xc5, 0xe0, 0x80,
- 0x31, 0xe5, 0x24, 0x47, 0xe6, 0x01, 0x07, 0x26,
- 0x16, 0xe0, 0x5c, 0xe1, 0x18, 0xe2, 0x18, 0xe9,
- 0x02, 0xeb, 0x01, 0xe0, 0x04, 0xe5, 0x00, 0x20,
- 0x05, 0x20, 0xe5, 0x00, 0x00, 0x25, 0x00, 0xe5,
- 0x10, 0xa7, 0x00, 0x27, 0x20, 0x26, 0x07, 0x06,
- 0x05, 0x07, 0x05, 0x07, 0x06, 0x56, 0xe0, 0x01,
- 0xe9, 0x02, 0xe0, 0x3e, 0xe5, 0x00, 0x20, 0xe5,
- 0x1f, 0x47, 0x66, 0x20, 0x26, 0x67, 0x06, 0x05,
- 0x16, 0x05, 0x07, 0xe0, 0x13, 0x05, 0xe6, 0x02,
- 0xe5, 0x20, 0xa6, 0x07, 0x05, 0x66, 0xf6, 0x00,
- 0x06, 0xe0, 0x00, 0x05, 0xa6, 0x27, 0x46, 0xe5,
- 0x26, 0xe6, 0x05, 0x07, 0x26, 0x56, 0x05, 0x96,
- 0xe0, 0x05, 0xe5, 0x41, 0xe0, 0x80, 0x7f, 0xe5,
- 0x01, 0x00, 0xe5, 0x1d, 0x07, 0xc6, 0x00, 0xa6,
- 0x07, 0x06, 0x05, 0x96, 0xe0, 0x02, 0xe9, 0x02,
- 0xeb, 0x0b, 0x40, 0x36, 0xe5, 0x16, 0x20, 0xe6,
- 0x0e, 0x00, 0x07, 0xc6, 0x07, 0x26, 0x07, 0x26,
- 0xe0, 0x41, 0xc5, 0x00, 0x25, 0x00, 0xe5, 0x1e,
- 0xa6, 0x40, 0x06, 0x00, 0x26, 0x00, 0xc6, 0x05,
- 0x06, 0xe0, 0x00, 0xe9, 0x02, 0xa0, 0xa5, 0x00,
- 0x25, 0x00, 0xe5, 0x18, 0x87, 0x00, 0x26, 0x00,
- 0x27, 0x06, 0x07, 0x06, 0x05, 0xc0, 0xe9, 0x02,
- 0xe0, 0x80, 0xae, 0xe5, 0x0b, 0x26, 0x27, 0x36,
- 0xe0, 0x80, 0x2f, 0x05, 0xe0, 0x07, 0xeb, 0x0d,
- 0xef, 0x00, 0x6d, 0xef, 0x09, 0xe0, 0x05, 0x16,
- 0xe5, 0x83, 0x12, 0xe0, 0x5e, 0xea, 0x67, 0x00,
- 0x96, 0xe0, 0x03, 0xe5, 0x80, 0x3c, 0xe0, 0x89,
- 0xc4, 0xe5, 0x59, 0x36, 0xe0, 0x05, 0xe5, 0x83,
- 0xa7, 0x00, 0xfb, 0x01, 0xe0, 0x8f, 0x3f, 0xe5,
- 0x81, 0xbf, 0xe0, 0xa1, 0x31, 0xe5, 0x81, 0xb1,
- 0xc0, 0xe5, 0x17, 0x00, 0xe9, 0x02, 0x60, 0x36,
- 0xe5, 0x47, 0x00, 0xe9, 0x02, 0xa0, 0xe5, 0x16,
- 0x20, 0x86, 0x16, 0xe0, 0x02, 0xe5, 0x28, 0xc6,
- 0x96, 0x6f, 0x64, 0x16, 0x0f, 0xe0, 0x02, 0xe9,
- 0x02, 0x00, 0xcb, 0x00, 0xe5, 0x0d, 0x80, 0xe5,
- 0x0b, 0xe0, 0x82, 0x28, 0xe1, 0x18, 0xe2, 0x18,
- 0xeb, 0x0f, 0x76, 0xe0, 0x5d, 0xe5, 0x43, 0x60,
- 0x06, 0x05, 0xe7, 0x2f, 0xc0, 0x66, 0xe4, 0x05,
- 0xe0, 0x38, 0x24, 0x16, 0x04, 0x06, 0xe0, 0x03,
- 0x27, 0xe0, 0x06, 0xe5, 0x97, 0x70, 0xe0, 0x00,
- 0xe5, 0x84, 0x4e, 0xe0, 0x22, 0xe5, 0x01, 0xe0,
- 0xa2, 0x5f, 0x64, 0x00, 0xc4, 0x00, 0x24, 0x00,
- 0xe5, 0x80, 0x9b, 0xe0, 0x25, 0x45, 0xe0, 0x09,
- 0x65, 0xe0, 0x00, 0xe5, 0x81, 0x04, 0xe0, 0x88,
- 0x7c, 0xe5, 0x63, 0x80, 0xe5, 0x05, 0x40, 0xe5,
- 0x01, 0xc0, 0xe5, 0x02, 0x20, 0x0f, 0x26, 0x16,
- 0x7b, 0xe0, 0x91, 0xd4, 0xe6, 0x26, 0x20, 0xe6,
- 0x0f, 0xe0, 0x01, 0xef, 0x6c, 0xe0, 0x34, 0xef,
- 0x80, 0x6e, 0xe0, 0x02, 0xef, 0x1f, 0x20, 0xef,
- 0x34, 0x27, 0x46, 0x4f, 0xa7, 0xfb, 0x00, 0xe6,
- 0x00, 0x2f, 0xc6, 0xef, 0x16, 0x66, 0xef, 0x35,
- 0xe0, 0x0d, 0xef, 0x3a, 0x46, 0x0f, 0xe0, 0x80,
- 0x12, 0xeb, 0x0c, 0xe0, 0x04, 0xef, 0x4f, 0xe0,
- 0x01, 0xeb, 0x11, 0xe0, 0x7f, 0xe1, 0x12, 0xe2,
- 0x12, 0xe1, 0x12, 0xc2, 0x00, 0xe2, 0x0a, 0xe1,
- 0x12, 0xe2, 0x12, 0x01, 0x00, 0x21, 0x20, 0x01,
- 0x20, 0x21, 0x20, 0x61, 0x00, 0xe1, 0x00, 0x62,
- 0x00, 0x02, 0x00, 0xc2, 0x00, 0xe2, 0x03, 0xe1,
- 0x12, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x20, 0xe1,
- 0x00, 0x00, 0xc1, 0x00, 0xe2, 0x12, 0x21, 0x00,
- 0x61, 0x00, 0x81, 0x00, 0x01, 0x40, 0xc1, 0x00,
- 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12,
- 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12,
- 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12,
- 0xe2, 0x14, 0x20, 0xe1, 0x11, 0x0c, 0xe2, 0x11,
- 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c,
- 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2,
+ 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, 0x37, 0x12,
+ 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, 0x13, 0xec,
+ 0x80, 0x7a, 0xef, 0x28, 0xec, 0x0d, 0x2f, 0xac,
+ 0xef, 0x1f, 0x20, 0xef, 0x18, 0x00, 0xef, 0x61,
+ 0xe1, 0x28, 0xe2, 0x28, 0x5f, 0x21, 0x22, 0xdf,
+ 0x41, 0x02, 0x3f, 0x02, 0x3f, 0x82, 0x24, 0x41,
+ 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, 0x46, 0x3f,
+ 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00, 0x02,
+ 0x80, 0x02, 0x20, 0xe5, 0x30, 0xc0, 0x04, 0x16,
+ 0xe0, 0x06, 0x06, 0xe5, 0x0f, 0xe0, 0x01, 0xc5,
+ 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5,
+ 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xe6,
+ 0x18, 0x36, 0x14, 0x15, 0x14, 0x15, 0x56, 0x14,
+ 0x15, 0x16, 0x14, 0x15, 0xf6, 0x01, 0x11, 0x36,
+ 0x11, 0x16, 0x14, 0x15, 0x36, 0x14, 0x15, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x96,
+ 0x04, 0xf6, 0x02, 0x31, 0x76, 0x11, 0x16, 0x12,
+ 0xf6, 0x05, 0x2f, 0x56, 0x12, 0x13, 0x12, 0x13,
+ 0x12, 0x13, 0x12, 0x13, 0x11, 0xe0, 0x1a, 0xef,
+ 0x12, 0x00, 0xef, 0x51, 0xe0, 0x04, 0xef, 0x80,
+ 0x4e, 0xe0, 0x12, 0xef, 0x04, 0x60, 0x17, 0x56,
+ 0x0f, 0x04, 0x05, 0x0a, 0x12, 0x13, 0x12, 0x13,
+ 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x2f, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x11,
+ 0x12, 0x33, 0x0f, 0xea, 0x01, 0x66, 0x27, 0x11,
+ 0x84, 0x2f, 0x4a, 0x04, 0x05, 0x16, 0x2f, 0x00,
+ 0xe5, 0x4e, 0x20, 0x26, 0x2e, 0x24, 0x05, 0x11,
+ 0xe5, 0x52, 0x16, 0x44, 0x05, 0x80, 0xe5, 0x23,
+ 0x00, 0xe5, 0x56, 0x00, 0x2f, 0x6b, 0xef, 0x02,
+ 0xe5, 0x18, 0xef, 0x1c, 0xe0, 0x04, 0xe5, 0x08,
+ 0xef, 0x17, 0x00, 0xeb, 0x02, 0xef, 0x16, 0xeb,
+ 0x00, 0x0f, 0xeb, 0x07, 0xef, 0x18, 0xeb, 0x02,
+ 0xef, 0x1f, 0xeb, 0x07, 0xef, 0x80, 0xb8, 0xe5,
+ 0x99, 0x38, 0xef, 0x38, 0xe5, 0xc0, 0x11, 0x8d,
+ 0x04, 0xe5, 0x83, 0xef, 0x40, 0xef, 0x2f, 0xe0,
+ 0x01, 0xe5, 0x20, 0xa4, 0x36, 0xe5, 0x80, 0x84,
+ 0x04, 0x56, 0xe5, 0x08, 0xe9, 0x02, 0x25, 0xe0,
+ 0x0c, 0xff, 0x26, 0x05, 0x06, 0x48, 0x16, 0xe6,
+ 0x02, 0x16, 0x04, 0xff, 0x14, 0x24, 0x26, 0xe5,
+ 0x3e, 0xea, 0x02, 0x26, 0xb6, 0xe0, 0x00, 0xee,
+ 0x0f, 0xe4, 0x01, 0x2e, 0xff, 0x06, 0x22, 0xff,
+ 0x36, 0x04, 0xe2, 0x00, 0x9f, 0xff, 0x02, 0x04,
+ 0x2e, 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d, 0x61,
+ 0x02, 0x81, 0x02, 0xff, 0x07, 0x41, 0x02, 0x3f,
+ 0x80, 0x3f, 0x00, 0x02, 0x00, 0x02, 0x7f, 0xe0,
+ 0x10, 0x44, 0x3f, 0x05, 0x24, 0x02, 0xc5, 0x06,
+ 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f, 0x27, 0x26,
+ 0x07, 0x6f, 0x06, 0x40, 0xab, 0x2f, 0x0d, 0x0f,
+ 0xa0, 0xe5, 0x2c, 0x76, 0xe0, 0x00, 0x27, 0xe5,
+ 0x2a, 0xe7, 0x08, 0x26, 0xe0, 0x00, 0x36, 0xe9,
+ 0x02, 0xa0, 0xe6, 0x0a, 0xa5, 0x56, 0x05, 0x16,
+ 0x25, 0x06, 0xe9, 0x02, 0xe5, 0x14, 0xe6, 0x00,
+ 0x36, 0xe5, 0x0f, 0xe6, 0x03, 0x27, 0xe0, 0x03,
+ 0x16, 0xe5, 0x15, 0x40, 0x46, 0x07, 0xe5, 0x27,
+ 0x06, 0x27, 0x66, 0x27, 0x26, 0x47, 0xf6, 0x05,
+ 0x00, 0x04, 0xe9, 0x02, 0x60, 0x36, 0x85, 0x06,
+ 0x04, 0xe5, 0x01, 0xe9, 0x02, 0x85, 0x00, 0xe5,
+ 0x21, 0xa6, 0x27, 0x26, 0x27, 0x26, 0xe0, 0x01,
+ 0x45, 0x06, 0xe5, 0x00, 0x06, 0x07, 0x20, 0xe9,
+ 0x02, 0x20, 0x76, 0xe5, 0x08, 0x04, 0xa5, 0x4f,
+ 0x05, 0x07, 0x06, 0x07, 0xe5, 0x2a, 0x06, 0x05,
+ 0x46, 0x25, 0x26, 0x85, 0x26, 0x05, 0x06, 0x05,
+ 0xe0, 0x10, 0x25, 0x04, 0x36, 0xe5, 0x03, 0x07,
+ 0x26, 0x27, 0x36, 0x05, 0x24, 0x07, 0x06, 0xe0,
+ 0x02, 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0xe0, 0x01,
+ 0xc5, 0x00, 0xc5, 0x00, 0xe2, 0x23, 0x0e, 0x64,
+ 0xe2, 0x01, 0x04, 0x2e, 0x60, 0xe2, 0x48, 0xe5,
+ 0x1b, 0x27, 0x06, 0x27, 0x06, 0x27, 0x16, 0x07,
+ 0x06, 0x20, 0xe9, 0x02, 0xa0, 0xe5, 0xab, 0x1c,
+ 0xe0, 0x04, 0xe5, 0x0f, 0x60, 0xe5, 0x29, 0x60,
+ 0xfc, 0x87, 0x78, 0xfd, 0x98, 0x78, 0xe5, 0x80,
+ 0xe6, 0x20, 0xe5, 0x62, 0xe0, 0x1e, 0xc2, 0xe0,
+ 0x04, 0x82, 0x80, 0x05, 0x06, 0xe5, 0x02, 0x0c,
+ 0xe5, 0x05, 0x00, 0x85, 0x00, 0x05, 0x00, 0x25,
+ 0x00, 0x25, 0x00, 0xe5, 0x64, 0xee, 0x09, 0xe0,
+ 0x08, 0xe5, 0x80, 0xe3, 0x13, 0x12, 0xef, 0x08,
+ 0xe5, 0x38, 0x20, 0xe5, 0x2e, 0xc0, 0x0f, 0xe0,
+ 0x18, 0xe5, 0x04, 0x0d, 0x4f, 0xe6, 0x08, 0xd6,
+ 0x12, 0x13, 0x16, 0xa0, 0xe6, 0x08, 0x16, 0x31,
+ 0x30, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12,
+ 0x13, 0x36, 0x12, 0x13, 0x76, 0x50, 0x56, 0x00,
+ 0x76, 0x11, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13,
+ 0x56, 0x0c, 0x11, 0x4c, 0x00, 0x16, 0x0d, 0x36,
+ 0x60, 0x85, 0x00, 0xe5, 0x7f, 0x20, 0x1b, 0x00,
+ 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16,
+ 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1,
+ 0x12, 0x12, 0x16, 0x13, 0x0e, 0x10, 0x0e, 0xe2,
+ 0x12, 0x12, 0x0c, 0x13, 0x0c, 0x12, 0x13, 0x16,
+ 0x12, 0x13, 0x36, 0xe5, 0x02, 0x04, 0xe5, 0x25,
+ 0x24, 0xe5, 0x17, 0x40, 0xa5, 0x20, 0xa5, 0x20,
+ 0xa5, 0x20, 0x45, 0x40, 0x2d, 0x0c, 0x0e, 0x0f,
+ 0x2d, 0x00, 0x0f, 0x6c, 0x2f, 0xe0, 0x02, 0x5b,
+ 0x2f, 0x20, 0xe5, 0x04, 0x00, 0xe5, 0x12, 0x00,
+ 0xe5, 0x0b, 0x00, 0x25, 0x00, 0xe5, 0x07, 0x20,
+ 0xe5, 0x06, 0xe0, 0x1a, 0xe5, 0x73, 0x80, 0x56,
+ 0x60, 0xeb, 0x25, 0x40, 0xef, 0x01, 0xea, 0x2d,
+ 0x6b, 0xef, 0x09, 0x2b, 0x4f, 0x00, 0xef, 0x05,
+ 0x40, 0x0f, 0xe0, 0x27, 0xef, 0x25, 0x06, 0xe0,
+ 0x7a, 0xe5, 0x15, 0x40, 0xe5, 0x29, 0xe0, 0x07,
+ 0x06, 0xeb, 0x13, 0x60, 0xe5, 0x18, 0x6b, 0xe0,
+ 0x01, 0xe5, 0x0c, 0x0a, 0xe5, 0x00, 0x0a, 0x80,
+ 0xe5, 0x1e, 0x86, 0x80, 0xe5, 0x16, 0x00, 0x16,
+ 0xe5, 0x1c, 0x60, 0xe5, 0x00, 0x16, 0x8a, 0xe0,
+ 0x22, 0xe1, 0x20, 0xe2, 0x20, 0xe5, 0x46, 0x20,
+ 0xe9, 0x02, 0xa0, 0xe1, 0x1c, 0x60, 0xe2, 0x1c,
+ 0x60, 0xe5, 0x20, 0xe0, 0x00, 0xe5, 0x2c, 0xe0,
+ 0x03, 0x16, 0xe1, 0x03, 0x00, 0xe1, 0x07, 0x00,
+ 0xc1, 0x00, 0x21, 0x00, 0xe2, 0x03, 0x00, 0xe2,
+ 0x07, 0x00, 0xc2, 0x00, 0x22, 0xe0, 0x3b, 0xe5,
+ 0x80, 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02,
+ 0xe5, 0x00, 0xe0, 0x10, 0xa4, 0x00, 0xe4, 0x22,
+ 0x00, 0xe4, 0x01, 0xe0, 0x3d, 0xa5, 0x20, 0x05,
+ 0x00, 0xe5, 0x24, 0x00, 0x25, 0x40, 0x05, 0x20,
+ 0xe5, 0x0f, 0x00, 0x16, 0xeb, 0x00, 0xe5, 0x0f,
+ 0x2f, 0xcb, 0xe5, 0x17, 0xe0, 0x00, 0xeb, 0x01,
+ 0xe0, 0x28, 0xe5, 0x0b, 0x00, 0x25, 0x80, 0x8b,
+ 0xe5, 0x0e, 0xab, 0x40, 0x16, 0xe5, 0x12, 0x80,
+ 0x16, 0xe0, 0x38, 0xe5, 0x30, 0x60, 0x2b, 0x25,
+ 0xeb, 0x08, 0x20, 0xeb, 0x26, 0x05, 0x46, 0x00,
+ 0x26, 0x80, 0x66, 0x65, 0x00, 0x45, 0x00, 0xe5,
+ 0x15, 0x20, 0x46, 0x60, 0x06, 0xeb, 0x01, 0xc0,
+ 0xf6, 0x01, 0xc0, 0xe5, 0x15, 0x2b, 0x16, 0xe5,
+ 0x15, 0x4b, 0xe0, 0x18, 0xe5, 0x00, 0x0f, 0xe5,
+ 0x14, 0x26, 0x60, 0x8b, 0xd6, 0xe0, 0x01, 0xe5,
+ 0x2e, 0x40, 0xd6, 0xe5, 0x0e, 0x20, 0xeb, 0x00,
+ 0xe5, 0x0b, 0x80, 0xeb, 0x00, 0xe5, 0x0a, 0xc0,
+ 0x76, 0xe0, 0x04, 0xcb, 0xe0, 0x48, 0xe5, 0x41,
+ 0xe0, 0x2f, 0xe1, 0x2b, 0xe0, 0x05, 0xe2, 0x2b,
+ 0xc0, 0xab, 0xe5, 0x1c, 0x66, 0xe0, 0x00, 0xe9,
+ 0x02, 0xe0, 0x80, 0x9e, 0xeb, 0x17, 0x00, 0xe5,
+ 0x22, 0x00, 0x26, 0x11, 0x20, 0x25, 0xe0, 0x43,
+ 0x46, 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0, 0x00,
+ 0xe5, 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0, 0x0e,
+ 0xe5, 0x0a, 0x66, 0x76, 0xe0, 0x1e, 0xe5, 0x0d,
+ 0xcb, 0xe0, 0x0c, 0xe5, 0x0f, 0xe0, 0x01, 0x07,
+ 0x06, 0x07, 0xe5, 0x2d, 0xe6, 0x07, 0xd6, 0x60,
+ 0xeb, 0x0c, 0xe9, 0x02, 0x06, 0x25, 0x26, 0x05,
+ 0xe0, 0x01, 0x46, 0x07, 0xe5, 0x25, 0x47, 0x66,
+ 0x27, 0x26, 0x36, 0x1b, 0x76, 0x06, 0xe0, 0x02,
+ 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0,
+ 0x46, 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00,
+ 0xe9, 0x02, 0x76, 0x05, 0x27, 0x05, 0xe0, 0x00,
+ 0xe5, 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26,
+ 0x07, 0xe5, 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65,
+ 0x76, 0x66, 0x16, 0x07, 0x06, 0xe9, 0x02, 0x05,
+ 0x16, 0x05, 0x56, 0x00, 0xeb, 0x0c, 0xe0, 0x03,
+ 0xe5, 0x0a, 0x00, 0xe5, 0x11, 0x47, 0x46, 0x27,
+ 0x06, 0x07, 0x26, 0xb6, 0x06, 0x25, 0x06, 0xe0,
+ 0x36, 0xc5, 0x00, 0x05, 0x00, 0x65, 0x00, 0xe5,
+ 0x07, 0x00, 0xe5, 0x02, 0x16, 0xa0, 0xe5, 0x27,
+ 0x06, 0x47, 0xe6, 0x00, 0x80, 0xe9, 0x02, 0xa0,
+ 0x26, 0x27, 0x00, 0xe5, 0x00, 0x20, 0x25, 0x20,
+ 0xe5, 0x0e, 0x00, 0xc5, 0x00, 0x25, 0x00, 0x85,
+ 0x00, 0x26, 0x05, 0x27, 0x06, 0x67, 0x20, 0x27,
+ 0x20, 0x47, 0x20, 0x05, 0xa0, 0x07, 0x80, 0x85,
+ 0x27, 0x20, 0xc6, 0x40, 0x86, 0xe0, 0x80, 0x03,
+ 0xe5, 0x2d, 0x47, 0xe6, 0x00, 0x27, 0x46, 0x07,
+ 0x06, 0x65, 0x96, 0xe9, 0x02, 0x36, 0x00, 0x16,
+ 0x06, 0x45, 0xe0, 0x16, 0xe5, 0x28, 0x47, 0xa6,
+ 0x07, 0x06, 0x67, 0x26, 0x07, 0x26, 0x25, 0x16,
+ 0x05, 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x1e,
+ 0xe5, 0x27, 0x47, 0x66, 0x20, 0x67, 0x26, 0x07,
+ 0x26, 0xf6, 0x0f, 0x65, 0x26, 0xe0, 0x1a, 0xe5,
+ 0x28, 0x47, 0xe6, 0x00, 0x27, 0x06, 0x07, 0x26,
+ 0x56, 0x05, 0xe0, 0x03, 0xe9, 0x02, 0xa0, 0xf6,
+ 0x05, 0xe0, 0x0b, 0xe5, 0x23, 0x06, 0x07, 0x06,
+ 0x27, 0xa6, 0x07, 0x06, 0x05, 0x16, 0xa0, 0xe9,
+ 0x02, 0xe0, 0x2e, 0xe5, 0x13, 0x20, 0x46, 0x27,
+ 0x66, 0x07, 0x86, 0x60, 0xe9, 0x02, 0x2b, 0x56,
+ 0x0f, 0xc5, 0xe0, 0x80, 0x31, 0xe5, 0x24, 0x47,
+ 0xe6, 0x01, 0x07, 0x26, 0x16, 0xe0, 0x5c, 0xe1,
+ 0x18, 0xe2, 0x18, 0xe9, 0x02, 0xeb, 0x01, 0xe0,
+ 0x04, 0xe5, 0x00, 0x20, 0x05, 0x20, 0xe5, 0x00,
+ 0x00, 0x25, 0x00, 0xe5, 0x10, 0xa7, 0x00, 0x27,
+ 0x20, 0x26, 0x07, 0x06, 0x05, 0x07, 0x05, 0x07,
+ 0x06, 0x56, 0xe0, 0x01, 0xe9, 0x02, 0xe0, 0x3e,
+ 0xe5, 0x00, 0x20, 0xe5, 0x1f, 0x47, 0x66, 0x20,
+ 0x26, 0x67, 0x06, 0x05, 0x16, 0x05, 0x07, 0xe0,
+ 0x13, 0x05, 0xe6, 0x02, 0xe5, 0x20, 0xa6, 0x07,
+ 0x05, 0x66, 0xf6, 0x00, 0x06, 0xe0, 0x00, 0x05,
+ 0xa6, 0x27, 0x46, 0xe5, 0x26, 0xe6, 0x05, 0x07,
+ 0x26, 0x56, 0x05, 0x96, 0xe0, 0x05, 0xe5, 0x41,
+ 0xc0, 0xf6, 0x02, 0xe0, 0x80, 0x6e, 0xe5, 0x01,
+ 0x00, 0xe5, 0x1d, 0x07, 0xc6, 0x00, 0xa6, 0x07,
+ 0x06, 0x05, 0x96, 0xe0, 0x02, 0xe9, 0x02, 0xeb,
+ 0x0b, 0x40, 0x36, 0xe5, 0x16, 0x20, 0xe6, 0x0e,
+ 0x00, 0x07, 0xc6, 0x07, 0x26, 0x07, 0x26, 0xe0,
+ 0x41, 0xc5, 0x00, 0x25, 0x00, 0xe5, 0x1e, 0xa6,
+ 0x40, 0x06, 0x00, 0x26, 0x00, 0xc6, 0x05, 0x06,
+ 0xe0, 0x00, 0xe9, 0x02, 0xa0, 0xa5, 0x00, 0x25,
+ 0x00, 0xe5, 0x18, 0x87, 0x00, 0x26, 0x00, 0x27,
+ 0x06, 0x07, 0x06, 0x05, 0xc0, 0xe9, 0x02, 0xe0,
+ 0x80, 0xae, 0xe5, 0x0b, 0x26, 0x27, 0x36, 0xc0,
+ 0x26, 0x05, 0x07, 0xe5, 0x05, 0x00, 0xe5, 0x1a,
+ 0x27, 0x86, 0x40, 0x27, 0x06, 0x07, 0x06, 0xf6,
+ 0x05, 0xe9, 0x02, 0xe0, 0x4e, 0x05, 0xe0, 0x07,
+ 0xeb, 0x0d, 0xef, 0x00, 0x6d, 0xef, 0x09, 0xe0,
+ 0x05, 0x16, 0xe5, 0x83, 0x12, 0xe0, 0x5e, 0xea,
+ 0x67, 0x00, 0x96, 0xe0, 0x03, 0xe5, 0x80, 0x3c,
+ 0xe0, 0x89, 0xc4, 0xe5, 0x59, 0x36, 0xe0, 0x05,
+ 0xe5, 0x83, 0xa8, 0xfb, 0x08, 0x06, 0xa5, 0xe6,
+ 0x07, 0xe0, 0x8f, 0x22, 0xe5, 0x81, 0xbf, 0xe0,
+ 0xa1, 0x31, 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17,
+ 0x00, 0xe9, 0x02, 0x60, 0x36, 0xe5, 0x47, 0x00,
+ 0xe9, 0x02, 0xa0, 0xe5, 0x16, 0x20, 0x86, 0x16,
+ 0xe0, 0x02, 0xe5, 0x28, 0xc6, 0x96, 0x6f, 0x64,
+ 0x16, 0x0f, 0xe0, 0x02, 0xe9, 0x02, 0x00, 0xcb,
+ 0x00, 0xe5, 0x0d, 0x80, 0xe5, 0x0b, 0xe0, 0x82,
+ 0x28, 0xe1, 0x18, 0xe2, 0x18, 0xeb, 0x0f, 0x76,
+ 0xe0, 0x5d, 0xe5, 0x43, 0x60, 0x06, 0x05, 0xe7,
+ 0x2f, 0xc0, 0x66, 0xe4, 0x05, 0xe0, 0x38, 0x24,
+ 0x16, 0x04, 0x06, 0xe0, 0x03, 0x27, 0xe0, 0x06,
+ 0xe5, 0x97, 0x70, 0xe0, 0x00, 0xe5, 0x84, 0x4e,
+ 0xe0, 0x22, 0xe5, 0x01, 0xe0, 0xa2, 0x5f, 0x64,
+ 0x00, 0xc4, 0x00, 0x24, 0x00, 0xe5, 0x80, 0x9b,
+ 0xe0, 0x07, 0x05, 0xe0, 0x15, 0x45, 0x20, 0x05,
+ 0xe0, 0x06, 0x65, 0xe0, 0x00, 0xe5, 0x81, 0x04,
+ 0xe0, 0x88, 0x7c, 0xe5, 0x63, 0x80, 0xe5, 0x05,
+ 0x40, 0xe5, 0x01, 0xc0, 0xe5, 0x02, 0x20, 0x0f,
+ 0x26, 0x16, 0x7b, 0xe0, 0x91, 0xd4, 0xe6, 0x26,
+ 0x20, 0xe6, 0x0f, 0xe0, 0x01, 0xef, 0x6c, 0xe0,
+ 0x34, 0xef, 0x80, 0x6e, 0xe0, 0x02, 0xef, 0x1f,
+ 0x20, 0xef, 0x34, 0x27, 0x46, 0x4f, 0xa7, 0xfb,
+ 0x00, 0xe6, 0x00, 0x2f, 0xc6, 0xef, 0x16, 0x66,
+ 0xef, 0x35, 0xe0, 0x0d, 0xef, 0x3a, 0x46, 0x0f,
+ 0xe0, 0x72, 0xeb, 0x0c, 0xe0, 0x04, 0xeb, 0x0c,
+ 0xe0, 0x04, 0xef, 0x4f, 0xe0, 0x01, 0xeb, 0x11,
+ 0xe0, 0x7f, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12,
+ 0xc2, 0x00, 0xe2, 0x0a, 0xe1, 0x12, 0xe2, 0x12,
+ 0x01, 0x00, 0x21, 0x20, 0x01, 0x20, 0x21, 0x20,
+ 0x61, 0x00, 0xe1, 0x00, 0x62, 0x00, 0x02, 0x00,
+ 0xc2, 0x00, 0xe2, 0x03, 0xe1, 0x12, 0xe2, 0x12,
+ 0x21, 0x00, 0x61, 0x20, 0xe1, 0x00, 0x00, 0xc1,
+ 0x00, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x00, 0x81,
+ 0x00, 0x01, 0x40, 0xc1, 0x00, 0xe2, 0x12, 0xe1,
+ 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1,
+ 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1,
+ 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x14, 0x20,
0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1,
- 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0x3f, 0x20,
- 0xe9, 0x2a, 0xef, 0x81, 0x78, 0xe6, 0x2f, 0x6f,
- 0xe6, 0x2a, 0xef, 0x00, 0x06, 0xef, 0x06, 0x06,
- 0x2f, 0x96, 0xe0, 0x07, 0x86, 0x00, 0xe6, 0x07,
- 0xe0, 0x83, 0xc8, 0xe2, 0x02, 0x05, 0xe2, 0x0c,
- 0xe0, 0x80, 0x59, 0xc6, 0x00, 0xe6, 0x09, 0x20,
- 0xc6, 0x00, 0x26, 0x00, 0x86, 0xe0, 0x80, 0x4d,
- 0xe5, 0x25, 0x40, 0xc6, 0xc4, 0x20, 0xe9, 0x02,
- 0x60, 0x05, 0x0f, 0xe0, 0x80, 0xb8, 0xe5, 0x16,
- 0x06, 0xe0, 0x09, 0xe5, 0x24, 0x66, 0xe9, 0x02,
- 0x80, 0x0d, 0xe0, 0x84, 0x58, 0xc5, 0x00, 0x65,
- 0x00, 0x25, 0x00, 0xe5, 0x07, 0x00, 0xe5, 0x80,
- 0x3d, 0x20, 0xeb, 0x01, 0xc6, 0xe0, 0x21, 0xe1,
- 0x1a, 0xe2, 0x1a, 0xc6, 0x04, 0x60, 0xe9, 0x02,
- 0x60, 0x36, 0xe0, 0x82, 0x89, 0xeb, 0x33, 0x0f,
- 0x4b, 0x0d, 0x6b, 0xe0, 0x44, 0xeb, 0x25, 0x0f,
- 0xeb, 0x07, 0xe0, 0x80, 0x3a, 0x65, 0x00, 0xe5,
- 0x13, 0x00, 0x25, 0x00, 0x05, 0x20, 0x05, 0x00,
- 0xe5, 0x02, 0x00, 0x65, 0x00, 0x05, 0x00, 0x05,
- 0xa0, 0x05, 0x60, 0x05, 0x00, 0x05, 0x00, 0x05,
- 0x00, 0x45, 0x00, 0x25, 0x00, 0x05, 0x20, 0x05,
- 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05,
- 0x00, 0x25, 0x00, 0x05, 0x20, 0x65, 0x00, 0xc5,
- 0x00, 0x65, 0x00, 0x65, 0x00, 0x05, 0x00, 0xe5,
- 0x02, 0x00, 0xe5, 0x09, 0x80, 0x45, 0x00, 0x85,
- 0x00, 0xe5, 0x09, 0xe0, 0x2c, 0x2c, 0xe0, 0x80,
- 0x86, 0xef, 0x24, 0x60, 0xef, 0x5c, 0xe0, 0x04,
- 0xef, 0x07, 0x20, 0xef, 0x07, 0x00, 0xef, 0x07,
- 0x00, 0xef, 0x1d, 0xe0, 0x02, 0xeb, 0x05, 0xef,
- 0x80, 0x19, 0xe0, 0x30, 0xef, 0x15, 0xe0, 0x05,
- 0xef, 0x24, 0x60, 0xef, 0x01, 0xc0, 0x2f, 0xe0,
- 0x06, 0xaf, 0xe0, 0x80, 0x12, 0xef, 0x80, 0x73,
- 0x8e, 0xef, 0x82, 0x50, 0x80, 0xef, 0x08, 0x40,
- 0xef, 0x05, 0x40, 0xef, 0x6c, 0xe0, 0x04, 0xef,
- 0x51, 0xc0, 0xef, 0x04, 0x60, 0x0f, 0xe0, 0x07,
- 0xef, 0x04, 0x60, 0xef, 0x30, 0xe0, 0x00, 0xef,
- 0x02, 0xa0, 0xef, 0x20, 0xe0, 0x00, 0xef, 0x16,
- 0x20, 0x2f, 0xe0, 0x46, 0xef, 0x80, 0xcc, 0xe0,
- 0x04, 0xef, 0x06, 0x20, 0x8f, 0x40, 0x8f, 0x40,
- 0xcf, 0xe0, 0x01, 0xef, 0x15, 0x40, 0xef, 0x03,
- 0x80, 0xaf, 0xe0, 0x02, 0xef, 0x02, 0xa0, 0xef,
- 0x00, 0xe0, 0x00, 0xcf, 0xe0, 0x01, 0xef, 0x80,
- 0x0b, 0x00, 0xef, 0x2f, 0xe0, 0x1d, 0xe9, 0x02,
- 0xe0, 0x83, 0x7e, 0xe5, 0xc0, 0x66, 0x58, 0xe0,
- 0x18, 0xe5, 0x8f, 0xb1, 0xc0, 0xe5, 0x80, 0x56,
- 0x20, 0xe5, 0x95, 0xfa, 0xe0, 0x06, 0xe5, 0x9c,
- 0xa9, 0xe0, 0x8b, 0x97, 0xe5, 0x81, 0x96, 0xe0,
- 0x85, 0x5a, 0xe5, 0x92, 0xc3, 0xe0, 0xca, 0xac,
- 0x2e, 0x1b, 0xe0, 0x16, 0xfb, 0x58, 0xe0, 0x78,
- 0xe6, 0x80, 0x68, 0xe0, 0xc0, 0xbd, 0x88, 0xfd,
- 0xc0, 0xbf, 0x76, 0x20, 0xfd, 0xc0, 0xbf, 0x76,
- 0x20,
+ 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11,
+ 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c,
+ 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2,
+ 0x11, 0x0c, 0xa2, 0x3f, 0x20, 0xe9, 0x2a, 0xef,
+ 0x81, 0x78, 0xe6, 0x2f, 0x6f, 0xe6, 0x2a, 0xef,
+ 0x00, 0x06, 0xef, 0x06, 0x06, 0x2f, 0x96, 0xe0,
+ 0x07, 0x86, 0x00, 0xe6, 0x07, 0xe0, 0x83, 0xc8,
+ 0xe2, 0x02, 0x05, 0xe2, 0x0c, 0xa0, 0xa2, 0xe0,
+ 0x80, 0x4d, 0xc6, 0x00, 0xe6, 0x09, 0x20, 0xc6,
+ 0x00, 0x26, 0x00, 0x86, 0x80, 0xe4, 0x36, 0xe0,
+ 0x19, 0x06, 0xe0, 0x68, 0xe5, 0x25, 0x40, 0xc6,
+ 0xc4, 0x20, 0xe9, 0x02, 0x60, 0x05, 0x0f, 0xe0,
+ 0x80, 0xb8, 0xe5, 0x16, 0x06, 0xe0, 0x09, 0xe5,
+ 0x24, 0x66, 0xe9, 0x02, 0x80, 0x0d, 0xe0, 0x81,
+ 0x48, 0xe5, 0x13, 0x04, 0x66, 0xe9, 0x02, 0xe0,
+ 0x82, 0x5e, 0xc5, 0x00, 0x65, 0x00, 0x25, 0x00,
+ 0xe5, 0x07, 0x00, 0xe5, 0x80, 0x3d, 0x20, 0xeb,
+ 0x01, 0xc6, 0xe0, 0x21, 0xe1, 0x1a, 0xe2, 0x1a,
+ 0xc6, 0x04, 0x60, 0xe9, 0x02, 0x60, 0x36, 0xe0,
+ 0x82, 0x89, 0xeb, 0x33, 0x0f, 0x4b, 0x0d, 0x6b,
+ 0xe0, 0x44, 0xeb, 0x25, 0x0f, 0xeb, 0x07, 0xe0,
+ 0x80, 0x3a, 0x65, 0x00, 0xe5, 0x13, 0x00, 0x25,
+ 0x00, 0x05, 0x20, 0x05, 0x00, 0xe5, 0x02, 0x00,
+ 0x65, 0x00, 0x05, 0x00, 0x05, 0xa0, 0x05, 0x60,
+ 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x45, 0x00,
+ 0x25, 0x00, 0x05, 0x20, 0x05, 0x00, 0x05, 0x00,
+ 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x25, 0x00,
+ 0x05, 0x20, 0x65, 0x00, 0xc5, 0x00, 0x65, 0x00,
+ 0x65, 0x00, 0x05, 0x00, 0xe5, 0x02, 0x00, 0xe5,
+ 0x09, 0x80, 0x45, 0x00, 0x85, 0x00, 0xe5, 0x09,
+ 0xe0, 0x2c, 0x2c, 0xe0, 0x80, 0x86, 0xef, 0x24,
+ 0x60, 0xef, 0x5c, 0xe0, 0x04, 0xef, 0x07, 0x20,
+ 0xef, 0x07, 0x00, 0xef, 0x07, 0x00, 0xef, 0x1d,
+ 0xe0, 0x02, 0xeb, 0x05, 0xef, 0x80, 0x19, 0xe0,
+ 0x30, 0xef, 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60,
+ 0xef, 0x01, 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0,
+ 0x80, 0x12, 0xef, 0x80, 0x73, 0x8e, 0xef, 0x82,
+ 0x50, 0x60, 0xef, 0x09, 0x40, 0xef, 0x05, 0x40,
+ 0xef, 0x6f, 0x60, 0xef, 0x57, 0xa0, 0xef, 0x04,
+ 0x60, 0x0f, 0xe0, 0x07, 0xef, 0x04, 0x60, 0xef,
+ 0x30, 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20,
+ 0xe0, 0x00, 0xef, 0x16, 0x20, 0x2f, 0xe0, 0x46,
+ 0xef, 0x80, 0xcc, 0xe0, 0x04, 0xef, 0x06, 0x20,
+ 0xef, 0x05, 0x40, 0xef, 0x01, 0xc0, 0xef, 0x26,
+ 0x00, 0xcf, 0xe0, 0x00, 0xef, 0x06, 0x60, 0xef,
+ 0x01, 0xc0, 0xef, 0x01, 0xc0, 0xef, 0x80, 0x0b,
+ 0x00, 0xef, 0x2f, 0xe0, 0x1d, 0xe9, 0x02, 0xe0,
+ 0x83, 0x7e, 0xe5, 0xc0, 0x66, 0x58, 0xe0, 0x18,
+ 0xe5, 0x8f, 0xb2, 0xa0, 0xe5, 0x80, 0x56, 0x20,
+ 0xe5, 0x95, 0xfa, 0xe0, 0x06, 0xe5, 0x9c, 0xa9,
+ 0xe0, 0x8b, 0x97, 0xe5, 0x81, 0x96, 0xe0, 0x85,
+ 0x5a, 0xe5, 0x92, 0xc3, 0x80, 0xe5, 0x8f, 0xd8,
+ 0xe0, 0xca, 0x9b, 0xc9, 0x1b, 0xe0, 0x16, 0xfb,
+ 0x58, 0xe0, 0x78, 0xe6, 0x80, 0x68, 0xe0, 0xc0,
+ 0xbd, 0x88, 0xfd, 0xc0, 0xbf, 0x76, 0x20, 0xfd,
+ 0xc0, 0xbf, 0x76, 0x20,
};
typedef enum {
@@ -2868,6 +2966,7 @@ typedef enum {
UNICODE_SCRIPT_Kaithi,
UNICODE_SCRIPT_Kannada,
UNICODE_SCRIPT_Katakana,
+ UNICODE_SCRIPT_Kawi,
UNICODE_SCRIPT_Kayah_Li,
UNICODE_SCRIPT_Kharoshthi,
UNICODE_SCRIPT_Khmer,
@@ -2902,6 +3001,7 @@ typedef enum {
UNICODE_SCRIPT_Multani,
UNICODE_SCRIPT_Myanmar,
UNICODE_SCRIPT_Nabataean,
+ UNICODE_SCRIPT_Nag_Mundari,
UNICODE_SCRIPT_Nandinagari,
UNICODE_SCRIPT_New_Tai_Lue,
UNICODE_SCRIPT_Newa,
@@ -3033,6 +3133,7 @@ static const char unicode_script_name_table[] =
"Kaithi,Kthi" "\0"
"Kannada,Knda" "\0"
"Katakana,Kana" "\0"
+ "Kawi,Kawi" "\0"
"Kayah_Li,Kali" "\0"
"Kharoshthi,Khar" "\0"
"Khmer,Khmr" "\0"
@@ -3067,6 +3168,7 @@ static const char unicode_script_name_table[] =
"Multani,Mult" "\0"
"Myanmar,Mymr" "\0"
"Nabataean,Nbat" "\0"
+ "Nag_Mundari,Nagm" "\0"
"Nandinagari,Nand" "\0"
"New_Tai_Lue,Talu" "\0"
"Newa,Newa" "\0"
@@ -3134,12 +3236,12 @@ static const char unicode_script_name_table[] =
"Zanabazar_Square,Zanb" "\0"
;
-static const uint8_t unicode_script_table[2690] = {
- 0xc0, 0x19, 0x99, 0x46, 0x85, 0x19, 0x99, 0x46,
- 0xae, 0x19, 0x80, 0x46, 0x8e, 0x19, 0x80, 0x46,
- 0x84, 0x19, 0x96, 0x46, 0x80, 0x19, 0x9e, 0x46,
- 0x80, 0x19, 0xe1, 0x60, 0x46, 0xa6, 0x19, 0x84,
- 0x46, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0,
+static const uint8_t unicode_script_table[2720] = {
+ 0xc0, 0x19, 0x99, 0x47, 0x85, 0x19, 0x99, 0x47,
+ 0xae, 0x19, 0x80, 0x47, 0x8e, 0x19, 0x80, 0x47,
+ 0x84, 0x19, 0x96, 0x47, 0x80, 0x19, 0x9e, 0x47,
+ 0x80, 0x19, 0xe1, 0x60, 0x47, 0xa6, 0x19, 0x84,
+ 0x47, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0,
0x0f, 0x38, 0x83, 0x2c, 0x80, 0x19, 0x82, 0x2c,
0x01, 0x83, 0x2c, 0x80, 0x19, 0x80, 0x2c, 0x03,
0x80, 0x2c, 0x80, 0x19, 0x80, 0x2c, 0x80, 0x19,
@@ -3152,11 +3254,11 @@ static const uint8_t unicode_script_table[2690] = {
0x80, 0x19, 0x8d, 0x04, 0x80, 0x19, 0x82, 0x04,
0x80, 0x19, 0x9f, 0x04, 0x80, 0x19, 0x89, 0x04,
0x8a, 0x38, 0x99, 0x04, 0x80, 0x38, 0xe0, 0x0b,
- 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x89, 0x00,
- 0xbb, 0x89, 0x01, 0x82, 0x89, 0xaf, 0x04, 0xb1,
- 0x93, 0x0d, 0xba, 0x64, 0x01, 0x82, 0x64, 0xad,
- 0x7d, 0x01, 0x8e, 0x7d, 0x00, 0x9b, 0x51, 0x01,
- 0x80, 0x51, 0x00, 0x8a, 0x89, 0x04, 0x9e, 0x04,
+ 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x8b, 0x00,
+ 0xbb, 0x8b, 0x01, 0x82, 0x8b, 0xaf, 0x04, 0xb1,
+ 0x95, 0x0d, 0xba, 0x66, 0x01, 0x82, 0x66, 0xad,
+ 0x7f, 0x01, 0x8e, 0x7f, 0x00, 0x9b, 0x52, 0x01,
+ 0x80, 0x52, 0x00, 0x8a, 0x8b, 0x04, 0x9e, 0x04,
0x00, 0x81, 0x04, 0x05, 0xc9, 0x04, 0x80, 0x19,
0x9c, 0x04, 0xd0, 0x20, 0x83, 0x38, 0x8e, 0x20,
0x81, 0x19, 0x99, 0x20, 0x83, 0x0b, 0x00, 0x87,
@@ -3176,43 +3278,43 @@ static const uint8_t unicode_script_table[2690] = {
0x84, 0x2d, 0x01, 0x89, 0x2d, 0x00, 0x82, 0x2d,
0x00, 0x82, 0x2d, 0x01, 0x80, 0x2d, 0x0e, 0x83,
0x2d, 0x01, 0x8b, 0x2d, 0x06, 0x86, 0x2d, 0x00,
- 0x82, 0x72, 0x00, 0x87, 0x72, 0x01, 0x81, 0x72,
- 0x01, 0x95, 0x72, 0x00, 0x86, 0x72, 0x00, 0x81,
- 0x72, 0x00, 0x84, 0x72, 0x01, 0x88, 0x72, 0x01,
- 0x81, 0x72, 0x01, 0x82, 0x72, 0x06, 0x82, 0x72,
- 0x03, 0x81, 0x72, 0x00, 0x84, 0x72, 0x01, 0x91,
- 0x72, 0x09, 0x81, 0x90, 0x00, 0x85, 0x90, 0x02,
- 0x82, 0x90, 0x00, 0x83, 0x90, 0x02, 0x81, 0x90,
- 0x00, 0x80, 0x90, 0x00, 0x81, 0x90, 0x02, 0x81,
- 0x90, 0x02, 0x82, 0x90, 0x02, 0x8b, 0x90, 0x03,
- 0x84, 0x90, 0x02, 0x82, 0x90, 0x00, 0x83, 0x90,
- 0x01, 0x80, 0x90, 0x05, 0x80, 0x90, 0x0d, 0x94,
- 0x90, 0x04, 0x8c, 0x92, 0x00, 0x82, 0x92, 0x00,
- 0x96, 0x92, 0x00, 0x8f, 0x92, 0x01, 0x88, 0x92,
- 0x00, 0x82, 0x92, 0x00, 0x83, 0x92, 0x06, 0x81,
- 0x92, 0x00, 0x82, 0x92, 0x01, 0x80, 0x92, 0x01,
- 0x83, 0x92, 0x01, 0x89, 0x92, 0x06, 0x88, 0x92,
+ 0x82, 0x74, 0x00, 0x87, 0x74, 0x01, 0x81, 0x74,
+ 0x01, 0x95, 0x74, 0x00, 0x86, 0x74, 0x00, 0x81,
+ 0x74, 0x00, 0x84, 0x74, 0x01, 0x88, 0x74, 0x01,
+ 0x81, 0x74, 0x01, 0x82, 0x74, 0x06, 0x82, 0x74,
+ 0x03, 0x81, 0x74, 0x00, 0x84, 0x74, 0x01, 0x91,
+ 0x74, 0x09, 0x81, 0x92, 0x00, 0x85, 0x92, 0x02,
+ 0x82, 0x92, 0x00, 0x83, 0x92, 0x02, 0x81, 0x92,
+ 0x00, 0x80, 0x92, 0x00, 0x81, 0x92, 0x02, 0x81,
+ 0x92, 0x02, 0x82, 0x92, 0x02, 0x8b, 0x92, 0x03,
+ 0x84, 0x92, 0x02, 0x82, 0x92, 0x00, 0x83, 0x92,
+ 0x01, 0x80, 0x92, 0x05, 0x80, 0x92, 0x0d, 0x94,
+ 0x92, 0x04, 0x8c, 0x94, 0x00, 0x82, 0x94, 0x00,
+ 0x96, 0x94, 0x00, 0x8f, 0x94, 0x01, 0x88, 0x94,
+ 0x00, 0x82, 0x94, 0x00, 0x83, 0x94, 0x06, 0x81,
+ 0x94, 0x00, 0x82, 0x94, 0x01, 0x80, 0x94, 0x01,
+ 0x83, 0x94, 0x01, 0x89, 0x94, 0x06, 0x88, 0x94,
0x8c, 0x3d, 0x00, 0x82, 0x3d, 0x00, 0x96, 0x3d,
0x00, 0x89, 0x3d, 0x00, 0x84, 0x3d, 0x01, 0x88,
0x3d, 0x00, 0x82, 0x3d, 0x00, 0x83, 0x3d, 0x06,
0x81, 0x3d, 0x05, 0x81, 0x3d, 0x00, 0x83, 0x3d,
- 0x01, 0x89, 0x3d, 0x00, 0x81, 0x3d, 0x0c, 0x8c,
- 0x50, 0x00, 0x82, 0x50, 0x00, 0xb2, 0x50, 0x00,
- 0x82, 0x50, 0x00, 0x85, 0x50, 0x03, 0x8f, 0x50,
- 0x01, 0x99, 0x50, 0x00, 0x82, 0x83, 0x00, 0x91,
- 0x83, 0x02, 0x97, 0x83, 0x00, 0x88, 0x83, 0x00,
- 0x80, 0x83, 0x01, 0x86, 0x83, 0x02, 0x80, 0x83,
- 0x03, 0x85, 0x83, 0x00, 0x80, 0x83, 0x00, 0x87,
- 0x83, 0x05, 0x89, 0x83, 0x01, 0x82, 0x83, 0x0b,
- 0xb9, 0x94, 0x03, 0x80, 0x19, 0x9b, 0x94, 0x24,
- 0x81, 0x45, 0x00, 0x80, 0x45, 0x00, 0x84, 0x45,
- 0x00, 0x97, 0x45, 0x00, 0x80, 0x45, 0x00, 0x96,
- 0x45, 0x01, 0x84, 0x45, 0x00, 0x80, 0x45, 0x00,
- 0x85, 0x45, 0x01, 0x89, 0x45, 0x01, 0x83, 0x45,
- 0x1f, 0xc7, 0x95, 0x00, 0xa3, 0x95, 0x03, 0xa6,
- 0x95, 0x00, 0xa3, 0x95, 0x00, 0x8e, 0x95, 0x00,
- 0x86, 0x95, 0x83, 0x19, 0x81, 0x95, 0x24, 0xe0,
- 0x3f, 0x5f, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
+ 0x01, 0x89, 0x3d, 0x00, 0x82, 0x3d, 0x0b, 0x8c,
+ 0x51, 0x00, 0x82, 0x51, 0x00, 0xb2, 0x51, 0x00,
+ 0x82, 0x51, 0x00, 0x85, 0x51, 0x03, 0x8f, 0x51,
+ 0x01, 0x99, 0x51, 0x00, 0x82, 0x85, 0x00, 0x91,
+ 0x85, 0x02, 0x97, 0x85, 0x00, 0x88, 0x85, 0x00,
+ 0x80, 0x85, 0x01, 0x86, 0x85, 0x02, 0x80, 0x85,
+ 0x03, 0x85, 0x85, 0x00, 0x80, 0x85, 0x00, 0x87,
+ 0x85, 0x05, 0x89, 0x85, 0x01, 0x82, 0x85, 0x0b,
+ 0xb9, 0x96, 0x03, 0x80, 0x19, 0x9b, 0x96, 0x24,
+ 0x81, 0x46, 0x00, 0x80, 0x46, 0x00, 0x84, 0x46,
+ 0x00, 0x97, 0x46, 0x00, 0x80, 0x46, 0x00, 0x96,
+ 0x46, 0x01, 0x84, 0x46, 0x00, 0x80, 0x46, 0x00,
+ 0x86, 0x46, 0x00, 0x89, 0x46, 0x01, 0x83, 0x46,
+ 0x1f, 0xc7, 0x97, 0x00, 0xa3, 0x97, 0x03, 0xa6,
+ 0x97, 0x00, 0xa3, 0x97, 0x00, 0x8e, 0x97, 0x00,
+ 0x86, 0x97, 0x83, 0x19, 0x81, 0x97, 0x24, 0xe0,
+ 0x3f, 0x60, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
0x80, 0x28, 0x01, 0xaa, 0x28, 0x80, 0x19, 0x83,
0x28, 0xe0, 0x9f, 0x31, 0xc8, 0x27, 0x00, 0x83,
0x27, 0x01, 0x86, 0x27, 0x00, 0x80, 0x27, 0x00,
@@ -3222,32 +3324,32 @@ static const uint8_t unicode_script_table[2690] = {
0x8e, 0x27, 0x00, 0xb8, 0x27, 0x00, 0x83, 0x27,
0x01, 0xc2, 0x27, 0x01, 0x9f, 0x27, 0x02, 0x99,
0x27, 0x05, 0xd5, 0x17, 0x01, 0x85, 0x17, 0x01,
- 0xe2, 0x1f, 0x12, 0x9c, 0x67, 0x02, 0xca, 0x7c,
- 0x82, 0x19, 0x8a, 0x7c, 0x06, 0x95, 0x8a, 0x08,
- 0x80, 0x8a, 0x94, 0x33, 0x81, 0x19, 0x08, 0x93,
- 0x11, 0x0b, 0x8c, 0x8b, 0x00, 0x82, 0x8b, 0x00,
- 0x81, 0x8b, 0x0b, 0xdd, 0x41, 0x01, 0x89, 0x41,
- 0x05, 0x89, 0x41, 0x05, 0x81, 0x5c, 0x81, 0x19,
- 0x80, 0x5c, 0x80, 0x19, 0x93, 0x5c, 0x05, 0xd8,
- 0x5c, 0x06, 0xaa, 0x5c, 0x04, 0xc5, 0x12, 0x09,
- 0x9e, 0x48, 0x00, 0x8b, 0x48, 0x03, 0x8b, 0x48,
- 0x03, 0x80, 0x48, 0x02, 0x8b, 0x48, 0x9d, 0x8c,
- 0x01, 0x84, 0x8c, 0x0a, 0xab, 0x62, 0x03, 0x99,
- 0x62, 0x05, 0x8a, 0x62, 0x02, 0x81, 0x62, 0x9f,
- 0x41, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x8d,
- 0x00, 0x9c, 0x8d, 0x01, 0x8a, 0x8d, 0x05, 0x89,
- 0x8d, 0x05, 0x8d, 0x8d, 0x01, 0x9e, 0x38, 0x30,
- 0xcc, 0x07, 0x02, 0xae, 0x07, 0x00, 0xbf, 0x87,
- 0xb3, 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x47, 0x02,
- 0x8e, 0x47, 0x02, 0x82, 0x47, 0xaf, 0x68, 0x88,
+ 0xe2, 0x1f, 0x12, 0x9c, 0x69, 0x02, 0xca, 0x7e,
+ 0x82, 0x19, 0x8a, 0x7e, 0x06, 0x95, 0x8c, 0x08,
+ 0x80, 0x8c, 0x94, 0x33, 0x81, 0x19, 0x08, 0x93,
+ 0x11, 0x0b, 0x8c, 0x8d, 0x00, 0x82, 0x8d, 0x00,
+ 0x81, 0x8d, 0x0b, 0xdd, 0x42, 0x01, 0x89, 0x42,
+ 0x05, 0x89, 0x42, 0x05, 0x81, 0x5d, 0x81, 0x19,
+ 0x80, 0x5d, 0x80, 0x19, 0x93, 0x5d, 0x05, 0xd8,
+ 0x5d, 0x06, 0xaa, 0x5d, 0x04, 0xc5, 0x12, 0x09,
+ 0x9e, 0x49, 0x00, 0x8b, 0x49, 0x03, 0x8b, 0x49,
+ 0x03, 0x80, 0x49, 0x02, 0x8b, 0x49, 0x9d, 0x8e,
+ 0x01, 0x84, 0x8e, 0x0a, 0xab, 0x64, 0x03, 0x99,
+ 0x64, 0x05, 0x8a, 0x64, 0x02, 0x81, 0x64, 0x9f,
+ 0x42, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x8f,
+ 0x00, 0x9c, 0x8f, 0x01, 0x8a, 0x8f, 0x05, 0x89,
+ 0x8f, 0x05, 0x8d, 0x8f, 0x01, 0x9e, 0x38, 0x30,
+ 0xcc, 0x07, 0x02, 0xae, 0x07, 0x00, 0xbf, 0x89,
+ 0xb3, 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x48, 0x02,
+ 0x8e, 0x48, 0x02, 0x82, 0x48, 0xaf, 0x6a, 0x88,
0x1d, 0x06, 0xaa, 0x28, 0x01, 0x82, 0x28, 0x87,
- 0x87, 0x07, 0x82, 0x38, 0x80, 0x19, 0x8c, 0x38,
+ 0x89, 0x07, 0x82, 0x38, 0x80, 0x19, 0x8c, 0x38,
0x80, 0x19, 0x86, 0x38, 0x83, 0x19, 0x80, 0x38,
0x85, 0x19, 0x80, 0x38, 0x82, 0x19, 0x81, 0x38,
- 0x80, 0x19, 0x04, 0xa5, 0x46, 0x84, 0x2c, 0x80,
- 0x1d, 0xb0, 0x46, 0x84, 0x2c, 0x83, 0x46, 0x84,
- 0x2c, 0x8c, 0x46, 0x80, 0x1d, 0xc5, 0x46, 0x80,
- 0x2c, 0xbf, 0x38, 0xe0, 0x9f, 0x46, 0x95, 0x2c,
+ 0x80, 0x19, 0x04, 0xa5, 0x47, 0x84, 0x2c, 0x80,
+ 0x1d, 0xb0, 0x47, 0x84, 0x2c, 0x83, 0x47, 0x84,
+ 0x2c, 0x8c, 0x47, 0x80, 0x1d, 0xc5, 0x47, 0x80,
+ 0x2c, 0xbf, 0x38, 0xe0, 0x9f, 0x47, 0x95, 0x2c,
0x01, 0x85, 0x2c, 0x01, 0xa5, 0x2c, 0x01, 0x85,
0x2c, 0x01, 0x87, 0x2c, 0x00, 0x80, 0x2c, 0x00,
0x80, 0x2c, 0x00, 0x80, 0x2c, 0x00, 0x9e, 0x2c,
@@ -3255,18 +3357,18 @@ static const uint8_t unicode_script_table[2690] = {
0x2c, 0x01, 0x85, 0x2c, 0x00, 0x92, 0x2c, 0x01,
0x82, 0x2c, 0x00, 0x88, 0x2c, 0x00, 0x8b, 0x19,
0x81, 0x38, 0xd6, 0x19, 0x00, 0x8a, 0x19, 0x80,
- 0x46, 0x01, 0x8a, 0x19, 0x80, 0x46, 0x8e, 0x19,
- 0x00, 0x8c, 0x46, 0x02, 0xa0, 0x19, 0x0e, 0xa0,
+ 0x47, 0x01, 0x8a, 0x19, 0x80, 0x47, 0x8e, 0x19,
+ 0x00, 0x8c, 0x47, 0x02, 0xa0, 0x19, 0x0e, 0xa0,
0x38, 0x0e, 0xa5, 0x19, 0x80, 0x2c, 0x82, 0x19,
- 0x81, 0x46, 0x85, 0x19, 0x80, 0x46, 0x9a, 0x19,
- 0x80, 0x46, 0x90, 0x19, 0xa8, 0x46, 0x82, 0x19,
+ 0x81, 0x47, 0x85, 0x19, 0x80, 0x47, 0x9a, 0x19,
+ 0x80, 0x47, 0x90, 0x19, 0xa8, 0x47, 0x82, 0x19,
0x03, 0xe2, 0x36, 0x19, 0x18, 0x8a, 0x19, 0x14,
0xe3, 0x3f, 0x19, 0xe0, 0x9f, 0x0f, 0xe2, 0x13,
0x19, 0x01, 0x9f, 0x19, 0x00, 0xe0, 0x08, 0x19,
- 0xdf, 0x29, 0x9f, 0x46, 0xe0, 0x13, 0x1a, 0x04,
+ 0xdf, 0x29, 0x9f, 0x47, 0xe0, 0x13, 0x1a, 0x04,
0x86, 0x1a, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
- 0x80, 0x28, 0x01, 0xb7, 0x96, 0x06, 0x81, 0x96,
- 0x0d, 0x80, 0x96, 0x96, 0x27, 0x08, 0x86, 0x27,
+ 0x80, 0x28, 0x01, 0xb7, 0x98, 0x06, 0x81, 0x98,
+ 0x0d, 0x80, 0x98, 0x96, 0x27, 0x08, 0x86, 0x27,
0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86,
0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00,
0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x9f, 0x1d,
@@ -3282,27 +3384,27 @@ static const uint8_t unicode_script_table[2690] = {
0x9e, 0x31, 0x00, 0xbf, 0x19, 0x9e, 0x31, 0xd0,
0x19, 0xae, 0x3e, 0x80, 0x19, 0xd7, 0x3e, 0xe0,
0x47, 0x19, 0xf0, 0x09, 0x5f, 0x30, 0xbf, 0x19,
- 0xf0, 0x41, 0x9f, 0x30, 0xe4, 0x2c, 0xa0, 0x02,
- 0xb6, 0xa0, 0x08, 0xaf, 0x4b, 0xe0, 0xcb, 0x9b,
+ 0xf0, 0x41, 0x9f, 0x30, 0xe4, 0x2c, 0xa2, 0x02,
+ 0xb6, 0xa2, 0x08, 0xaf, 0x4c, 0xe0, 0xcb, 0x9d,
0x13, 0xdf, 0x1d, 0xd7, 0x08, 0x07, 0xa1, 0x19,
- 0xe0, 0x05, 0x46, 0x82, 0x19, 0xbf, 0x46, 0x04,
- 0x81, 0x46, 0x00, 0x80, 0x46, 0x00, 0x84, 0x46,
- 0x17, 0x8d, 0x46, 0xac, 0x88, 0x02, 0x89, 0x19,
- 0x05, 0xb7, 0x78, 0x07, 0xc5, 0x7e, 0x07, 0x8b,
- 0x7e, 0x05, 0x9f, 0x20, 0xad, 0x3f, 0x80, 0x19,
- 0x80, 0x3f, 0xa3, 0x7b, 0x0a, 0x80, 0x7b, 0x9c,
+ 0xe0, 0x05, 0x47, 0x82, 0x19, 0xbf, 0x47, 0x04,
+ 0x81, 0x47, 0x00, 0x80, 0x47, 0x00, 0x84, 0x47,
+ 0x17, 0x8d, 0x47, 0xac, 0x8a, 0x02, 0x89, 0x19,
+ 0x05, 0xb7, 0x7a, 0x07, 0xc5, 0x80, 0x07, 0x8b,
+ 0x80, 0x05, 0x9f, 0x20, 0xad, 0x40, 0x80, 0x19,
+ 0x80, 0x40, 0xa3, 0x7d, 0x0a, 0x80, 0x7d, 0x9c,
0x31, 0x02, 0xcd, 0x3b, 0x00, 0x80, 0x19, 0x89,
- 0x3b, 0x03, 0x81, 0x3b, 0x9e, 0x5f, 0x00, 0xb6,
+ 0x3b, 0x03, 0x81, 0x3b, 0x9e, 0x60, 0x00, 0xb6,
0x16, 0x08, 0x8d, 0x16, 0x01, 0x89, 0x16, 0x01,
- 0x83, 0x16, 0x9f, 0x5f, 0xc2, 0x8e, 0x17, 0x84,
- 0x8e, 0x96, 0x56, 0x09, 0x85, 0x27, 0x01, 0x85,
+ 0x83, 0x16, 0x9f, 0x60, 0xc2, 0x90, 0x17, 0x84,
+ 0x90, 0x96, 0x57, 0x09, 0x85, 0x27, 0x01, 0x85,
0x27, 0x01, 0x85, 0x27, 0x08, 0x86, 0x27, 0x00,
- 0x86, 0x27, 0x00, 0xaa, 0x46, 0x80, 0x19, 0x88,
- 0x46, 0x80, 0x2c, 0x83, 0x46, 0x81, 0x19, 0x03,
- 0xcf, 0x17, 0xad, 0x56, 0x01, 0x89, 0x56, 0x05,
+ 0x86, 0x27, 0x00, 0xaa, 0x47, 0x80, 0x19, 0x88,
+ 0x47, 0x80, 0x2c, 0x83, 0x47, 0x81, 0x19, 0x03,
+ 0xcf, 0x17, 0xad, 0x57, 0x01, 0x89, 0x57, 0x05,
0xf0, 0x1b, 0x43, 0x31, 0x0b, 0x96, 0x31, 0x03,
0xb0, 0x31, 0x70, 0x10, 0xa3, 0xe1, 0x0d, 0x30,
- 0x01, 0xe0, 0x09, 0x30, 0x25, 0x86, 0x46, 0x0b,
+ 0x01, 0xe0, 0x09, 0x30, 0x25, 0x86, 0x47, 0x0b,
0x84, 0x05, 0x04, 0x99, 0x35, 0x00, 0x84, 0x35,
0x00, 0x80, 0x35, 0x00, 0x81, 0x35, 0x00, 0x81,
0x35, 0x00, 0x89, 0x35, 0xe0, 0x12, 0x04, 0x0f,
@@ -3311,130 +3413,134 @@ static const uint8_t unicode_script_table[2690] = {
0x8f, 0x38, 0x89, 0x19, 0x05, 0x8d, 0x38, 0x81,
0x1d, 0xa2, 0x19, 0x00, 0x92, 0x19, 0x00, 0x83,
0x19, 0x03, 0x84, 0x04, 0x00, 0xe0, 0x26, 0x04,
- 0x01, 0x80, 0x19, 0x00, 0x9f, 0x19, 0x99, 0x46,
- 0x85, 0x19, 0x99, 0x46, 0x8a, 0x19, 0x89, 0x3e,
+ 0x01, 0x80, 0x19, 0x00, 0x9f, 0x19, 0x99, 0x47,
+ 0x85, 0x19, 0x99, 0x47, 0x8a, 0x19, 0x89, 0x3e,
0x80, 0x19, 0xac, 0x3e, 0x81, 0x19, 0x9e, 0x31,
0x02, 0x85, 0x31, 0x01, 0x85, 0x31, 0x01, 0x85,
0x31, 0x01, 0x82, 0x31, 0x02, 0x86, 0x19, 0x00,
- 0x86, 0x19, 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4a,
- 0x00, 0x99, 0x4a, 0x00, 0x92, 0x4a, 0x00, 0x81,
- 0x4a, 0x00, 0x8e, 0x4a, 0x01, 0x8d, 0x4a, 0x21,
- 0xe0, 0x1a, 0x4a, 0x04, 0x82, 0x19, 0x03, 0xac,
+ 0x86, 0x19, 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4b,
+ 0x00, 0x99, 0x4b, 0x00, 0x92, 0x4b, 0x00, 0x81,
+ 0x4b, 0x00, 0x8e, 0x4b, 0x01, 0x8d, 0x4b, 0x21,
+ 0xe0, 0x1a, 0x4b, 0x04, 0x82, 0x19, 0x03, 0xac,
0x19, 0x02, 0x88, 0x19, 0xce, 0x2c, 0x00, 0x8c,
0x19, 0x02, 0x80, 0x2c, 0x2e, 0xac, 0x19, 0x80,
- 0x38, 0x60, 0x21, 0x9c, 0x4c, 0x02, 0xb0, 0x13,
- 0x0e, 0x80, 0x38, 0x9a, 0x19, 0x03, 0xa3, 0x6a,
- 0x08, 0x82, 0x6a, 0x9a, 0x2a, 0x04, 0xaa, 0x6c,
- 0x04, 0x9d, 0x9a, 0x00, 0x80, 0x9a, 0xa3, 0x6d,
- 0x03, 0x8d, 0x6d, 0x29, 0xcf, 0x1f, 0xaf, 0x80,
- 0x9d, 0x74, 0x01, 0x89, 0x74, 0x05, 0xa3, 0x73,
- 0x03, 0xa3, 0x73, 0x03, 0xa7, 0x25, 0x07, 0xb3,
- 0x14, 0x0a, 0x80, 0x14, 0x8a, 0x9c, 0x00, 0x8e,
- 0x9c, 0x00, 0x86, 0x9c, 0x00, 0x81, 0x9c, 0x00,
- 0x8a, 0x9c, 0x00, 0x8e, 0x9c, 0x00, 0x86, 0x9c,
- 0x00, 0x81, 0x9c, 0x42, 0xe0, 0xd6, 0x49, 0x08,
- 0x95, 0x49, 0x09, 0x87, 0x49, 0x17, 0x85, 0x46,
- 0x00, 0xa9, 0x46, 0x00, 0x88, 0x46, 0x44, 0x85,
+ 0x38, 0x60, 0x21, 0x9c, 0x4d, 0x02, 0xb0, 0x13,
+ 0x0e, 0x80, 0x38, 0x9a, 0x19, 0x03, 0xa3, 0x6c,
+ 0x08, 0x82, 0x6c, 0x9a, 0x2a, 0x04, 0xaa, 0x6e,
+ 0x04, 0x9d, 0x9c, 0x00, 0x80, 0x9c, 0xa3, 0x6f,
+ 0x03, 0x8d, 0x6f, 0x29, 0xcf, 0x1f, 0xaf, 0x82,
+ 0x9d, 0x76, 0x01, 0x89, 0x76, 0x05, 0xa3, 0x75,
+ 0x03, 0xa3, 0x75, 0x03, 0xa7, 0x25, 0x07, 0xb3,
+ 0x14, 0x0a, 0x80, 0x14, 0x8a, 0x9e, 0x00, 0x8e,
+ 0x9e, 0x00, 0x86, 0x9e, 0x00, 0x81, 0x9e, 0x00,
+ 0x8a, 0x9e, 0x00, 0x8e, 0x9e, 0x00, 0x86, 0x9e,
+ 0x00, 0x81, 0x9e, 0x42, 0xe0, 0xd6, 0x4a, 0x08,
+ 0x95, 0x4a, 0x09, 0x87, 0x4a, 0x17, 0x85, 0x47,
+ 0x00, 0xa9, 0x47, 0x00, 0x88, 0x47, 0x44, 0x85,
0x1c, 0x01, 0x80, 0x1c, 0x00, 0xab, 0x1c, 0x00,
0x81, 0x1c, 0x02, 0x80, 0x1c, 0x01, 0x80, 0x1c,
- 0x95, 0x37, 0x00, 0x88, 0x37, 0x9f, 0x76, 0x9e,
- 0x60, 0x07, 0x88, 0x60, 0x2f, 0x92, 0x34, 0x00,
- 0x81, 0x34, 0x04, 0x84, 0x34, 0x9b, 0x79, 0x02,
- 0x80, 0x79, 0x99, 0x4d, 0x04, 0x80, 0x4d, 0x3f,
- 0x9f, 0x59, 0x97, 0x58, 0x03, 0x93, 0x58, 0x01,
- 0xad, 0x58, 0x83, 0x40, 0x00, 0x81, 0x40, 0x04,
- 0x87, 0x40, 0x00, 0x82, 0x40, 0x00, 0x9c, 0x40,
- 0x01, 0x82, 0x40, 0x03, 0x89, 0x40, 0x06, 0x88,
- 0x40, 0x06, 0x9f, 0x6f, 0x9f, 0x6b, 0x1f, 0xa6,
- 0x52, 0x03, 0x8b, 0x52, 0x08, 0xb5, 0x06, 0x02,
+ 0x95, 0x37, 0x00, 0x88, 0x37, 0x9f, 0x78, 0x9e,
+ 0x61, 0x07, 0x88, 0x61, 0x2f, 0x92, 0x34, 0x00,
+ 0x81, 0x34, 0x04, 0x84, 0x34, 0x9b, 0x7b, 0x02,
+ 0x80, 0x7b, 0x99, 0x4e, 0x04, 0x80, 0x4e, 0x3f,
+ 0x9f, 0x5a, 0x97, 0x59, 0x03, 0x93, 0x59, 0x01,
+ 0xad, 0x59, 0x83, 0x41, 0x00, 0x81, 0x41, 0x04,
+ 0x87, 0x41, 0x00, 0x82, 0x41, 0x00, 0x9c, 0x41,
+ 0x01, 0x82, 0x41, 0x03, 0x89, 0x41, 0x06, 0x88,
+ 0x41, 0x06, 0x9f, 0x71, 0x9f, 0x6d, 0x1f, 0xa6,
+ 0x53, 0x03, 0x8b, 0x53, 0x08, 0xb5, 0x06, 0x02,
0x86, 0x06, 0x95, 0x3a, 0x01, 0x87, 0x3a, 0x92,
- 0x39, 0x04, 0x87, 0x39, 0x91, 0x7a, 0x06, 0x83,
- 0x7a, 0x0b, 0x86, 0x7a, 0x4f, 0xc8, 0x70, 0x36,
- 0xb2, 0x69, 0x0c, 0xb2, 0x69, 0x06, 0x85, 0x69,
+ 0x39, 0x04, 0x87, 0x39, 0x91, 0x7c, 0x06, 0x83,
+ 0x7c, 0x0b, 0x86, 0x7c, 0x4f, 0xc8, 0x72, 0x36,
+ 0xb2, 0x6b, 0x0c, 0xb2, 0x6b, 0x06, 0x85, 0x6b,
0xa7, 0x32, 0x07, 0x89, 0x32, 0x60, 0xc5, 0x9e,
- 0x04, 0x00, 0xa9, 0x9f, 0x00, 0x82, 0x9f, 0x01,
- 0x81, 0x9f, 0x4d, 0xa7, 0x6e, 0x07, 0xa9, 0x84,
- 0x15, 0x99, 0x71, 0x25, 0x9b, 0x18, 0x13, 0x96,
- 0x26, 0x08, 0xcd, 0x0e, 0x03, 0xa3, 0x0e, 0x08,
- 0x80, 0x0e, 0xc2, 0x3c, 0x09, 0x80, 0x3c, 0x01,
- 0x98, 0x85, 0x06, 0x89, 0x85, 0x05, 0xb4, 0x15,
- 0x00, 0x91, 0x15, 0x07, 0xa6, 0x4f, 0x08, 0xdf,
- 0x7f, 0x00, 0x93, 0x83, 0x0a, 0x91, 0x42, 0x00,
- 0xab, 0x42, 0x40, 0x86, 0x5e, 0x00, 0x80, 0x5e,
- 0x00, 0x83, 0x5e, 0x00, 0x8e, 0x5e, 0x00, 0x8a,
- 0x5e, 0x05, 0xba, 0x44, 0x04, 0x89, 0x44, 0x05,
- 0x83, 0x2b, 0x00, 0x87, 0x2b, 0x01, 0x81, 0x2b,
- 0x01, 0x95, 0x2b, 0x00, 0x86, 0x2b, 0x00, 0x81,
- 0x2b, 0x00, 0x84, 0x2b, 0x00, 0x80, 0x38, 0x88,
- 0x2b, 0x01, 0x81, 0x2b, 0x01, 0x82, 0x2b, 0x01,
- 0x80, 0x2b, 0x05, 0x80, 0x2b, 0x04, 0x86, 0x2b,
- 0x01, 0x86, 0x2b, 0x02, 0x84, 0x2b, 0x60, 0x2a,
- 0xdb, 0x63, 0x00, 0x84, 0x63, 0x1d, 0xc7, 0x97,
- 0x07, 0x89, 0x97, 0x60, 0x45, 0xb5, 0x81, 0x01,
- 0xa5, 0x81, 0x21, 0xc4, 0x5b, 0x0a, 0x89, 0x5b,
- 0x05, 0x8c, 0x5c, 0x12, 0xb9, 0x8f, 0x05, 0x89,
- 0x8f, 0x35, 0x9a, 0x02, 0x01, 0x8e, 0x02, 0x03,
- 0x96, 0x02, 0x60, 0x58, 0xbb, 0x22, 0x60, 0x03,
- 0xd2, 0x9e, 0x0b, 0x80, 0x9e, 0x86, 0x21, 0x01,
- 0x80, 0x21, 0x01, 0x87, 0x21, 0x00, 0x81, 0x21,
- 0x00, 0x9d, 0x21, 0x00, 0x81, 0x21, 0x01, 0x8b,
- 0x21, 0x08, 0x89, 0x21, 0x45, 0x87, 0x61, 0x01,
- 0xad, 0x61, 0x01, 0x8a, 0x61, 0x1a, 0xc7, 0xa1,
- 0x07, 0xd2, 0x86, 0x0c, 0x8f, 0x12, 0xb8, 0x77,
- 0x60, 0xa6, 0x88, 0x0c, 0x00, 0xac, 0x0c, 0x00,
- 0x8d, 0x0c, 0x09, 0x9c, 0x0c, 0x02, 0x9f, 0x53,
- 0x01, 0x95, 0x53, 0x00, 0x8d, 0x53, 0x48, 0x86,
- 0x54, 0x00, 0x81, 0x54, 0x00, 0xab, 0x54, 0x02,
- 0x80, 0x54, 0x00, 0x81, 0x54, 0x00, 0x88, 0x54,
- 0x07, 0x89, 0x54, 0x05, 0x85, 0x2e, 0x00, 0x81,
- 0x2e, 0x00, 0xa4, 0x2e, 0x00, 0x81, 0x2e, 0x00,
- 0x85, 0x2e, 0x06, 0x89, 0x2e, 0x60, 0xd5, 0x98,
- 0x4e, 0x60, 0x56, 0x80, 0x4b, 0x0e, 0xb1, 0x90,
- 0x0c, 0x80, 0x90, 0xe3, 0x39, 0x1b, 0x60, 0x05,
- 0xe0, 0x0e, 0x1b, 0x00, 0x84, 0x1b, 0x0a, 0xe0,
- 0x63, 0x1b, 0x69, 0xeb, 0xe0, 0x02, 0x1e, 0x0c,
- 0xe3, 0xce, 0x24, 0x00, 0x88, 0x24, 0x6f, 0x66,
- 0xe1, 0xe6, 0x03, 0x70, 0x11, 0x58, 0xe1, 0xd8,
- 0x08, 0x06, 0x9e, 0x5d, 0x00, 0x89, 0x5d, 0x03,
- 0x81, 0x5d, 0xce, 0x98, 0x00, 0x89, 0x98, 0x05,
- 0x9d, 0x09, 0x01, 0x85, 0x09, 0x09, 0xc5, 0x75,
- 0x09, 0x89, 0x75, 0x00, 0x86, 0x75, 0x00, 0x94,
- 0x75, 0x04, 0x92, 0x75, 0x62, 0x4f, 0xda, 0x55,
- 0x60, 0x04, 0xca, 0x5a, 0x03, 0xb8, 0x5a, 0x06,
- 0x90, 0x5a, 0x3f, 0x80, 0x91, 0x80, 0x65, 0x81,
- 0x30, 0x80, 0x43, 0x0a, 0x81, 0x30, 0x0d, 0xf0,
- 0x07, 0x97, 0x91, 0x07, 0xe2, 0x9f, 0x91, 0xe1,
- 0x75, 0x43, 0x29, 0x88, 0x91, 0x70, 0x12, 0x86,
- 0x83, 0x3e, 0x00, 0x86, 0x3e, 0x00, 0x81, 0x3e,
- 0x00, 0x80, 0x3e, 0xe0, 0xbe, 0x36, 0x82, 0x3e,
- 0x2c, 0x82, 0x36, 0x10, 0x83, 0x3e, 0x07, 0xe1,
- 0x2b, 0x65, 0x68, 0xa3, 0xe0, 0x0a, 0x23, 0x04,
+ 0x04, 0x00, 0xa9, 0xa1, 0x00, 0x82, 0xa1, 0x01,
+ 0x81, 0xa1, 0x4a, 0x82, 0x04, 0xa7, 0x70, 0x07,
+ 0xa9, 0x86, 0x15, 0x99, 0x73, 0x25, 0x9b, 0x18,
+ 0x13, 0x96, 0x26, 0x08, 0xcd, 0x0e, 0x03, 0xa3,
+ 0x0e, 0x08, 0x80, 0x0e, 0xc2, 0x3c, 0x09, 0x80,
+ 0x3c, 0x01, 0x98, 0x87, 0x06, 0x89, 0x87, 0x05,
+ 0xb4, 0x15, 0x00, 0x91, 0x15, 0x07, 0xa6, 0x50,
+ 0x08, 0xdf, 0x81, 0x00, 0x93, 0x85, 0x0a, 0x91,
+ 0x43, 0x00, 0xae, 0x43, 0x3d, 0x86, 0x5f, 0x00,
+ 0x80, 0x5f, 0x00, 0x83, 0x5f, 0x00, 0x8e, 0x5f,
+ 0x00, 0x8a, 0x5f, 0x05, 0xba, 0x45, 0x04, 0x89,
+ 0x45, 0x05, 0x83, 0x2b, 0x00, 0x87, 0x2b, 0x01,
+ 0x81, 0x2b, 0x01, 0x95, 0x2b, 0x00, 0x86, 0x2b,
+ 0x00, 0x81, 0x2b, 0x00, 0x84, 0x2b, 0x00, 0x80,
+ 0x38, 0x88, 0x2b, 0x01, 0x81, 0x2b, 0x01, 0x82,
+ 0x2b, 0x01, 0x80, 0x2b, 0x05, 0x80, 0x2b, 0x04,
+ 0x86, 0x2b, 0x01, 0x86, 0x2b, 0x02, 0x84, 0x2b,
+ 0x60, 0x2a, 0xdb, 0x65, 0x00, 0x84, 0x65, 0x1d,
+ 0xc7, 0x99, 0x07, 0x89, 0x99, 0x60, 0x45, 0xb5,
+ 0x83, 0x01, 0xa5, 0x83, 0x21, 0xc4, 0x5c, 0x0a,
+ 0x89, 0x5c, 0x05, 0x8c, 0x5d, 0x12, 0xb9, 0x91,
+ 0x05, 0x89, 0x91, 0x35, 0x9a, 0x02, 0x01, 0x8e,
+ 0x02, 0x03, 0x96, 0x02, 0x60, 0x58, 0xbb, 0x22,
+ 0x60, 0x03, 0xd2, 0xa0, 0x0b, 0x80, 0xa0, 0x86,
+ 0x21, 0x01, 0x80, 0x21, 0x01, 0x87, 0x21, 0x00,
+ 0x81, 0x21, 0x00, 0x9d, 0x21, 0x00, 0x81, 0x21,
+ 0x01, 0x8b, 0x21, 0x08, 0x89, 0x21, 0x45, 0x87,
+ 0x63, 0x01, 0xad, 0x63, 0x01, 0x8a, 0x63, 0x1a,
+ 0xc7, 0xa3, 0x07, 0xd2, 0x88, 0x0c, 0x8f, 0x12,
+ 0xb8, 0x79, 0x06, 0x89, 0x20, 0x60, 0x95, 0x88,
+ 0x0c, 0x00, 0xac, 0x0c, 0x00, 0x8d, 0x0c, 0x09,
+ 0x9c, 0x0c, 0x02, 0x9f, 0x54, 0x01, 0x95, 0x54,
+ 0x00, 0x8d, 0x54, 0x48, 0x86, 0x55, 0x00, 0x81,
+ 0x55, 0x00, 0xab, 0x55, 0x02, 0x80, 0x55, 0x00,
+ 0x81, 0x55, 0x00, 0x88, 0x55, 0x07, 0x89, 0x55,
+ 0x05, 0x85, 0x2e, 0x00, 0x81, 0x2e, 0x00, 0xa4,
+ 0x2e, 0x00, 0x81, 0x2e, 0x00, 0x85, 0x2e, 0x06,
+ 0x89, 0x2e, 0x60, 0xd5, 0x98, 0x4f, 0x06, 0x90,
+ 0x3f, 0x00, 0xa8, 0x3f, 0x02, 0x9b, 0x3f, 0x55,
+ 0x80, 0x4c, 0x0e, 0xb1, 0x92, 0x0c, 0x80, 0x92,
+ 0xe3, 0x39, 0x1b, 0x60, 0x05, 0xe0, 0x0e, 0x1b,
+ 0x00, 0x84, 0x1b, 0x0a, 0xe0, 0x63, 0x1b, 0x69,
+ 0xeb, 0xe0, 0x02, 0x1e, 0x0c, 0xe3, 0xf5, 0x24,
+ 0x6f, 0x49, 0xe1, 0xe6, 0x03, 0x70, 0x11, 0x58,
+ 0xe1, 0xd8, 0x08, 0x06, 0x9e, 0x5e, 0x00, 0x89,
+ 0x5e, 0x03, 0x81, 0x5e, 0xce, 0x9a, 0x00, 0x89,
+ 0x9a, 0x05, 0x9d, 0x09, 0x01, 0x85, 0x09, 0x09,
+ 0xc5, 0x77, 0x09, 0x89, 0x77, 0x00, 0x86, 0x77,
+ 0x00, 0x94, 0x77, 0x04, 0x92, 0x77, 0x62, 0x4f,
+ 0xda, 0x56, 0x60, 0x04, 0xca, 0x5b, 0x03, 0xb8,
+ 0x5b, 0x06, 0x90, 0x5b, 0x3f, 0x80, 0x93, 0x80,
+ 0x67, 0x81, 0x30, 0x80, 0x44, 0x0a, 0x81, 0x30,
+ 0x0d, 0xf0, 0x07, 0x97, 0x93, 0x07, 0xe2, 0x9f,
+ 0x93, 0xe1, 0x75, 0x44, 0x29, 0x88, 0x93, 0x70,
+ 0x12, 0x86, 0x83, 0x3e, 0x00, 0x86, 0x3e, 0x00,
+ 0x81, 0x3e, 0x00, 0x80, 0x3e, 0xe0, 0xbe, 0x36,
+ 0x82, 0x3e, 0x0e, 0x80, 0x36, 0x1c, 0x82, 0x36,
+ 0x01, 0x80, 0x3e, 0x0d, 0x83, 0x3e, 0x07, 0xe1,
+ 0x2b, 0x67, 0x68, 0xa3, 0xe0, 0x0a, 0x23, 0x04,
0x8c, 0x23, 0x02, 0x88, 0x23, 0x06, 0x89, 0x23,
0x01, 0x83, 0x23, 0x83, 0x19, 0x70, 0x01, 0xfb,
0xad, 0x38, 0x01, 0x96, 0x38, 0x08, 0xe0, 0x13,
0x19, 0x3b, 0xe0, 0x95, 0x19, 0x09, 0xa6, 0x19,
0x01, 0xbd, 0x19, 0x82, 0x38, 0x90, 0x19, 0x87,
0x38, 0x81, 0x19, 0x86, 0x38, 0x9d, 0x19, 0x83,
- 0x38, 0xbc, 0x19, 0x14, 0xc5, 0x2c, 0x60, 0x39,
- 0x93, 0x19, 0x0b, 0xd6, 0x19, 0x08, 0x98, 0x19,
- 0x60, 0x26, 0xd4, 0x19, 0x00, 0xc6, 0x19, 0x00,
- 0x81, 0x19, 0x01, 0x80, 0x19, 0x01, 0x81, 0x19,
- 0x01, 0x83, 0x19, 0x00, 0x8b, 0x19, 0x00, 0x80,
- 0x19, 0x00, 0x86, 0x19, 0x00, 0xc0, 0x19, 0x00,
- 0x83, 0x19, 0x01, 0x87, 0x19, 0x00, 0x86, 0x19,
- 0x00, 0x9b, 0x19, 0x00, 0x83, 0x19, 0x00, 0x84,
- 0x19, 0x00, 0x80, 0x19, 0x02, 0x86, 0x19, 0x00,
- 0xe0, 0xf3, 0x19, 0x01, 0xe0, 0xc3, 0x19, 0x01,
- 0xb1, 0x19, 0xe2, 0x2b, 0x82, 0x0e, 0x84, 0x82,
- 0x00, 0x8e, 0x82, 0x63, 0xef, 0x9e, 0x46, 0x60,
- 0x80, 0x86, 0x29, 0x00, 0x90, 0x29, 0x01, 0x86,
- 0x29, 0x00, 0x81, 0x29, 0x00, 0x84, 0x29, 0x60,
- 0x74, 0xac, 0x66, 0x02, 0x8d, 0x66, 0x01, 0x89,
- 0x66, 0x03, 0x81, 0x66, 0x60, 0xdf, 0x9e, 0x99,
- 0x10, 0xb9, 0x9d, 0x04, 0x80, 0x9d, 0x64, 0x7f,
+ 0x38, 0xbc, 0x19, 0x14, 0xc5, 0x2c, 0x60, 0x19,
+ 0x93, 0x19, 0x0b, 0x93, 0x19, 0x0b, 0xd6, 0x19,
+ 0x08, 0x98, 0x19, 0x60, 0x26, 0xd4, 0x19, 0x00,
+ 0xc6, 0x19, 0x00, 0x81, 0x19, 0x01, 0x80, 0x19,
+ 0x01, 0x81, 0x19, 0x01, 0x83, 0x19, 0x00, 0x8b,
+ 0x19, 0x00, 0x80, 0x19, 0x00, 0x86, 0x19, 0x00,
+ 0xc0, 0x19, 0x00, 0x83, 0x19, 0x01, 0x87, 0x19,
+ 0x00, 0x86, 0x19, 0x00, 0x9b, 0x19, 0x00, 0x83,
+ 0x19, 0x00, 0x84, 0x19, 0x00, 0x80, 0x19, 0x02,
+ 0x86, 0x19, 0x00, 0xe0, 0xf3, 0x19, 0x01, 0xe0,
+ 0xc3, 0x19, 0x01, 0xb1, 0x19, 0xe2, 0x2b, 0x84,
+ 0x0e, 0x84, 0x84, 0x00, 0x8e, 0x84, 0x63, 0xef,
+ 0x9e, 0x47, 0x05, 0x85, 0x47, 0x60, 0x74, 0x86,
+ 0x29, 0x00, 0x90, 0x29, 0x01, 0x86, 0x29, 0x00,
+ 0x81, 0x29, 0x00, 0x84, 0x29, 0x04, 0xbd, 0x1d,
+ 0x20, 0x80, 0x1d, 0x60, 0x0f, 0xac, 0x68, 0x02,
+ 0x8d, 0x68, 0x01, 0x89, 0x68, 0x03, 0x81, 0x68,
+ 0x60, 0xdf, 0x9e, 0x9b, 0x10, 0xb9, 0x9f, 0x04,
+ 0x80, 0x9f, 0x61, 0x6f, 0xa9, 0x62, 0x62, 0x85,
0x86, 0x27, 0x00, 0x83, 0x27, 0x00, 0x81, 0x27,
- 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x57, 0x01,
- 0x8f, 0x57, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01,
+ 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x58, 0x01,
+ 0x8f, 0x58, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01,
0x03, 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x19, 0x4b,
0xbc, 0x19, 0x60, 0x61, 0x83, 0x04, 0x00, 0x9a,
0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01,
@@ -3455,86 +3561,85 @@ static const uint8_t unicode_script_table[2690] = {
0x19, 0x37, 0x99, 0x19, 0x80, 0x36, 0x81, 0x19,
0x0c, 0xab, 0x19, 0x03, 0x88, 0x19, 0x06, 0x81,
0x19, 0x0d, 0x85, 0x19, 0x60, 0x39, 0xe3, 0x77,
- 0x19, 0x04, 0x8f, 0x19, 0x02, 0x8c, 0x19, 0x02,
- 0xe0, 0x13, 0x19, 0x0b, 0xd8, 0x19, 0x06, 0x8b,
+ 0x19, 0x03, 0x90, 0x19, 0x02, 0x8c, 0x19, 0x02,
+ 0xe0, 0x16, 0x19, 0x03, 0xde, 0x19, 0x05, 0x8b,
0x19, 0x03, 0x80, 0x19, 0x0e, 0x8b, 0x19, 0x03,
0xb7, 0x19, 0x07, 0x89, 0x19, 0x05, 0xa7, 0x19,
0x07, 0x9d, 0x19, 0x01, 0x81, 0x19, 0x4d, 0xe0,
- 0xf3, 0x19, 0x0b, 0x8d, 0x19, 0x01, 0x84, 0x19,
- 0x02, 0x84, 0x19, 0x02, 0x86, 0x19, 0x08, 0x9c,
- 0x19, 0x02, 0x8a, 0x19, 0x04, 0x85, 0x19, 0x09,
- 0x89, 0x19, 0x05, 0x87, 0x19, 0x07, 0x86, 0x19,
- 0x08, 0xe0, 0x32, 0x19, 0x00, 0xb6, 0x19, 0x24,
- 0x89, 0x19, 0x63, 0xa5, 0xf0, 0x96, 0x7f, 0x30,
- 0x1f, 0xef, 0xd8, 0x30, 0x06, 0xe0, 0x7d, 0x30,
- 0x01, 0xf0, 0x06, 0x21, 0x30, 0x0d, 0xf0, 0x0c,
- 0xd0, 0x30, 0x6b, 0xbe, 0xe1, 0xbd, 0x30, 0x65,
- 0x81, 0xf0, 0x02, 0xea, 0x30, 0x7a, 0xdc, 0x55,
- 0x80, 0x19, 0x1d, 0xdf, 0x19, 0x60, 0x1f, 0xe0,
- 0x8f, 0x38,
+ 0xf3, 0x19, 0x0b, 0x8d, 0x19, 0x01, 0x8c, 0x19,
+ 0x02, 0x88, 0x19, 0x06, 0xad, 0x19, 0x00, 0x86,
+ 0x19, 0x07, 0x8d, 0x19, 0x03, 0x88, 0x19, 0x06,
+ 0x88, 0x19, 0x06, 0xe0, 0x32, 0x19, 0x00, 0xb6,
+ 0x19, 0x24, 0x89, 0x19, 0x63, 0xa5, 0xf0, 0x96,
+ 0x7f, 0x30, 0x1f, 0xef, 0xd9, 0x30, 0x05, 0xe0,
+ 0x7d, 0x30, 0x01, 0xf0, 0x06, 0x21, 0x30, 0x0d,
+ 0xf0, 0x0c, 0xd0, 0x30, 0x6b, 0xbe, 0xe1, 0xbd,
+ 0x30, 0x65, 0x81, 0xf0, 0x02, 0xea, 0x30, 0x04,
+ 0xef, 0xff, 0x30, 0x7a, 0xcb, 0xf0, 0x80, 0x19,
+ 0x1d, 0xdf, 0x19, 0x60, 0x1f, 0xe0, 0x8f, 0x38,
};
static const uint8_t unicode_script_ext_table[828] = {
0x82, 0xc1, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x00,
- 0x00, 0x01, 0x2c, 0x1c, 0x00, 0x0c, 0x01, 0x46,
- 0x80, 0x92, 0x00, 0x00, 0x02, 0x1d, 0x6c, 0x00,
- 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x46, 0x00,
+ 0x00, 0x01, 0x2c, 0x1c, 0x00, 0x0c, 0x01, 0x47,
+ 0x80, 0x92, 0x00, 0x00, 0x02, 0x1d, 0x6e, 0x00,
+ 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x47, 0x00,
0x02, 0x1d, 0x29, 0x81, 0x03, 0x00, 0x00, 0x06,
- 0x04, 0x64, 0x32, 0x89, 0x93, 0x9f, 0x0d, 0x00,
- 0x00, 0x06, 0x04, 0x64, 0x32, 0x89, 0x93, 0x9f,
- 0x00, 0x03, 0x04, 0x89, 0x93, 0x01, 0x00, 0x00,
- 0x07, 0x01, 0x04, 0x64, 0x32, 0x89, 0x93, 0x9f,
- 0x1f, 0x00, 0x00, 0x09, 0x01, 0x04, 0x51, 0x52,
- 0x71, 0x7a, 0x32, 0x84, 0x89, 0x09, 0x00, 0x0a,
- 0x02, 0x04, 0x89, 0x09, 0x00, 0x09, 0x03, 0x04,
- 0x93, 0x9f, 0x05, 0x00, 0x00, 0x02, 0x04, 0x89,
+ 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1, 0x0d, 0x00,
+ 0x00, 0x06, 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1,
+ 0x00, 0x03, 0x04, 0x8b, 0x95, 0x01, 0x00, 0x00,
+ 0x07, 0x01, 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1,
+ 0x1f, 0x00, 0x00, 0x09, 0x01, 0x04, 0x52, 0x53,
+ 0x73, 0x7c, 0x32, 0x86, 0x8b, 0x09, 0x00, 0x0a,
+ 0x02, 0x04, 0x8b, 0x09, 0x00, 0x09, 0x03, 0x04,
+ 0x95, 0xa1, 0x05, 0x00, 0x00, 0x02, 0x04, 0x8b,
0x62, 0x00, 0x00, 0x02, 0x04, 0x32, 0x81, 0xfb,
0x00, 0x00, 0x0d, 0x0b, 0x20, 0x2b, 0x2d, 0x2f,
- 0x3d, 0x46, 0x50, 0x72, 0x7f, 0x90, 0x92, 0x97,
+ 0x3d, 0x47, 0x51, 0x74, 0x81, 0x92, 0x94, 0x99,
0x00, 0x0c, 0x0b, 0x20, 0x2b, 0x2d, 0x2f, 0x3d,
- 0x46, 0x50, 0x72, 0x90, 0x92, 0x97, 0x10, 0x00,
- 0x00, 0x14, 0x0b, 0x20, 0x22, 0x2e, 0x54, 0x2b,
- 0x2d, 0x2f, 0x3d, 0x4f, 0x50, 0x61, 0x72, 0x44,
- 0x83, 0x88, 0x8f, 0x90, 0x92, 0x97, 0x00, 0x15,
- 0x0b, 0x20, 0x22, 0x2e, 0x54, 0x2b, 0x2d, 0x2f,
- 0x3d, 0x48, 0x4f, 0x50, 0x61, 0x72, 0x44, 0x83,
- 0x88, 0x8f, 0x90, 0x92, 0x97, 0x09, 0x04, 0x20,
- 0x22, 0x3c, 0x4f, 0x75, 0x00, 0x09, 0x03, 0x0b,
- 0x15, 0x88, 0x75, 0x00, 0x09, 0x02, 0x2f, 0x5e,
- 0x75, 0x00, 0x09, 0x02, 0x2d, 0x42, 0x80, 0x75,
- 0x00, 0x0d, 0x02, 0x2b, 0x90, 0x80, 0x71, 0x00,
- 0x09, 0x02, 0x3d, 0x61, 0x82, 0xcf, 0x00, 0x09,
- 0x03, 0x15, 0x5f, 0x8c, 0x80, 0x30, 0x00, 0x00,
- 0x02, 0x28, 0x46, 0x85, 0xb8, 0x00, 0x01, 0x04,
- 0x11, 0x33, 0x8b, 0x8a, 0x80, 0x4a, 0x00, 0x01,
- 0x02, 0x5c, 0x78, 0x00, 0x00, 0x00, 0x02, 0x5c,
- 0x78, 0x84, 0x49, 0x00, 0x00, 0x04, 0x0b, 0x20,
+ 0x47, 0x51, 0x74, 0x92, 0x94, 0x99, 0x10, 0x00,
+ 0x00, 0x14, 0x0b, 0x20, 0x22, 0x2e, 0x55, 0x2b,
+ 0x2d, 0x2f, 0x3d, 0x50, 0x51, 0x63, 0x74, 0x45,
+ 0x85, 0x8a, 0x91, 0x92, 0x94, 0x99, 0x00, 0x15,
+ 0x0b, 0x20, 0x22, 0x2e, 0x55, 0x2b, 0x2d, 0x2f,
+ 0x3d, 0x49, 0x50, 0x51, 0x63, 0x74, 0x45, 0x85,
+ 0x8a, 0x91, 0x92, 0x94, 0x99, 0x09, 0x04, 0x20,
+ 0x22, 0x3c, 0x50, 0x75, 0x00, 0x09, 0x03, 0x0b,
+ 0x15, 0x8a, 0x75, 0x00, 0x09, 0x02, 0x2f, 0x5f,
+ 0x75, 0x00, 0x09, 0x02, 0x2d, 0x43, 0x80, 0x75,
+ 0x00, 0x0d, 0x02, 0x2b, 0x92, 0x80, 0x71, 0x00,
+ 0x09, 0x02, 0x3d, 0x63, 0x82, 0xcf, 0x00, 0x09,
+ 0x03, 0x15, 0x60, 0x8e, 0x80, 0x30, 0x00, 0x00,
+ 0x02, 0x28, 0x47, 0x85, 0xb8, 0x00, 0x01, 0x04,
+ 0x11, 0x33, 0x8d, 0x8c, 0x80, 0x4a, 0x00, 0x01,
+ 0x02, 0x5d, 0x7a, 0x00, 0x00, 0x00, 0x02, 0x5d,
+ 0x7a, 0x84, 0x49, 0x00, 0x00, 0x04, 0x0b, 0x20,
0x2b, 0x3d, 0x00, 0x01, 0x20, 0x00, 0x04, 0x0b,
0x20, 0x2b, 0x3d, 0x00, 0x02, 0x20, 0x2b, 0x00,
0x01, 0x20, 0x01, 0x02, 0x0b, 0x20, 0x00, 0x02,
- 0x20, 0x7f, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02,
- 0x20, 0x7f, 0x00, 0x06, 0x20, 0x3d, 0x50, 0x72,
- 0x90, 0x92, 0x00, 0x01, 0x20, 0x01, 0x02, 0x20,
- 0x7f, 0x01, 0x01, 0x20, 0x00, 0x02, 0x20, 0x7f,
+ 0x20, 0x81, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02,
+ 0x20, 0x81, 0x00, 0x06, 0x20, 0x3d, 0x51, 0x74,
+ 0x92, 0x94, 0x00, 0x01, 0x20, 0x01, 0x02, 0x20,
+ 0x81, 0x01, 0x01, 0x20, 0x00, 0x02, 0x20, 0x81,
0x00, 0x02, 0x0b, 0x20, 0x06, 0x01, 0x20, 0x00,
- 0x02, 0x20, 0x61, 0x00, 0x02, 0x0b, 0x20, 0x01,
+ 0x02, 0x20, 0x63, 0x00, 0x02, 0x0b, 0x20, 0x01,
0x01, 0x20, 0x00, 0x02, 0x0b, 0x20, 0x03, 0x01,
- 0x20, 0x00, 0x08, 0x0b, 0x20, 0x2b, 0x3d, 0x61,
- 0x72, 0x92, 0x97, 0x00, 0x02, 0x20, 0x2b, 0x00,
+ 0x20, 0x00, 0x08, 0x0b, 0x20, 0x2b, 0x3d, 0x63,
+ 0x74, 0x94, 0x99, 0x00, 0x02, 0x20, 0x2b, 0x00,
0x03, 0x20, 0x2b, 0x3d, 0x01, 0x02, 0x0b, 0x20,
0x00, 0x01, 0x0b, 0x01, 0x02, 0x20, 0x2b, 0x00,
- 0x01, 0x61, 0x80, 0x44, 0x00, 0x01, 0x01, 0x2c,
- 0x35, 0x00, 0x00, 0x02, 0x1d, 0x89, 0x00, 0x00,
- 0x00, 0x01, 0x89, 0x81, 0xb3, 0x00, 0x00, 0x02,
- 0x46, 0x5c, 0x80, 0x3f, 0x00, 0x00, 0x03, 0x20,
- 0x2b, 0x46, 0x8c, 0xd1, 0x00, 0x00, 0x02, 0x1d,
+ 0x01, 0x63, 0x80, 0x44, 0x00, 0x01, 0x01, 0x2c,
+ 0x35, 0x00, 0x00, 0x02, 0x1d, 0x8b, 0x00, 0x00,
+ 0x00, 0x01, 0x8b, 0x81, 0xb3, 0x00, 0x00, 0x02,
+ 0x47, 0x5d, 0x80, 0x3f, 0x00, 0x00, 0x03, 0x20,
+ 0x2b, 0x47, 0x8c, 0xd1, 0x00, 0x00, 0x02, 0x1d,
0x29, 0x81, 0x3c, 0x00, 0x01, 0x06, 0x0d, 0x31,
- 0x30, 0x36, 0x3e, 0xa0, 0x00, 0x05, 0x0d, 0x31,
+ 0x30, 0x36, 0x3e, 0xa2, 0x00, 0x05, 0x0d, 0x31,
0x30, 0x36, 0x3e, 0x01, 0x00, 0x00, 0x01, 0x30,
0x00, 0x00, 0x09, 0x06, 0x0d, 0x31, 0x30, 0x36,
- 0x3e, 0xa0, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x31,
+ 0x3e, 0xa2, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x31,
0x30, 0x36, 0x3e, 0x07, 0x06, 0x0d, 0x31, 0x30,
- 0x36, 0x3e, 0xa0, 0x03, 0x05, 0x0d, 0x31, 0x30,
+ 0x36, 0x3e, 0xa2, 0x03, 0x05, 0x0d, 0x31, 0x30,
0x36, 0x3e, 0x09, 0x00, 0x03, 0x02, 0x0d, 0x30,
0x01, 0x00, 0x00, 0x05, 0x0d, 0x31, 0x30, 0x36,
0x3e, 0x04, 0x02, 0x36, 0x3e, 0x00, 0x00, 0x00,
@@ -3542,7 +3647,7 @@ static const uint8_t unicode_script_ext_table[828] = {
0x01, 0x03, 0x30, 0x36, 0x3e, 0x01, 0x01, 0x30,
0x58, 0x00, 0x03, 0x02, 0x36, 0x3e, 0x02, 0x00,
0x00, 0x02, 0x36, 0x3e, 0x59, 0x00, 0x00, 0x06,
- 0x0d, 0x31, 0x30, 0x36, 0x3e, 0xa0, 0x00, 0x02,
+ 0x0d, 0x31, 0x30, 0x36, 0x3e, 0xa2, 0x00, 0x02,
0x36, 0x3e, 0x80, 0x12, 0x00, 0x0f, 0x01, 0x30,
0x1f, 0x00, 0x23, 0x01, 0x30, 0x3b, 0x00, 0x27,
0x01, 0x30, 0x37, 0x00, 0x30, 0x01, 0x30, 0x0e,
@@ -3550,32 +3655,32 @@ static const uint8_t unicode_script_ext_table[828] = {
0x30, 0x57, 0x00, 0x18, 0x01, 0x30, 0x09, 0x00,
0x04, 0x01, 0x30, 0x5f, 0x00, 0x1e, 0x01, 0x30,
0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, 0x1d, 0x29,
- 0x80, 0x0f, 0x00, 0x07, 0x02, 0x30, 0x46, 0x80,
+ 0x80, 0x0f, 0x00, 0x07, 0x02, 0x30, 0x47, 0x80,
0xa7, 0x00, 0x02, 0x0e, 0x20, 0x22, 0x2d, 0x2f,
- 0x42, 0x3d, 0x3c, 0x4f, 0x50, 0x5b, 0x61, 0x44,
- 0x8f, 0x97, 0x02, 0x0d, 0x20, 0x22, 0x2d, 0x2f,
- 0x42, 0x3d, 0x3c, 0x4f, 0x5b, 0x61, 0x44, 0x8f,
- 0x97, 0x03, 0x0b, 0x20, 0x22, 0x2d, 0x2f, 0x42,
- 0x3c, 0x4f, 0x5b, 0x44, 0x8f, 0x97, 0x80, 0x36,
+ 0x43, 0x3d, 0x3c, 0x50, 0x51, 0x5c, 0x63, 0x45,
+ 0x91, 0x99, 0x02, 0x0d, 0x20, 0x22, 0x2d, 0x2f,
+ 0x43, 0x3d, 0x3c, 0x50, 0x5c, 0x63, 0x45, 0x91,
+ 0x99, 0x03, 0x0b, 0x20, 0x22, 0x2d, 0x2f, 0x43,
+ 0x3c, 0x50, 0x5c, 0x45, 0x91, 0x99, 0x80, 0x36,
0x00, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x00, 0x00,
- 0x02, 0x20, 0x90, 0x39, 0x00, 0x00, 0x03, 0x3f,
- 0x46, 0x5f, 0x80, 0x1f, 0x00, 0x00, 0x02, 0x10,
+ 0x02, 0x20, 0x92, 0x39, 0x00, 0x00, 0x03, 0x40,
+ 0x47, 0x60, 0x80, 0x1f, 0x00, 0x00, 0x02, 0x10,
0x3b, 0xc0, 0x12, 0xed, 0x00, 0x01, 0x02, 0x04,
- 0x64, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04, 0x93,
- 0x09, 0x00, 0x00, 0x02, 0x04, 0x93, 0x46, 0x00,
+ 0x66, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04, 0x95,
+ 0x09, 0x00, 0x00, 0x02, 0x04, 0x95, 0x46, 0x00,
0x01, 0x05, 0x0d, 0x31, 0x30, 0x36, 0x3e, 0x80,
0x99, 0x00, 0x04, 0x06, 0x0d, 0x31, 0x30, 0x36,
- 0x3e, 0xa0, 0x09, 0x00, 0x00, 0x02, 0x36, 0x3e,
+ 0x3e, 0xa2, 0x09, 0x00, 0x00, 0x02, 0x36, 0x3e,
0x2c, 0x00, 0x01, 0x02, 0x36, 0x3e, 0x80, 0xdf,
- 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4a, 0x00, 0x02,
- 0x1c, 0x4a, 0x03, 0x00, 0x2c, 0x03, 0x1c, 0x49,
- 0x4a, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4a, 0x81,
+ 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4b, 0x00, 0x02,
+ 0x1c, 0x4b, 0x03, 0x00, 0x2c, 0x03, 0x1c, 0x4a,
+ 0x4b, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4b, 0x81,
0x1f, 0x00, 0x1b, 0x02, 0x04, 0x1a, 0x87, 0x75,
- 0x00, 0x00, 0x02, 0x52, 0x71, 0x87, 0x8d, 0x00,
- 0x00, 0x02, 0x2b, 0x90, 0x00, 0x00, 0x00, 0x02,
- 0x2b, 0x90, 0x36, 0x00, 0x01, 0x02, 0x2b, 0x90,
- 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2b, 0x90, 0x00,
- 0x00, 0x00, 0x02, 0x2b, 0x90, 0xc0, 0x5c, 0x4b,
+ 0x00, 0x00, 0x02, 0x53, 0x73, 0x87, 0x8d, 0x00,
+ 0x00, 0x02, 0x2b, 0x92, 0x00, 0x00, 0x00, 0x02,
+ 0x2b, 0x92, 0x36, 0x00, 0x01, 0x02, 0x2b, 0x92,
+ 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2b, 0x92, 0x00,
+ 0x00, 0x00, 0x02, 0x2b, 0x92, 0xc0, 0x5c, 0x4b,
0x00, 0x03, 0x01, 0x23, 0x96, 0x3b, 0x00, 0x11,
0x01, 0x30, 0x9e, 0x5d, 0x00, 0x01, 0x01, 0x30,
0xce, 0xcd, 0x2d, 0x00,
@@ -3616,7 +3721,7 @@ static const uint8_t unicode_prop_Other_Math_table[200] = {
0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90,
};
-static const uint8_t unicode_prop_Other_Alphabetic_table[417] = {
+static const uint8_t unicode_prop_Other_Alphabetic_table[428] = {
0x43, 0x44, 0x80, 0x42, 0x69, 0x8d, 0x00, 0x01,
0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x8c, 0x06, 0x8f,
0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80, 0xa2, 0x80,
@@ -3628,59 +3733,61 @@ static const uint8_t unicode_prop_Other_Alphabetic_table[417] = {
0x0a, 0x80, 0x8a, 0x82, 0xb9, 0x38, 0x10, 0x81,
0x94, 0x81, 0x95, 0x13, 0x82, 0xb9, 0x31, 0x09,
0x81, 0x88, 0x81, 0x89, 0x81, 0x9d, 0x80, 0xba,
- 0x22, 0x10, 0x82, 0x89, 0x80, 0xa7, 0x83, 0xb9,
+ 0x22, 0x10, 0x82, 0x89, 0x80, 0xa7, 0x84, 0xb8,
0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x9c, 0x82,
- 0xb9, 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x9b,
- 0x83, 0xb9, 0x30, 0x10, 0x82, 0x89, 0x80, 0x89,
- 0x81, 0x9c, 0x82, 0xca, 0x28, 0x00, 0x87, 0x91,
- 0x81, 0xbc, 0x01, 0x86, 0x91, 0x80, 0xe2, 0x01,
- 0x28, 0x81, 0x8f, 0x80, 0x40, 0xa2, 0x90, 0x8a,
- 0x8a, 0x80, 0xa3, 0xed, 0x8b, 0x00, 0x0b, 0x96,
- 0x1b, 0x10, 0x11, 0x32, 0x83, 0x8c, 0x8b, 0x00,
- 0x89, 0x83, 0x46, 0x73, 0x81, 0x9d, 0x81, 0x9d,
- 0x81, 0x9d, 0x81, 0xc1, 0x92, 0x40, 0xbb, 0x81,
- 0xa1, 0x80, 0xf5, 0x8b, 0x83, 0x88, 0x40, 0xdd,
- 0x84, 0xb8, 0x89, 0x81, 0x93, 0xc9, 0x81, 0x8a,
- 0x82, 0xb0, 0x84, 0xaf, 0x8e, 0xbb, 0x82, 0x9d,
- 0x88, 0x09, 0xb8, 0x8a, 0xb1, 0x92, 0x41, 0xaf,
- 0x8d, 0x46, 0xc0, 0xb3, 0x48, 0xf5, 0x9f, 0x60,
- 0x78, 0x73, 0x87, 0xa1, 0x81, 0x41, 0x61, 0x07,
- 0x80, 0x96, 0x84, 0xd7, 0x81, 0xb1, 0x8f, 0x00,
- 0xb8, 0x80, 0xa5, 0x84, 0x9b, 0x8b, 0xac, 0x83,
- 0xaf, 0x8b, 0xa4, 0x80, 0xc2, 0x8d, 0x8b, 0x07,
- 0x81, 0xac, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x80,
- 0xab, 0x24, 0x80, 0x40, 0xec, 0x87, 0x60, 0x4f,
- 0x32, 0x80, 0x48, 0x56, 0x84, 0x46, 0x85, 0x10,
- 0x0c, 0x83, 0x43, 0x13, 0x83, 0x41, 0x82, 0x81,
- 0x41, 0x52, 0x82, 0xb4, 0x8d, 0xac, 0x81, 0x8c,
- 0x80, 0xac, 0x88, 0x88, 0x80, 0xbc, 0x82, 0xa3,
- 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf, 0x8c, 0x8d,
- 0x81, 0xdb, 0x88, 0x08, 0x28, 0x40, 0x9f, 0x89,
- 0x96, 0x83, 0xb9, 0x31, 0x09, 0x81, 0x89, 0x80,
- 0x89, 0x81, 0x40, 0xd0, 0x8c, 0x02, 0xe9, 0x91,
- 0x40, 0xec, 0x31, 0x86, 0x9c, 0x81, 0xd1, 0x8e,
- 0x00, 0xe9, 0x8a, 0xe6, 0x8d, 0x41, 0x00, 0x8c,
- 0x40, 0xf6, 0x28, 0x09, 0x0a, 0x00, 0x80, 0x40,
- 0x8d, 0x31, 0x2b, 0x80, 0x9b, 0x89, 0xa9, 0x20,
- 0x83, 0x91, 0x8a, 0xad, 0x8d, 0x41, 0x96, 0x38,
- 0x86, 0xd2, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00,
- 0x08, 0x10, 0x02, 0x80, 0xc1, 0x20, 0x08, 0x83,
- 0x41, 0x5b, 0x83, 0x60, 0x50, 0x57, 0x00, 0xb6,
- 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80, 0x60,
- 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04, 0x49,
- 0x1b, 0x80, 0x47, 0xe7, 0x99, 0x85, 0x99, 0x85,
- 0x99,
+ 0xb9, 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x8e,
+ 0x80, 0x8b, 0x83, 0xb9, 0x30, 0x10, 0x82, 0x89,
+ 0x80, 0x89, 0x81, 0x9c, 0x82, 0xca, 0x28, 0x00,
+ 0x87, 0x91, 0x81, 0xbc, 0x01, 0x86, 0x91, 0x80,
+ 0xe2, 0x01, 0x28, 0x81, 0x8f, 0x80, 0x40, 0xa2,
+ 0x92, 0x88, 0x8a, 0x80, 0xa3, 0xed, 0x8b, 0x00,
+ 0x0b, 0x96, 0x1b, 0x10, 0x11, 0x32, 0x83, 0x8c,
+ 0x8b, 0x00, 0x89, 0x83, 0x46, 0x73, 0x81, 0x9d,
+ 0x81, 0x9d, 0x81, 0x9d, 0x81, 0xc1, 0x92, 0x40,
+ 0xbb, 0x81, 0xa1, 0x80, 0xf5, 0x8b, 0x83, 0x88,
+ 0x40, 0xdd, 0x84, 0xb8, 0x89, 0x81, 0x93, 0xc9,
+ 0x81, 0x8a, 0x82, 0xb0, 0x84, 0xaf, 0x8e, 0xbb,
+ 0x82, 0x9d, 0x88, 0x09, 0xb8, 0x8a, 0xb1, 0x92,
+ 0x41, 0xaf, 0x8d, 0x46, 0xc0, 0xb3, 0x48, 0xf5,
+ 0x9f, 0x60, 0x78, 0x73, 0x87, 0xa1, 0x81, 0x41,
+ 0x61, 0x07, 0x80, 0x96, 0x84, 0xd7, 0x81, 0xb1,
+ 0x8f, 0x00, 0xb8, 0x80, 0xa5, 0x84, 0x9b, 0x8b,
+ 0xac, 0x83, 0xaf, 0x8b, 0xa4, 0x80, 0xc2, 0x8d,
+ 0x8b, 0x07, 0x81, 0xac, 0x82, 0xb1, 0x00, 0x11,
+ 0x0c, 0x80, 0xab, 0x24, 0x80, 0x40, 0xec, 0x87,
+ 0x60, 0x4f, 0x32, 0x80, 0x48, 0x56, 0x84, 0x46,
+ 0x85, 0x10, 0x0c, 0x83, 0x43, 0x13, 0x83, 0x41,
+ 0x82, 0x81, 0x41, 0x52, 0x82, 0xb4, 0x8d, 0xac,
+ 0x81, 0x8a, 0x82, 0xac, 0x88, 0x88, 0x80, 0xbc,
+ 0x82, 0xa3, 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf,
+ 0x8c, 0x8d, 0x81, 0xdb, 0x88, 0x08, 0x28, 0x08,
+ 0x40, 0x9c, 0x89, 0x96, 0x83, 0xb9, 0x31, 0x09,
+ 0x81, 0x89, 0x80, 0x89, 0x81, 0x40, 0xd0, 0x8c,
+ 0x02, 0xe9, 0x91, 0x40, 0xec, 0x31, 0x86, 0x9c,
+ 0x81, 0xd1, 0x8e, 0x00, 0xe9, 0x8a, 0xe6, 0x8d,
+ 0x41, 0x00, 0x8c, 0x40, 0xf6, 0x28, 0x09, 0x0a,
+ 0x00, 0x80, 0x40, 0x8d, 0x31, 0x2b, 0x80, 0x9b,
+ 0x89, 0xa9, 0x20, 0x83, 0x91, 0x8a, 0xad, 0x8d,
+ 0x41, 0x96, 0x38, 0x86, 0xd2, 0x95, 0x80, 0x8d,
+ 0xf9, 0x2a, 0x00, 0x08, 0x10, 0x02, 0x80, 0xc1,
+ 0x20, 0x08, 0x83, 0x41, 0x5b, 0x83, 0x88, 0x08,
+ 0x80, 0xaf, 0x32, 0x82, 0x60, 0x50, 0x0d, 0x00,
+ 0xb6, 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80,
+ 0x60, 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04,
+ 0xe3, 0x80, 0x48, 0xb6, 0x80, 0x47, 0xe7, 0x99,
+ 0x85, 0x99, 0x85, 0x99,
};
-static const uint8_t unicode_prop_Other_Lowercase_table[59] = {
+static const uint8_t unicode_prop_Other_Lowercase_table[69] = {
0x40, 0xa9, 0x80, 0x8e, 0x80, 0x41, 0xf4, 0x88,
- 0x31, 0x9d, 0x84, 0xdf, 0x80, 0xb3, 0x80, 0x59,
- 0xb0, 0xbe, 0x8c, 0x80, 0xa1, 0xa4, 0x42, 0xb0,
- 0x80, 0x8c, 0x80, 0x8f, 0x8c, 0x40, 0xd2, 0x8f,
- 0x43, 0x4f, 0x99, 0x47, 0x91, 0x81, 0x60, 0x7a,
- 0x1d, 0x81, 0x40, 0xd1, 0x80, 0x40, 0x86, 0x81,
- 0x43, 0x61, 0x83, 0x60, 0x5c, 0x1f, 0x01, 0x10,
- 0xa9, 0x80, 0x88,
+ 0x31, 0x9d, 0x84, 0xdf, 0x80, 0xb3, 0x80, 0x4d,
+ 0x80, 0x80, 0x4c, 0x2e, 0xbe, 0x8c, 0x80, 0xa1,
+ 0xa4, 0x42, 0xb0, 0x80, 0x8c, 0x80, 0x8f, 0x8c,
+ 0x40, 0xd2, 0x8f, 0x43, 0x4f, 0x99, 0x47, 0x91,
+ 0x81, 0x60, 0x7a, 0x1d, 0x81, 0x40, 0xd1, 0x80,
+ 0x40, 0x80, 0x12, 0x81, 0x43, 0x61, 0x83, 0x88,
+ 0x80, 0x60, 0x5c, 0x15, 0x01, 0x10, 0xa9, 0x80,
+ 0x88, 0x60, 0xd8, 0x74, 0xbd,
};
static const uint8_t unicode_prop_Other_Uppercase_table[15] = {
@@ -3742,71 +3849,70 @@ static const uint8_t unicode_prop_Changes_When_Titlecased1_table[22] = {
0x8b, 0x80, 0x8e, 0x80, 0xae, 0x80,
};
-static const uint8_t unicode_prop_Changes_When_Casefolded1_table[33] = {
- 0x40, 0xde, 0x80, 0xcf, 0x80, 0x97, 0x80, 0x44,
- 0x3c, 0x80, 0x59, 0x11, 0x80, 0x40, 0xe4, 0x3f,
- 0x3f, 0x87, 0x89, 0x11, 0x05, 0x02, 0x11, 0x80,
- 0xa9, 0x11, 0x80, 0x60, 0xdb, 0x07, 0x86, 0x8b,
- 0x84,
+static const uint8_t unicode_prop_Changes_When_Casefolded1_table[29] = {
+ 0x41, 0xef, 0x80, 0x41, 0x9e, 0x80, 0x9e, 0x80,
+ 0x5a, 0xe4, 0x83, 0x40, 0xb5, 0x00, 0x00, 0x00,
+ 0x80, 0xde, 0x06, 0x06, 0x80, 0x8a, 0x09, 0x81,
+ 0x89, 0x10, 0x81, 0x8d, 0x80,
};
-static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[448] = {
+static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[447] = {
0x40, 0x9f, 0x06, 0x00, 0x01, 0x00, 0x01, 0x12,
- 0x10, 0x82, 0x9f, 0x80, 0xcf, 0x01, 0x80, 0x8b,
- 0x07, 0x80, 0xfb, 0x01, 0x01, 0x80, 0xa5, 0x80,
- 0x40, 0xbb, 0x88, 0x9e, 0x29, 0x84, 0xda, 0x08,
- 0x81, 0x89, 0x80, 0xa3, 0x04, 0x02, 0x04, 0x08,
- 0x80, 0xc9, 0x82, 0x9c, 0x80, 0x41, 0x93, 0x80,
- 0x40, 0x93, 0x80, 0xd7, 0x83, 0x42, 0xde, 0x87,
- 0xfb, 0x08, 0x80, 0xd2, 0x01, 0x80, 0xa1, 0x11,
- 0x80, 0x40, 0xfc, 0x81, 0x42, 0xd4, 0x80, 0xfe,
- 0x80, 0xa7, 0x81, 0xad, 0x80, 0xb5, 0x80, 0x88,
- 0x03, 0x03, 0x03, 0x80, 0x8b, 0x80, 0x88, 0x00,
- 0x26, 0x80, 0x90, 0x80, 0x88, 0x03, 0x03, 0x03,
- 0x80, 0x8b, 0x80, 0x41, 0x41, 0x80, 0xe1, 0x81,
- 0x46, 0x52, 0x81, 0xd4, 0x84, 0x45, 0x1b, 0x10,
- 0x8a, 0x80, 0x91, 0x80, 0x9b, 0x8c, 0x80, 0xa1,
- 0xa4, 0x40, 0xd9, 0x80, 0x40, 0xd5, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x3f, 0x87,
- 0x89, 0x11, 0x04, 0x00, 0x29, 0x04, 0x12, 0x80,
- 0x88, 0x12, 0x80, 0x88, 0x11, 0x11, 0x04, 0x08,
- 0x8f, 0x00, 0x20, 0x8b, 0x12, 0x2a, 0x08, 0x0b,
- 0x00, 0x07, 0x82, 0x8c, 0x06, 0x92, 0x81, 0x9a,
- 0x80, 0x8c, 0x8a, 0x80, 0xd6, 0x18, 0x10, 0x8a,
- 0x01, 0x0c, 0x0a, 0x00, 0x10, 0x11, 0x02, 0x06,
- 0x05, 0x1c, 0x85, 0x8f, 0x8f, 0x8f, 0x88, 0x80,
- 0x40, 0xa1, 0x08, 0x81, 0x40, 0xf7, 0x81, 0x41,
- 0x34, 0xd5, 0x99, 0x9a, 0x45, 0x20, 0x80, 0xe6,
- 0x82, 0xe4, 0x80, 0x41, 0x9e, 0x81, 0x40, 0xf0,
- 0x80, 0x41, 0x2e, 0x80, 0xd2, 0x80, 0x8b, 0x40,
- 0xd5, 0xa9, 0x80, 0xb4, 0x00, 0x82, 0xdf, 0x09,
- 0x80, 0xde, 0x80, 0xb0, 0xdd, 0x82, 0x8d, 0xdf,
- 0x9e, 0x80, 0xa7, 0x87, 0xae, 0x80, 0x41, 0x7f,
- 0x60, 0x72, 0x9b, 0x81, 0x40, 0xd1, 0x80, 0x40,
- 0x80, 0x12, 0x81, 0x43, 0x61, 0x83, 0x88, 0x80,
- 0x60, 0x4d, 0x95, 0x41, 0x0d, 0x08, 0x00, 0x81,
- 0x89, 0x00, 0x00, 0x09, 0x82, 0xc3, 0x81, 0xe9,
- 0xa5, 0x86, 0x8b, 0x24, 0x00, 0x97, 0x04, 0x00,
- 0x01, 0x01, 0x80, 0xeb, 0xa0, 0x41, 0x6a, 0x91,
- 0xbf, 0x81, 0xb5, 0xa7, 0x8c, 0x82, 0x99, 0x95,
- 0x94, 0x81, 0x8b, 0x80, 0x92, 0x03, 0x1a, 0x00,
- 0x80, 0x40, 0x86, 0x08, 0x80, 0x9f, 0x99, 0x40,
- 0x83, 0x15, 0x0d, 0x0d, 0x0a, 0x16, 0x06, 0x80,
- 0x88, 0x47, 0x87, 0x20, 0xa9, 0x80, 0x88, 0x60,
- 0xb4, 0xe4, 0x83, 0x54, 0xb9, 0x86, 0x8d, 0x87,
- 0xbf, 0x85, 0x42, 0x3e, 0xd4, 0x80, 0xc6, 0x01,
- 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80,
- 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04,
- 0x00, 0x16, 0x80, 0x41, 0x53, 0x81, 0x41, 0x23,
- 0x81, 0xb1, 0x55, 0xff, 0x18, 0x9a, 0x01, 0x00,
- 0x08, 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18,
- 0x00, 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03,
- 0x00, 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80,
- 0x90, 0x42, 0x43, 0x8a, 0x84, 0x9e, 0x80, 0x9f,
- 0x99, 0x82, 0xa2, 0x80, 0xee, 0x82, 0x8c, 0xab,
- 0x83, 0x88, 0x31, 0x49, 0x9d, 0x89, 0x60, 0xfc,
- 0x05, 0x42, 0x1d, 0x6b, 0x05, 0xe1, 0x4f, 0xff,
+ 0x10, 0x82, 0xf3, 0x80, 0x8b, 0x80, 0x40, 0x84,
+ 0x01, 0x01, 0x80, 0xa2, 0x01, 0x80, 0x40, 0xbb,
+ 0x88, 0x9e, 0x29, 0x84, 0xda, 0x08, 0x81, 0x89,
+ 0x80, 0xa3, 0x04, 0x02, 0x04, 0x08, 0x07, 0x80,
+ 0x9e, 0x80, 0xa0, 0x82, 0x9c, 0x80, 0x42, 0x28,
+ 0x80, 0xd7, 0x83, 0x42, 0xde, 0x87, 0xfb, 0x08,
+ 0x80, 0xd2, 0x01, 0x80, 0xa1, 0x11, 0x80, 0x40,
+ 0xfc, 0x81, 0x42, 0xd4, 0x80, 0xfe, 0x80, 0xa7,
+ 0x81, 0xad, 0x80, 0xb5, 0x80, 0x88, 0x03, 0x03,
+ 0x03, 0x80, 0x8b, 0x80, 0x88, 0x00, 0x26, 0x80,
+ 0x90, 0x80, 0x88, 0x03, 0x03, 0x03, 0x80, 0x8b,
+ 0x80, 0x41, 0x41, 0x80, 0xe1, 0x81, 0x46, 0x52,
+ 0x81, 0xd4, 0x84, 0x45, 0x1b, 0x10, 0x8a, 0x80,
+ 0x91, 0x80, 0x9b, 0x8c, 0x80, 0xa1, 0xa4, 0x40,
+ 0xd5, 0x83, 0x40, 0xb5, 0x00, 0x00, 0x00, 0x80,
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xb7, 0x05, 0x00, 0x13, 0x05, 0x11, 0x02, 0x0c,
+ 0x11, 0x00, 0x00, 0x0c, 0x15, 0x05, 0x08, 0x8f,
+ 0x00, 0x20, 0x8b, 0x12, 0x2a, 0x08, 0x0b, 0x00,
+ 0x07, 0x82, 0x8c, 0x06, 0x92, 0x81, 0x9a, 0x80,
+ 0x8c, 0x8a, 0x80, 0xd6, 0x18, 0x10, 0x8a, 0x01,
+ 0x0c, 0x0a, 0x00, 0x10, 0x11, 0x02, 0x06, 0x05,
+ 0x1c, 0x85, 0x8f, 0x8f, 0x8f, 0x88, 0x80, 0x40,
+ 0xa1, 0x08, 0x81, 0x40, 0xf7, 0x81, 0x41, 0x34,
+ 0xd5, 0x99, 0x9a, 0x45, 0x20, 0x80, 0xe6, 0x82,
+ 0xe4, 0x80, 0x41, 0x9e, 0x81, 0x40, 0xf0, 0x80,
+ 0x41, 0x2e, 0x80, 0xd2, 0x80, 0x8b, 0x40, 0xd5,
+ 0xa9, 0x80, 0xb4, 0x00, 0x82, 0xdf, 0x09, 0x80,
+ 0xde, 0x80, 0xb0, 0xdd, 0x82, 0x8d, 0xdf, 0x9e,
+ 0x80, 0xa7, 0x87, 0xae, 0x80, 0x41, 0x7f, 0x60,
+ 0x72, 0x9b, 0x81, 0x40, 0xd1, 0x80, 0x40, 0x80,
+ 0x12, 0x81, 0x43, 0x61, 0x83, 0x88, 0x80, 0x60,
+ 0x4d, 0x95, 0x41, 0x0d, 0x08, 0x00, 0x81, 0x89,
+ 0x00, 0x00, 0x09, 0x82, 0xc3, 0x81, 0xe9, 0xc2,
+ 0x00, 0x97, 0x04, 0x00, 0x01, 0x01, 0x80, 0xeb,
+ 0xa0, 0x41, 0x6a, 0x91, 0xbf, 0x81, 0xb5, 0xa7,
+ 0x8c, 0x82, 0x99, 0x95, 0x94, 0x81, 0x8b, 0x80,
+ 0x92, 0x03, 0x1a, 0x00, 0x80, 0x40, 0x86, 0x08,
+ 0x80, 0x9f, 0x99, 0x40, 0x83, 0x15, 0x0d, 0x0d,
+ 0x0a, 0x16, 0x06, 0x80, 0x88, 0x47, 0x87, 0x20,
+ 0xa9, 0x80, 0x88, 0x60, 0xb4, 0xe4, 0x83, 0x54,
+ 0xb9, 0x86, 0x8d, 0x87, 0xbf, 0x85, 0x42, 0x3e,
+ 0xd4, 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80,
+ 0x8b, 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06,
+ 0x80, 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, 0x41,
+ 0x53, 0x81, 0x41, 0x23, 0x81, 0xb1, 0x48, 0x2f,
+ 0xbd, 0x4d, 0x91, 0x18, 0x9a, 0x01, 0x00, 0x08,
+ 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00,
+ 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00,
+ 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90,
+ 0x42, 0x43, 0x8a, 0x84, 0x9e, 0x80, 0x9f, 0x99,
+ 0x82, 0xa2, 0x80, 0xee, 0x82, 0x8c, 0xab, 0x83,
+ 0x88, 0x31, 0x49, 0x9d, 0x89, 0x60, 0xfc, 0x05,
+ 0x42, 0x1d, 0x6b, 0x05, 0xe1, 0x4f, 0xff,
};
static const uint8_t unicode_prop_ASCII_Hex_Digit_table[5] = {
@@ -3834,7 +3940,7 @@ static const uint8_t unicode_prop_Deprecated_table[23] = {
0x42, 0xb8, 0x81, 0x6d, 0xdc, 0xd5, 0x80,
};
-static const uint8_t unicode_prop_Diacritic_table[391] = {
+static const uint8_t unicode_prop_Diacritic_table[399] = {
0xdd, 0x00, 0x80, 0xc6, 0x05, 0x03, 0x01, 0x81,
0x41, 0xf6, 0x40, 0x9e, 0x07, 0x25, 0x90, 0x0b,
0x80, 0x88, 0x81, 0x40, 0xfc, 0x84, 0x40, 0xd0,
@@ -3869,20 +3975,21 @@ static const uint8_t unicode_prop_Diacritic_table[391] = {
0x00, 0x8f, 0x41, 0x0d, 0x00, 0x80, 0xae, 0x80,
0xac, 0x81, 0xc2, 0x80, 0x42, 0xfb, 0x80, 0x44,
0x9e, 0x28, 0xa9, 0x80, 0x88, 0x43, 0x29, 0x81,
- 0x42, 0x3a, 0x85, 0x42, 0x1d, 0x8a, 0xb0, 0x83,
- 0x40, 0xbf, 0x80, 0xa8, 0x80, 0xc7, 0x81, 0xf7,
- 0x81, 0xbd, 0x80, 0xcb, 0x80, 0x88, 0x82, 0xe7,
- 0x81, 0x40, 0xb1, 0x81, 0xd0, 0x80, 0x8f, 0x80,
- 0x97, 0x32, 0x84, 0x40, 0xcc, 0x02, 0x80, 0xfa,
- 0x81, 0x40, 0xfa, 0x81, 0xfd, 0x80, 0xf5, 0x81,
- 0xf2, 0x80, 0x41, 0x0c, 0x81, 0x41, 0x01, 0x0b,
- 0x80, 0x40, 0x9b, 0x80, 0xd2, 0x80, 0x91, 0x80,
- 0xd0, 0x80, 0x41, 0xa4, 0x80, 0x41, 0x01, 0x00,
- 0x81, 0xd0, 0x80, 0x60, 0x4d, 0x57, 0x84, 0xba,
- 0x86, 0x44, 0x57, 0x90, 0xcf, 0x81, 0x60, 0x3f,
- 0xfd, 0x18, 0x30, 0x81, 0x5f, 0x00, 0xad, 0x81,
- 0x96, 0x42, 0x1f, 0x12, 0x2f, 0x39, 0x86, 0x9d,
- 0x83, 0x4f, 0x81, 0x86, 0x41, 0x76, 0x80, 0xbc,
+ 0x42, 0x3a, 0x85, 0x41, 0xd4, 0x82, 0xc5, 0x8a,
+ 0xb0, 0x83, 0x40, 0xbf, 0x80, 0xa8, 0x80, 0xc7,
+ 0x81, 0xf7, 0x81, 0xbd, 0x80, 0xcb, 0x80, 0x88,
+ 0x82, 0xe7, 0x81, 0x40, 0xb1, 0x81, 0xd0, 0x80,
+ 0x8f, 0x80, 0x97, 0x32, 0x84, 0x40, 0xcc, 0x02,
+ 0x80, 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd, 0x80,
+ 0xf5, 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81, 0x41,
+ 0x01, 0x0b, 0x80, 0x40, 0x9b, 0x80, 0xd2, 0x80,
+ 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80, 0x41,
+ 0x01, 0x00, 0x81, 0xd0, 0x80, 0x56, 0xae, 0x8e,
+ 0x60, 0x36, 0x99, 0x84, 0xba, 0x86, 0x44, 0x57,
+ 0x90, 0xcf, 0x81, 0x60, 0x3f, 0xfd, 0x18, 0x30,
+ 0x81, 0x5f, 0x00, 0xad, 0x81, 0x96, 0x42, 0x1f,
+ 0x12, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x4e, 0x81,
+ 0xbd, 0x40, 0xc1, 0x86, 0x41, 0x76, 0x80, 0xbc,
0x83, 0x45, 0xdf, 0x86, 0xec, 0x10, 0x82,
};
@@ -3914,16 +4021,16 @@ static const uint8_t unicode_prop_IDS_Trinary_Operator_table[4] = {
0x60, 0x2f, 0xf1, 0x81,
};
-static const uint8_t unicode_prop_Ideographic_table[66] = {
+static const uint8_t unicode_prop_Ideographic_table[69] = {
0x60, 0x30, 0x05, 0x81, 0x98, 0x88, 0x8d, 0x82,
0x43, 0xc4, 0x59, 0xbf, 0xbf, 0x60, 0x51, 0xff,
0x60, 0x58, 0xff, 0x41, 0x6d, 0x81, 0xe9, 0x60,
0x75, 0x09, 0x80, 0x9a, 0x57, 0xf7, 0x87, 0x44,
0xd5, 0xa9, 0x88, 0x60, 0x24, 0x66, 0x41, 0x8b,
0x60, 0x4d, 0x03, 0x60, 0xa6, 0xdf, 0x9f, 0x50,
- 0x38, 0x86, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d,
+ 0x39, 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d,
0x5d, 0x30, 0x4c, 0x1e, 0x42, 0x1d, 0x45, 0xe1,
- 0x53, 0x4a,
+ 0x53, 0x4a, 0x84, 0x50, 0x5f,
};
static const uint8_t unicode_prop_Join_Control_table[4] = {
@@ -3979,7 +4086,7 @@ static const uint8_t unicode_prop_Regional_Indicator_table[4] = {
0x61, 0xf1, 0xe5, 0x99,
};
-static const uint8_t unicode_prop_Sentence_Terminal_table[194] = {
+static const uint8_t unicode_prop_Sentence_Terminal_table[196] = {
0xa0, 0x80, 0x8b, 0x80, 0x8f, 0x80, 0x45, 0x48,
0x80, 0x40, 0x92, 0x82, 0x40, 0xb3, 0x80, 0xaa,
0x82, 0x40, 0xf5, 0x80, 0xbc, 0x00, 0x02, 0x81,
@@ -4001,13 +4108,13 @@ static const uint8_t unicode_prop_Sentence_Terminal_table[194] = {
0xeb, 0x80, 0x41, 0xa0, 0x81, 0x41, 0x74, 0x0c,
0x8e, 0xe8, 0x81, 0x40, 0xf8, 0x82, 0x42, 0x04,
0x00, 0x80, 0x40, 0xfa, 0x81, 0xd6, 0x81, 0x41,
- 0xa3, 0x81, 0x42, 0xb3, 0x81, 0x60, 0x4b, 0x74,
- 0x81, 0x40, 0x84, 0x80, 0xc0, 0x81, 0x8a, 0x80,
- 0x43, 0x52, 0x80, 0x60, 0x4e, 0x05, 0x80, 0x5d,
- 0xe7, 0x80,
+ 0xa3, 0x81, 0x42, 0xb3, 0x81, 0xc9, 0x81, 0x60,
+ 0x4b, 0x28, 0x81, 0x40, 0x84, 0x80, 0xc0, 0x81,
+ 0x8a, 0x80, 0x43, 0x52, 0x80, 0x60, 0x4e, 0x05,
+ 0x80, 0x5d, 0xe7, 0x80,
};
-static const uint8_t unicode_prop_Soft_Dotted_table[74] = {
+static const uint8_t unicode_prop_Soft_Dotted_table[79] = {
0xe8, 0x81, 0x40, 0xc3, 0x80, 0x41, 0x18, 0x80,
0x9d, 0x80, 0xb3, 0x80, 0x93, 0x80, 0x41, 0x3f,
0x80, 0xe1, 0x00, 0x80, 0x59, 0x08, 0x80, 0xb2,
@@ -4017,10 +4124,10 @@ static const uint8_t unicode_prop_Soft_Dotted_table[74] = {
0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1,
0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1,
0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0x48,
- 0x85, 0x80,
+ 0x85, 0x80, 0x41, 0x30, 0x81, 0x99, 0x80,
};
-static const uint8_t unicode_prop_Terminal_Punctuation_table[246] = {
+static const uint8_t unicode_prop_Terminal_Punctuation_table[248] = {
0xa0, 0x80, 0x89, 0x00, 0x80, 0x8a, 0x0a, 0x80,
0x43, 0x3d, 0x07, 0x80, 0x42, 0x00, 0x80, 0xb8,
0x80, 0xc7, 0x80, 0x8d, 0x00, 0x82, 0x40, 0xb3,
@@ -4048,19 +4155,19 @@ static const uint8_t unicode_prop_Terminal_Punctuation_table[246] = {
0x82, 0x8b, 0x81, 0x41, 0x65, 0x1a, 0x8e, 0xe8,
0x81, 0x40, 0xf8, 0x82, 0x42, 0x04, 0x00, 0x80,
0x40, 0xfa, 0x81, 0xd6, 0x0b, 0x81, 0x41, 0x9d,
- 0x82, 0xac, 0x80, 0x42, 0x84, 0x81, 0x45, 0x76,
- 0x84, 0x60, 0x45, 0xf8, 0x81, 0x40, 0x84, 0x80,
- 0xc0, 0x82, 0x89, 0x80, 0x43, 0x51, 0x81, 0x60,
- 0x4e, 0x05, 0x80, 0x5d, 0xe6, 0x83,
+ 0x82, 0xac, 0x80, 0x42, 0x84, 0x81, 0xc9, 0x81,
+ 0x45, 0x2a, 0x84, 0x60, 0x45, 0xf8, 0x81, 0x40,
+ 0x84, 0x80, 0xc0, 0x82, 0x89, 0x80, 0x43, 0x51,
+ 0x81, 0x60, 0x4e, 0x05, 0x80, 0x5d, 0xe6, 0x83,
};
-static const uint8_t unicode_prop_Unified_Ideograph_table[42] = {
+static const uint8_t unicode_prop_Unified_Ideograph_table[45] = {
0x60, 0x33, 0xff, 0x59, 0xbf, 0xbf, 0x60, 0x51,
0xff, 0x60, 0x5a, 0x0d, 0x08, 0x00, 0x81, 0x89,
0x00, 0x00, 0x09, 0x82, 0x61, 0x05, 0xd5, 0x60,
- 0xa6, 0xdf, 0x9f, 0x50, 0x38, 0x86, 0x40, 0xdd,
+ 0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40, 0xdd,
0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x54, 0x1e,
- 0x53, 0x4a,
+ 0x53, 0x4a, 0x84, 0x50, 0x5f,
};
static const uint8_t unicode_prop_Variation_Selector_table[13] = {
@@ -4125,11 +4232,11 @@ static const uint8_t unicode_prop_Emoji_table[239] = {
0xbe, 0x8a, 0x28, 0x97, 0x31, 0x0f, 0x8b, 0x01,
0x19, 0x03, 0x81, 0x8c, 0x09, 0x07, 0x81, 0x88,
0x04, 0x82, 0x8b, 0x17, 0x11, 0x00, 0x03, 0x05,
- 0x02, 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x0a, 0x84,
- 0x88, 0x10, 0x01, 0x10, 0x81, 0x89, 0x40, 0xe2,
+ 0x02, 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x0a, 0x83,
+ 0x89, 0x10, 0x01, 0x10, 0x81, 0x89, 0x40, 0xe2,
0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80, 0x89, 0x80,
- 0x40, 0xb8, 0xef, 0x22, 0x22, 0x86, 0x88, 0x9c,
- 0x82, 0x8a, 0x25, 0x89, 0x89, 0x2f, 0x3e,
+ 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x88, 0x86, 0xad,
+ 0x06, 0x87, 0x8d, 0x83, 0x88, 0x86, 0x88,
};
static const uint8_t unicode_prop_Emoji_Component_table[28] = {
@@ -4152,7 +4259,7 @@ static const uint8_t unicode_prop_Emoji_Modifier_Base_table[71] = {
0xd2, 0x80, 0x8f, 0x82, 0x88, 0x80, 0x8a, 0x80,
0x42, 0x3e, 0x01, 0x07, 0x3d, 0x80, 0x88, 0x89,
0x0a, 0xb7, 0x80, 0xbc, 0x08, 0x08, 0x80, 0x90,
- 0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, 0x86,
+ 0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, 0x88,
};
static const uint8_t unicode_prop_Emoji_Presentation_table[145] = {
@@ -4170,11 +4277,11 @@ static const uint8_t unicode_prop_Emoji_Presentation_table[145] = {
0x1c, 0x8b, 0x90, 0x10, 0x82, 0xc6, 0x00, 0x80,
0x40, 0xba, 0x81, 0xbe, 0x8c, 0x18, 0x97, 0x91,
0x80, 0x99, 0x81, 0x8c, 0x80, 0xd5, 0xd4, 0xaf,
- 0xc5, 0x28, 0x12, 0x0a, 0x22, 0x8a, 0x0e, 0x88,
+ 0xc5, 0x28, 0x12, 0x0a, 0x1b, 0x8a, 0x0e, 0x88,
0x40, 0xe2, 0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80,
- 0x89, 0x80, 0x40, 0xb8, 0xef, 0x22, 0x22, 0x86,
- 0x88, 0x9c, 0x82, 0x8a, 0x25, 0x89, 0x89, 0x2f,
- 0x3e,
+ 0x89, 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x88,
+ 0x86, 0xad, 0x06, 0x87, 0x8d, 0x83, 0x88, 0x86,
+ 0x88,
};
static const uint8_t unicode_prop_Extended_Pictographic_table[156] = {
@@ -4447,3 +4554,4 @@ static const uint16_t unicode_prop_len_table[] = {
};
#endif /* CONFIG_ALL_UNICODE */
+/* 62 tables / 32261 bytes, 5 index / 345 bytes */
diff --git a/src/shared/quickjs/libunicode.c b/src/shared/quickjs/libunicode.c
index 112da72da..482c51944 100644
--- a/src/shared/quickjs/libunicode.c
+++ b/src/shared/quickjs/libunicode.c
@@ -43,11 +43,111 @@ enum {
RUN_TYPE_UF_D1_EXT,
RUN_TYPE_U_EXT,
RUN_TYPE_LF_EXT,
- RUN_TYPE_U_EXT2,
- RUN_TYPE_L_EXT2,
- RUN_TYPE_U_EXT3,
+ RUN_TYPE_UF_EXT2,
+ RUN_TYPE_LF_EXT2,
+ RUN_TYPE_UF_EXT3,
};
+static int lre_case_conv1(uint32_t c, int conv_type)
+{
+ uint32_t res[LRE_CC_RES_LEN_MAX];
+ lre_case_conv(res, c, conv_type);
+ return res[0];
+}
+
+/* case conversion using the table entry 'idx' with value 'v' */
+static int lre_case_conv_entry(uint32_t *res, uint32_t c, int conv_type, uint32_t idx, uint32_t v)
+{
+ uint32_t code, data, type, a, is_lower;
+ is_lower = (conv_type != 0);
+ type = (v >> (32 - 17 - 7 - 4)) & 0xf;
+ data = ((v & 0xf) << 8) | case_conv_table2[idx];
+ code = v >> (32 - 17);
+ switch(type) {
+ case RUN_TYPE_U:
+ case RUN_TYPE_L:
+ case RUN_TYPE_UF:
+ case RUN_TYPE_LF:
+ if (conv_type == (type & 1) ||
+ (type >= RUN_TYPE_UF && conv_type == 2)) {
+ c = c - code + (case_conv_table1[data] >> (32 - 17));
+ }
+ break;
+ case RUN_TYPE_UL:
+ a = c - code;
+ if ((a & 1) != (1 - is_lower))
+ break;
+ c = (a ^ 1) + code;
+ break;
+ case RUN_TYPE_LSU:
+ a = c - code;
+ if (a == 1) {
+ c += 2 * is_lower - 1;
+ } else if (a == (1 - is_lower) * 2) {
+ c += (2 * is_lower - 1) * 2;
+ }
+ break;
+ case RUN_TYPE_U2L_399_EXT2:
+ if (!is_lower) {
+ res[0] = c - code + case_conv_ext[data >> 6];
+ res[1] = 0x399;
+ return 2;
+ } else {
+ c = c - code + case_conv_ext[data & 0x3f];
+ }
+ break;
+ case RUN_TYPE_UF_D20:
+ if (conv_type == 1)
+ break;
+ c = data + (conv_type == 2) * 0x20;
+ break;
+ case RUN_TYPE_UF_D1_EXT:
+ if (conv_type == 1)
+ break;
+ c = case_conv_ext[data] + (conv_type == 2);
+ break;
+ case RUN_TYPE_U_EXT:
+ case RUN_TYPE_LF_EXT:
+ if (is_lower != (type - RUN_TYPE_U_EXT))
+ break;
+ c = case_conv_ext[data];
+ break;
+ case RUN_TYPE_LF_EXT2:
+ if (!is_lower)
+ break;
+ res[0] = c - code + case_conv_ext[data >> 6];
+ res[1] = case_conv_ext[data & 0x3f];
+ return 2;
+ case RUN_TYPE_UF_EXT2:
+ if (conv_type == 1)
+ break;
+ res[0] = c - code + case_conv_ext[data >> 6];
+ res[1] = case_conv_ext[data & 0x3f];
+ if (conv_type == 2) {
+ /* convert to lower */
+ res[0] = lre_case_conv1(res[0], 1);
+ res[1] = lre_case_conv1(res[1], 1);
+ }
+ return 2;
+ default:
+ case RUN_TYPE_UF_EXT3:
+ if (conv_type == 1)
+ break;
+ res[0] = case_conv_ext[data >> 8];
+ res[1] = case_conv_ext[(data >> 4) & 0xf];
+ res[2] = case_conv_ext[data & 0xf];
+ if (conv_type == 2) {
+ /* convert to lower */
+ res[0] = lre_case_conv1(res[0], 1);
+ res[1] = lre_case_conv1(res[1], 1);
+ res[2] = lre_case_conv1(res[2], 1);
+ }
+ return 3;
+ }
+ res[0] = c;
+ return 1;
+}
+
/* conv_type:
0 = to upper
1 = to lower
@@ -66,10 +166,9 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
}
}
} else {
- uint32_t v, code, data, type, len, a, is_lower;
+ uint32_t v, code, len;
int idx, idx_min, idx_max;
- is_lower = (conv_type != 0);
idx_min = 0;
idx_max = countof(case_conv_table1) - 1;
while (idx_min <= idx_max) {
@@ -82,74 +181,7 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
} else if (c >= code + len) {
idx_min = idx + 1;
} else {
- type = (v >> (32 - 17 - 7 - 4)) & 0xf;
- data = ((v & 0xf) << 8) | case_conv_table2[idx];
- switch(type) {
- case RUN_TYPE_U:
- case RUN_TYPE_L:
- case RUN_TYPE_UF:
- case RUN_TYPE_LF:
- if (conv_type == (type & 1) ||
- (type >= RUN_TYPE_UF && conv_type == 2)) {
- c = c - code + (case_conv_table1[data] >> (32 - 17));
- }
- break;
- case RUN_TYPE_UL:
- a = c - code;
- if ((a & 1) != (1 - is_lower))
- break;
- c = (a ^ 1) + code;
- break;
- case RUN_TYPE_LSU:
- a = c - code;
- if (a == 1) {
- c += 2 * is_lower - 1;
- } else if (a == (1 - is_lower) * 2) {
- c += (2 * is_lower - 1) * 2;
- }
- break;
- case RUN_TYPE_U2L_399_EXT2:
- if (!is_lower) {
- res[0] = c - code + case_conv_ext[data >> 6];
- res[1] = 0x399;
- return 2;
- } else {
- c = c - code + case_conv_ext[data & 0x3f];
- }
- break;
- case RUN_TYPE_UF_D20:
- if (conv_type == 1)
- break;
- c = data + (conv_type == 2) * 0x20;
- break;
- case RUN_TYPE_UF_D1_EXT:
- if (conv_type == 1)
- break;
- c = case_conv_ext[data] + (conv_type == 2);
- break;
- case RUN_TYPE_U_EXT:
- case RUN_TYPE_LF_EXT:
- if (is_lower != (type - RUN_TYPE_U_EXT))
- break;
- c = case_conv_ext[data];
- break;
- case RUN_TYPE_U_EXT2:
- case RUN_TYPE_L_EXT2:
- if (conv_type != (type - RUN_TYPE_U_EXT2))
- break;
- res[0] = c - code + case_conv_ext[data >> 6];
- res[1] = case_conv_ext[data & 0x3f];
- return 2;
- default:
- case RUN_TYPE_U_EXT3:
- if (conv_type != 0)
- break;
- res[0] = case_conv_ext[data >> 8];
- res[1] = case_conv_ext[(data >> 4) & 0xf];
- res[2] = case_conv_ext[data & 0xf];
- return 3;
- }
- break;
+ return lre_case_conv_entry(res, c, conv_type, idx, v);
}
}
}
@@ -157,13 +189,80 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
return 1;
}
+static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, BOOL is_unicode)
+{
+ uint32_t res[LRE_CC_RES_LEN_MAX];
+ int len;
+
+ if (is_unicode) {
+ len = lre_case_conv_entry(res, c, 2, idx, v);
+ if (len == 1) {
+ c = res[0];
+ } else {
+ /* handle the few specific multi-character cases (see
+ unicode_gen.c:dump_case_folding_special_cases()) */
+ if (c == 0xfb06) {
+ c = 0xfb05;
+ } else if (c == 0x01fd3) {
+ c = 0x390;
+ } else if (c == 0x01fe3) {
+ c = 0x3b0;
+ }
+ }
+ } else {
+ if (likely(c < 128)) {
+ if (c >= 'a' && c <= 'z')
+ c = c - 'a' + 'A';
+ } else {
+ /* legacy regexp: to upper case if single char >= 128 */
+ len = lre_case_conv_entry(res, c, FALSE, idx, v);
+ if (len == 1 && res[0] >= 128)
+ c = res[0];
+ }
+ }
+ return c;
+}
+
+/* JS regexp specific rules for case folding */
+int lre_canonicalize(uint32_t c, BOOL is_unicode)
+{
+ if (c < 128) {
+ /* fast case */
+ if (is_unicode) {
+ if (c >= 'A' && c <= 'Z') {
+ c = c - 'A' + 'a';
+ }
+ } else {
+ if (c >= 'a' && c <= 'z') {
+ c = c - 'a' + 'A';
+ }
+ }
+ } else {
+ 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) {
+ idx = (unsigned)(idx_max + idx_min) / 2;
+ v = case_conv_table1[idx];
+ code = v >> (32 - 17);
+ len = (v >> (32 - 17 - 7)) & 0x7f;
+ if (c < code) {
+ idx_max = idx - 1;
+ } else if (c >= code + len) {
+ idx_min = idx + 1;
+ } else {
+ return lre_case_folding_entry(c, idx, v, is_unicode);
+ }
+ }
+ }
+ return c;
+}
+
static uint32_t get_le24(const uint8_t *ptr)
{
-#if defined(__x86__) || defined(__x86_64__)
- return *(uint16_t *)ptr | (ptr[2] << 16);
-#else
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
-#endif
}
#define UNICODE_INDEX_BLOCK_LEN 32
@@ -214,6 +313,14 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table,
return FALSE; /* outside the table */
p = table + pos;
bit = 0;
+ /* Compressed run length encoding:
+ 00..3F: 2 packed lengths: 3-bit + 3-bit
+ 40..5F: 5-bits plus extra byte for length
+ 60..7F: 5-bits plus 2 extra bytes for length
+ 80..FF: 7-bit length
+ lengths must be incremented to get character count
+ Ranges alternate between false and true return value.
+ */
for(;;) {
b = *p++;
if (b < 64) {
@@ -271,7 +378,7 @@ BOOL lre_is_case_ignorable(uint32_t c)
/* character range */
-static maybe_unused void cr_dump(CharRange *cr)
+static __maybe_unused void cr_dump(CharRange *cr)
{
int i;
for(i = 0; i < cr->len; i++)
@@ -327,7 +434,7 @@ static void cr_compress(CharRange *cr)
{
int i, j, k, len;
uint32_t *pt;
-
+
pt = cr->points;
len = cr->len;
i = 0;
@@ -730,6 +837,13 @@ static int unicode_get_cc(uint32_t c)
if (pos < 0)
return 0;
p = unicode_cc_table + pos;
+ /* Compressed run length encoding:
+ - 2 high order bits are combining class type
+ - 0:0, 1:230, 2:extra byte linear progression, 3:extra byte
+ - 00..2F: range length (add 1)
+ - 30..37: 3-bit range-length + 1 extra byte
+ - 38..3F: 3-bit range-length + 2 extra byte
+ */
for(;;) {
b = *p++;
type = b >> 6;
@@ -1082,6 +1196,15 @@ static int unicode_general_category1(CharRange *cr, uint32_t gc_mask)
p = unicode_gc_table;
p_end = unicode_gc_table + countof(unicode_gc_table);
c = 0;
+ /* Compressed range encoding:
+ initial byte:
+ bits 0..4: category number (special case 31)
+ bits 5..7: range length (add 1)
+ special case bits 5..7 == 7: read an extra byte
+ - 00..7F: range length (add 7 + 1)
+ - 80..BF: 6-bits plus extra byte for range length (add 7 + 128)
+ - C0..FF: 6-bits plus 2 extra bytes for range length (add 7 + 128 + 16384)
+ */
while (p < p_end) {
b = *p++;
n = b >> 5;
@@ -1135,6 +1258,14 @@ static int unicode_prop1(CharRange *cr, int prop_idx)
p_end = p + unicode_prop_len_table[prop_idx];
c = 0;
bit = 0;
+ /* Compressed range encoding:
+ 00..3F: 2 packed lengths: 3-bit + 3-bit
+ 40..5F: 5-bits plus extra byte for length
+ 60..7F: 5-bits plus 2 extra bytes for length
+ 80..FF: 7-bit length
+ lengths must be incremented to get character count
+ Ranges alternate between false and true return value.
+ */
while (p < p_end) {
c0 = c;
b = *p++;
@@ -1179,11 +1310,11 @@ static int unicode_case1(CharRange *cr, int case_mask)
#define MR(x) (1 << RUN_TYPE_ ## x)
const uint32_t tab_run_mask[3] = {
MR(U) | MR(UF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(UF_D20) |
- MR(UF_D1_EXT) | MR(U_EXT) | MR(U_EXT2) | MR(U_EXT3),
+ MR(UF_D1_EXT) | MR(U_EXT) | MR(UF_EXT2) | MR(UF_EXT3),
- MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(L_EXT2),
+ MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2),
- MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT),
+ MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT) | MR(UF_EXT2) | MR(UF_EXT3),
};
#undef MR
uint32_t mask, v, code, type, len, i, idx;
@@ -1237,6 +1368,135 @@ static int unicode_case1(CharRange *cr, int case_mask)
return 0;
}
+static int point_cmp(const void *p1, const void *p2, void *arg)
+{
+ uint32_t v1 = *(uint32_t *)p1;
+ uint32_t v2 = *(uint32_t *)p2;
+ return (v1 > v2) - (v1 < v2);
+}
+
+static void cr_sort_and_remove_overlap(CharRange *cr)
+{
+ uint32_t start, end, start1, end1, i, j;
+
+ /* the resulting ranges are not necessarily sorted and may overlap */
+ rqsort(cr->points, cr->len / 2, sizeof(cr->points[0]) * 2, point_cmp, NULL);
+ j = 0;
+ for(i = 0; i < cr->len; ) {
+ start = cr->points[i];
+ end = cr->points[i + 1];
+ i += 2;
+ while (i < cr->len) {
+ start1 = cr->points[i];
+ end1 = cr->points[i + 1];
+ if (start1 > end) {
+ /* |------|
+ * |-------| */
+ break;
+ } else if (end1 <= end) {
+ /* |------|
+ * |--| */
+ i += 2;
+ } else {
+ /* |------|
+ * |-------| */
+ end = end1;
+ i += 2;
+ }
+ }
+ cr->points[j] = start;
+ cr->points[j + 1] = end;
+ j += 2;
+ }
+ cr->len = j;
+}
+
+/* canonicalize a character set using the JS regex case folding rules
+ (see lre_canonicalize()) */
+int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode)
+{
+ CharRange cr_inter, cr_mask, cr_result, cr_sub;
+ uint32_t v, code, len, i, idx, start, end, c, d_start, d_end, d;
+
+ cr_init(&cr_mask, cr->mem_opaque, cr->realloc_func);
+ cr_init(&cr_inter, cr->mem_opaque, cr->realloc_func);
+ cr_init(&cr_result, cr->mem_opaque, cr->realloc_func);
+ cr_init(&cr_sub, cr->mem_opaque, cr->realloc_func);
+
+ if (unicode_case1(&cr_mask, is_unicode ? CASE_F : CASE_U))
+ goto fail;
+ if (cr_op(&cr_inter, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER))
+ goto fail;
+
+ if (cr_invert(&cr_mask))
+ goto fail;
+ if (cr_op(&cr_sub, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER))
+ goto fail;
+
+ /* cr_inter = cr & cr_mask */
+ /* cr_sub = cr & ~cr_mask */
+
+ /* use the case conversion table to compute the result */
+ d_start = -1;
+ d_end = -1;
+ idx = 0;
+ v = case_conv_table1[idx];
+ code = v >> (32 - 17);
+ len = (v >> (32 - 17 - 7)) & 0x7f;
+ for(i = 0; i < cr_inter.len; i += 2) {
+ start = cr_inter.points[i];
+ end = cr_inter.points[i + 1];
+
+ for(c = start; c < end; c++) {
+ for(;;) {
+ if (c >= code && c < code + len)
+ break;
+ idx++;
+ assert(idx < countof(case_conv_table1));
+ v = case_conv_table1[idx];
+ code = v >> (32 - 17);
+ len = (v >> (32 - 17 - 7)) & 0x7f;
+ }
+ d = lre_case_folding_entry(c, idx, v, is_unicode);
+ /* try to merge with the current interval */
+ if (d_start == -1) {
+ d_start = d;
+ d_end = d + 1;
+ } else if (d_end == d) {
+ d_end++;
+ } else {
+ cr_add_interval(&cr_result, d_start, d_end);
+ d_start = d;
+ d_end = d + 1;
+ }
+ }
+ }
+ if (d_start != -1) {
+ if (cr_add_interval(&cr_result, d_start, d_end))
+ goto fail;
+ }
+
+ /* the resulting ranges are not necessarily sorted and may overlap */
+ cr_sort_and_remove_overlap(&cr_result);
+
+ /* or with the character not affected by the case folding */
+ cr->len = 0;
+ if (cr_op(cr, cr_result.points, cr_result.len, cr_sub.points, cr_sub.len, CR_OP_UNION))
+ goto fail;
+
+ cr_free(&cr_inter);
+ cr_free(&cr_mask);
+ cr_free(&cr_result);
+ cr_free(&cr_sub);
+ return 0;
+ fail:
+ cr_free(&cr_inter);
+ cr_free(&cr_mask);
+ cr_free(&cr_result);
+ cr_free(&cr_sub);
+ return -1;
+}
+
typedef enum {
POP_GC,
POP_PROP,
@@ -1556,3 +1816,97 @@ int unicode_prop(CharRange *cr, const char *prop_name)
}
#endif /* CONFIG_ALL_UNICODE */
+
+/*---- lre codepoint categorizing functions ----*/
+
+#define S UNICODE_C_SPACE
+#define D UNICODE_C_DIGIT
+#define X UNICODE_C_XDIGIT
+#define U UNICODE_C_UPPER
+#define L UNICODE_C_LOWER
+#define _ UNICODE_C_UNDER
+#define d UNICODE_C_DOLLAR
+
+uint8_t const lre_ctype_bits[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, S, S, S, S, S, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ S, 0, 0, 0, d, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ X|D, X|D, X|D, X|D, X|D, X|D, X|D, X|D,
+ X|D, X|D, 0, 0, 0, 0, 0, 0,
+
+ 0, X|U, X|U, X|U, X|U, X|U, X|U, U,
+ U, U, U, U, U, U, U, U,
+ U, U, U, U, U, U, U, U,
+ U, U, U, 0, 0, 0, 0, _,
+
+ 0, X|L, X|L, X|L, X|L, X|L, X|L, L,
+ L, L, L, L, L, L, L, L,
+ L, L, L, L, L, L, L, L,
+ L, L, L, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ S, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+#undef S
+#undef D
+#undef X
+#undef U
+#undef L
+#undef _
+#undef d
+
+/* code point ranges for Zs,Zl or Zp property */
+static const uint16_t char_range_s[] = {
+ 10,
+ 0x0009, 0x000D + 1,
+ 0x0020, 0x0020 + 1,
+ 0x00A0, 0x00A0 + 1,
+ 0x1680, 0x1680 + 1,
+ 0x2000, 0x200A + 1,
+ /* 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; */
+ /* 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; */
+ 0x2028, 0x2029 + 1,
+ 0x202F, 0x202F + 1,
+ 0x205F, 0x205F + 1,
+ 0x3000, 0x3000 + 1,
+ /* FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; */
+ 0xFEFF, 0xFEFF + 1,
+};
+
+BOOL lre_is_space_non_ascii(uint32_t c)
+{
+ size_t i, n;
+
+ n = countof(char_range_s);
+ for(i = 5; i < n; i += 2) {
+ uint32_t low = char_range_s[i];
+ uint32_t high = char_range_s[i + 1];
+ if (c < low)
+ return FALSE;
+ if (c < high)
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/src/shared/quickjs/libunicode.h b/src/shared/quickjs/libunicode.h
index cfa600a50..cc2f244c7 100644
--- a/src/shared/quickjs/libunicode.h
+++ b/src/shared/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,26 +24,13 @@
#ifndef LIBUNICODE_H
#define LIBUNICODE_H
-#include <inttypes.h>
-
-#define LRE_BOOL int /* for documentation purposes */
+#include <stdint.h>
/* define it to include all the unicode tables (40KB larger) */
#define CONFIG_ALL_UNICODE
#define LRE_CC_RES_LEN_MAX 3
-typedef enum {
- UNICODE_NFC,
- UNICODE_NFD,
- UNICODE_NFKC,
- UNICODE_NFKD,
-} UnicodeNormalizationEnum;
-
-int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
-LRE_BOOL lre_is_cased(uint32_t c);
-LRE_BOOL lre_is_case_ignorable(uint32_t c);
-
/* char ranges */
typedef struct {
@@ -101,10 +88,14 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
int cr_invert(CharRange *cr);
-#ifdef CONFIG_ALL_UNICODE
+int cr_regexp_canonicalize(CharRange *cr, int is_unicode);
-LRE_BOOL lre_is_id_start(uint32_t c);
-LRE_BOOL lre_is_id_continue(uint32_t c);
+typedef enum {
+ UNICODE_NFC,
+ UNICODE_NFD,
+ UNICODE_NFKC,
+ UNICODE_NFKD,
+} UnicodeNormalizationEnum;
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
UnicodeNormalizationEnum n_type,
@@ -112,13 +103,80 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
/* Unicode character range functions */
-int unicode_script(CharRange *cr,
- const char *script_name, LRE_BOOL is_ext);
+int unicode_script(CharRange *cr, const char *script_name, int is_ext);
int unicode_general_category(CharRange *cr, const char *gc_name);
int unicode_prop(CharRange *cr, const char *prop_name);
-#endif /* CONFIG_ALL_UNICODE */
+int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
+int lre_canonicalize(uint32_t c, int is_unicode);
+
+/* Code point type categories */
+enum {
+ UNICODE_C_SPACE = (1 << 0),
+ UNICODE_C_DIGIT = (1 << 1),
+ UNICODE_C_UPPER = (1 << 2),
+ UNICODE_C_LOWER = (1 << 3),
+ UNICODE_C_UNDER = (1 << 4),
+ UNICODE_C_DOLLAR = (1 << 5),
+ UNICODE_C_XDIGIT = (1 << 6),
+};
+extern uint8_t const lre_ctype_bits[256];
+
+/* zero or non-zero return value */
+int lre_is_cased(uint32_t c);
+int lre_is_case_ignorable(uint32_t c);
+int lre_is_id_start(uint32_t c);
+int lre_is_id_continue(uint32_t c);
+
+static inline int lre_is_space_byte(uint8_t c) {
+ return lre_ctype_bits[c] & UNICODE_C_SPACE;
+}
+
+static inline int lre_is_id_start_byte(uint8_t c) {
+ return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
+ UNICODE_C_UNDER | UNICODE_C_DOLLAR);
+}
-#undef LRE_BOOL
+static inline int lre_is_id_continue_byte(uint8_t c) {
+ return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
+ UNICODE_C_UNDER | UNICODE_C_DOLLAR |
+ UNICODE_C_DIGIT);
+}
+
+int lre_is_space_non_ascii(uint32_t c);
+
+static inline int lre_is_space(uint32_t c) {
+ if (c < 256)
+ return lre_is_space_byte(c);
+ else
+ return lre_is_space_non_ascii(c);
+}
+
+static inline int lre_js_is_ident_first(uint32_t c) {
+ if (c < 128) {
+ return lre_is_id_start_byte(c);
+ } else {
+#ifdef CONFIG_ALL_UNICODE
+ return lre_is_id_start(c);
+#else
+ return !lre_is_space_non_ascii(c);
+#endif
+ }
+}
+
+static inline int lre_js_is_ident_next(uint32_t c) {
+ if (c < 128) {
+ return lre_is_id_continue_byte(c);
+ } else {
+ /* ZWNJ and ZWJ are accepted in identifiers */
+ if (c >= 0x200C && c <= 0x200D)
+ return TRUE;
+#ifdef CONFIG_ALL_UNICODE
+ return lre_is_id_continue(c);
+#else
+ return !lre_is_space_non_ascii(c);
+#endif
+ }
+}
#endif /* LIBUNICODE_H */
diff --git a/src/shared/quickjs/list.h b/src/shared/quickjs/list.h
index e7f51a9d9..809831115 100644
--- a/src/shared/quickjs/list.h
+++ b/src/shared/quickjs/list.h
@@ -36,8 +36,7 @@ struct list_head {
#define LIST_HEAD_INIT(el) { &(el), &(el) }
/* return the pointer of type 'type *' containing 'el' as field 'member' */
-#define list_entry(el, type, member) \
- ((type *)((uint8_t *)(el) - offsetof(type, member)))
+#define list_entry(el, type, member) container_of(el, type, member)
static inline void init_list_head(struct list_head *head)
{
@@ -46,8 +45,8 @@ static inline void init_list_head(struct list_head *head)
}
/* insert 'el' between 'prev' and 'next' */
-static inline void list_add_impl(struct list_head *el,
- struct list_head *prev, struct list_head *next)
+static inline void __list_add(struct list_head *el,
+ struct list_head *prev, struct list_head *next)
{
prev->next = el;
el->prev = prev;
@@ -58,13 +57,13 @@ static inline void list_add_impl(struct list_head *el,
/* add 'el' at the head of the list 'head' (= after element head) */
static inline void list_add(struct list_head *el, struct list_head *head)
{
- list_add_impl(el, head, head->next);
+ __list_add(el, head, head->next);
}
/* add 'el' at the end of the list 'head' (= before element head) */
static inline void list_add_tail(struct list_head *el, struct list_head *head)
{
- list_add_impl(el, head->prev, head);
+ __list_add(el, head->prev, head);
}
static inline void list_del(struct list_head *el)
diff --git a/src/shared/quickjs/quickjs-atom.h b/src/shared/quickjs/quickjs-atom.h
index 4c2279452..f4d5838d4 100644
--- a/src/shared/quickjs/quickjs-atom.h
+++ b/src/shared/quickjs/quickjs-atom.h
@@ -1,6 +1,6 @@
/*
* QuickJS atom definitions
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
@@ -82,6 +82,7 @@ DEF(length, "length")
DEF(fileName, "fileName")
DEF(lineNumber, "lineNumber")
DEF(message, "message")
+DEF(cause, "cause")
DEF(errors, "errors")
DEF(stack, "stack")
DEF(name, "name")
@@ -166,22 +167,23 @@ DEF(revoke, "revoke")
DEF(async, "async")
DEF(exec, "exec")
DEF(groups, "groups")
+DEF(indices, "indices")
DEF(status, "status")
DEF(reason, "reason")
DEF(globalThis, "globalThis")
-#ifdef CONFIG_BIGNUM
DEF(bigint, "bigint")
+#ifdef CONFIG_BIGNUM
DEF(bigfloat, "bigfloat")
DEF(bigdecimal, "bigdecimal")
DEF(roundingMode, "roundingMode")
DEF(maximumSignificantDigits, "maximumSignificantDigits")
DEF(maximumFractionDigits, "maximumFractionDigits")
#endif
-#ifdef CONFIG_ATOMICS
+/* the following 3 atoms are only used with CONFIG_ATOMICS */
DEF(not_equal, "not-equal")
DEF(timed_out, "timed-out")
DEF(ok, "ok")
-#endif
+/* */
DEF(toJSON, "toJSON")
/* class names */
DEF(Object, "Object")
@@ -202,22 +204,20 @@ DEF(RegExp, "RegExp")
DEF(ArrayBuffer, "ArrayBuffer")
DEF(SharedArrayBuffer, "SharedArrayBuffer")
/* must keep same order as class IDs for typed arrays */
-DEF(Uint8ClampedArray, "Uint8ClampedArray")
+DEF(Uint8ClampedArray, "Uint8ClampedArray")
DEF(Int8Array, "Int8Array")
DEF(Uint8Array, "Uint8Array")
DEF(Int16Array, "Int16Array")
DEF(Uint16Array, "Uint16Array")
DEF(Int32Array, "Int32Array")
DEF(Uint32Array, "Uint32Array")
-#ifdef CONFIG_BIGNUM
DEF(BigInt64Array, "BigInt64Array")
DEF(BigUint64Array, "BigUint64Array")
-#endif
DEF(Float32Array, "Float32Array")
DEF(Float64Array, "Float64Array")
DEF(DataView, "DataView")
-#ifdef CONFIG_BIGNUM
DEF(BigInt, "BigInt")
+#ifdef CONFIG_BIGNUM
DEF(BigFloat, "BigFloat")
DEF(BigFloatEnv, "BigFloatEnv")
DEF(BigDecimal, "BigDecimal")
@@ -269,5 +269,5 @@ DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
#ifdef CONFIG_BIGNUM
DEF(Symbol_operatorSet, "Symbol.operatorSet")
#endif
-
+
#endif /* DEF */
diff --git a/src/shared/quickjs/quickjs-opcode.h b/src/shared/quickjs/quickjs-opcode.h
index c731a14a9..1e1821259 100644
--- a/src/shared/quickjs/quickjs-opcode.h
+++ b/src/shared/quickjs/quickjs-opcode.h
@@ -1,6 +1,6 @@
/*
* QuickJS opcode definitions
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
@@ -165,14 +165,15 @@ DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
DEF( get_arg, 3, 0, 1, arg)
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
-DEF( get_var_ref, 3, 0, 1, var_ref)
+DEF( get_var_ref, 3, 0, 1, var_ref)
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
DEF(set_loc_uninitialized, 3, 0, 0, loc)
DEF( get_loc_check, 3, 0, 1, loc)
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
DEF( put_loc_check_init, 3, 1, 0, loc)
-DEF(get_var_ref_check, 3, 0, 1, var_ref)
+DEF(get_loc_checkthis, 3, 0, 1, loc)
+DEF(get_var_ref_check, 3, 0, 1, var_ref)
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
DEF( close_loc, 3, 0, 0, loc)
@@ -182,6 +183,7 @@ DEF( goto, 5, 0, 0, label) /* must come after if_true */
DEF( catch, 5, 0, 1, label)
DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */
DEF( ret, 1, 1, 0, none) /* used to return from the finally block */
+DEF( nip_catch, 1, 2, 1, none) /* catch ... a -> a */
DEF( to_object, 1, 1, 1, none)
//DEF( to_string, 1, 1, 1, none)
@@ -208,7 +210,6 @@ DEF( for_of_next, 2, 3, 5, u8)
DEF(iterator_check_object, 1, 1, 1, none)
DEF(iterator_get_value_done, 1, 1, 2, none)
DEF( iterator_close, 1, 3, 0, none)
-DEF(iterator_close_return, 1, 4, 4, none)
DEF( iterator_next, 1, 4, 4, none)
DEF( iterator_call, 2, 4, 5, u8)
DEF( initial_yield, 1, 0, 0, none)
@@ -256,12 +257,13 @@ DEF( and, 1, 2, 1, none)
DEF( xor, 1, 2, 1, none)
DEF( or, 1, 2, 1, none)
DEF(is_undefined_or_null, 1, 1, 1, none)
+DEF( private_in, 1, 2, 1, none)
#ifdef CONFIG_BIGNUM
DEF( mul_pow10, 1, 2, 1, none)
DEF( math_mod, 1, 2, 1, none)
#endif
/* must be the last non short and non temporary opcode */
-DEF( nop, 1, 0, 0, none)
+DEF( nop, 1, 0, 0, none)
/* temporary opcodes: never emitted in the final bytecode */
@@ -270,6 +272,8 @@ def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
+/* the following opcodes must be in the same order as the 'with_x' and
+ get_var_undef, get_var and put_var opcodes */
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
@@ -277,12 +281,15 @@ def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
+def(scope_get_var_checkthis, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2, only used to return 'this' in derived class constructors */
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
-def(scope_put_private_field, 7, 1, 1, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
-
+def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
+def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1, removed in phase 2 */
+def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */
+def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
-
+
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
#if SHORT_OPCODES
diff --git a/src/shared/quickjs/quickjs.c b/src/shared/quickjs/quickjs.c
index 1e3b97d51..3bafe6948 100644
--- a/src/shared/quickjs/quickjs.c
+++ b/src/shared/quickjs/quickjs.c
@@ -58,9 +58,8 @@
#include "list.h"
#include "quickjs.h"
#include "libregexp.h"
-#ifdef CONFIG_BIGNUM
+#include "libunicode.h"
#include "libbf.h"
-#endif
#define OPTIMIZE 0
#define SHORT_OPCODES 1
@@ -102,6 +101,7 @@
8: dump stdlib functions
16: dump bytecode in hex
32: dump line number table
+ 64: dump compute_stack_size
*/
//#define DUMP_BYTECODE (1)
/* dump the occurence of the automatic GC */
@@ -176,15 +176,13 @@ enum {
JS_CLASS_UINT16_ARRAY, /* u.array (typed_array) */
JS_CLASS_INT32_ARRAY, /* u.array (typed_array) */
JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */
-#ifdef CONFIG_BIGNUM
JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */
JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */
-#endif
JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */
JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */
JS_CLASS_DATAVIEW, /* u.typed_array */
-#ifdef CONFIG_BIGNUM
JS_CLASS_BIG_INT, /* u.object_data */
+#ifdef CONFIG_BIGNUM
JS_CLASS_BIG_FLOAT, /* u.object_data */
JS_CLASS_FLOAT_ENV, /* u.float_env */
JS_CLASS_BIG_DECIMAL, /* u.object_data */
@@ -232,14 +230,14 @@ typedef enum JSErrorEnum {
JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */
} JSErrorEnum;
-#define JS_MAX_LOCAL_VARS 65536
+#define JS_MAX_LOCAL_VARS 65535
#define JS_STACK_SIZE_MAX 65534
#define JS_STRING_LEN_MAX ((1 << 30) - 1)
#ifdef __GNUC__
-#define warn_unused __attribute__((warn_unused_result))
+#define __exception __attribute__((warn_unused_result))
#else
-#define warn_unused
+#define __exception
#endif
typedef struct JSShape JSShape;
@@ -254,7 +252,6 @@ typedef enum {
typedef enum OPCodeEnum OPCodeEnum;
-#ifdef CONFIG_BIGNUM
/* function pointers are used for numeric operations so that it is
possible to remove some numeric types */
typedef struct {
@@ -272,7 +269,6 @@ typedef struct {
int64_t exponent);
int (*mul_pow10)(JSContext *ctx, JSValue *sp);
} JSNumericOperations;
-#endif
struct JSRuntime {
JSMallocFunctions mf;
@@ -324,6 +320,8 @@ struct JSRuntime {
JSModuleNormalizeFunc *module_normalize_func;
JSModuleLoaderFunc *module_loader_func;
void *module_loader_opaque;
+ /* timestamp for internal use in module evaluation */
+ int64_t module_async_evaluation_next_timestamp;
BOOL can_block : 8; /* TRUE if Atomics.wait can block */
/* used to allocate, free and clone SharedArrayBuffers */
@@ -334,9 +332,9 @@ struct JSRuntime {
int shape_hash_size;
int shape_hash_count; /* number of hashed shapes */
JSShape **shape_hash;
-#ifdef CONFIG_BIGNUM
bf_context_t bf_ctx;
JSNumericOperations bigint_ops;
+#ifdef CONFIG_BIGNUM
JSNumericOperations bigfloat_ops;
JSNumericOperations bigdecimal_ops;
uint32_t operator_count;
@@ -357,17 +355,18 @@ struct JSClass {
#define JS_MODE_STRICT (1 << 0)
#define JS_MODE_STRIP (1 << 1)
#define JS_MODE_MATH (1 << 2)
+#define JS_MODE_ASYNC (1 << 3) /* async function */
typedef struct JSStackFrame {
struct JSStackFrame *prev_frame; /* NULL if first stack frame */
JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */
JSValue *arg_buf; /* arguments */
JSValue *var_buf; /* variables */
- struct list_head var_ref_list; /* list of JSVarRef.link */
+ struct list_head var_ref_list; /* list of JSVarRef.var_ref_link */
const uint8_t *cur_pc; /* only used in bytecode functions : PC of the
instruction after the call */
int arg_count;
- int js_mode; /* 0 or JS_MODE_MATH for C functions */
+ int js_mode; /* for C functions, only JS_MODE_MATH may be set */
/* only used in generators. Current stack pointer value. NULL if
the function is running. */
JSValue *cur_sp;
@@ -398,13 +397,8 @@ typedef struct JSVarRef {
union {
JSGCObjectHeader header; /* must come first */
struct {
- int _gc_ref_count; /* corresponds to header.ref_count */
- uint8_t _gc_mark; /* corresponds to header.mark/gc_obj_type */
-
- /* 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
- */
+ int __gc_ref_count; /* corresponds to header.ref_count */
+ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
uint8_t is_detached : 1;
uint8_t is_arg : 1;
uint16_t var_idx; /* index of the corresponding function variable on
@@ -413,16 +407,15 @@ typedef struct JSVarRef {
};
JSValue *pvalue; /* pointer to the value, either on the stack or
to 'value' */
- JSValue value; /* used when the variable is no longer on the stack */
+ union {
+ JSValue value; /* used when is_detached = TRUE */
+ struct {
+ struct list_head var_ref_link; /* JSStackFrame.var_ref_list list */
+ struct JSAsyncFunctionState *async_func; /* != NULL if async stack frame */
+ }; /* used when is_detached = FALSE */
+ };
} JSVarRef;
-#ifdef CONFIG_BIGNUM
-typedef struct JSFloatEnv {
- limb_t prec;
- bf_flags_t flags;
- unsigned int status;
-} JSFloatEnv;
-
/* the same structure is used for big integers and big floats. Big
integers are never infinite or NaNs */
typedef struct JSBigFloat {
@@ -430,6 +423,13 @@ typedef struct JSBigFloat {
bf_t num;
} JSBigFloat;
+#ifdef CONFIG_BIGNUM
+typedef struct JSFloatEnv {
+ limb_t prec;
+ bf_flags_t flags;
+ unsigned int status;
+} JSFloatEnv;
+
typedef struct JSBigDecimal {
JSRefCountHeader header; /* must come first, 32-bit */
bfdec_t num;
@@ -473,15 +473,14 @@ struct JSContext {
JSValue global_var_obj; /* contains the global let/const definitions */
uint64_t random_state;
-#ifdef CONFIG_BIGNUM
bf_context_t *bf_ctx; /* points to rt->bf_ctx, shared by all contexts */
+#ifdef CONFIG_BIGNUM
JSFloatEnv fp_env; /* global FP environment */
BOOL bignum_ext : 8; /* enable math mode */
BOOL allow_operator_overloading : 8;
#endif
/* when the counter reaches zero, JSRutime.interrupt_handler is called */
int interrupt_counter;
- BOOL is_error_property_enabled;
struct list_head loaded_modules; /* list of JSModuleDef.link */
@@ -598,6 +597,7 @@ typedef struct JSVarDef {
uint8_t is_const : 1;
uint8_t is_lexical : 1;
uint8_t is_captured : 1;
+ uint8_t is_static_private : 1; /* only used during private class field parsing */
uint8_t var_kind : 4; /* see JSVarKindEnum */
/* only used during compilation: function pool index for lexical
variables with var_kind =
@@ -638,7 +638,8 @@ typedef struct JSFunctionBytecode {
uint8_t has_debug : 1;
uint8_t backtrace_barrier : 1; /* stop backtrace on this function */
uint8_t read_only_bytecode : 1;
- /* XXX: 4 bits available */
+ uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
+ /* XXX: 10 bits available */
uint8_t *byte_code_buf; /* (self pointer) */
int byte_code_len;
JSAtom func_name;
@@ -678,9 +679,11 @@ typedef enum JSIteratorKindEnum {
typedef struct JSForInIterator {
JSValue obj;
- BOOL is_array;
- uint32_t array_length;
uint32_t idx;
+ uint32_t atom_count;
+ uint8_t in_prototype_chain;
+ uint8_t is_array;
+ JSPropertyEnum *tab_atom; /* is_array = FALSE */
} JSForInIterator;
typedef struct JSRegExp {
@@ -714,21 +717,16 @@ typedef struct JSTypedArray {
} JSTypedArray;
typedef struct JSAsyncFunctionState {
- JSValue this_val; /* 'this' generator argument */
+ JSGCObjectHeader header;
+ JSValue this_val; /* 'this' argument */
int argc; /* number of function arguments */
BOOL throw_flag; /* used to throw an exception in JS_CallInternal() */
+ BOOL is_completed; /* TRUE if the function has returned. The stack
+ frame is no longer valid */
+ JSValue resolving_funcs[2]; /* only used in JS async functions */
JSStackFrame frame;
} JSAsyncFunctionState;
-/* XXX: could use an object instead to avoid the
- JS_TAG_ASYNC_FUNCTION tag for the GC */
-typedef struct JSAsyncFunctionData {
- JSGCObjectHeader header; /* must come first */
- JSValue resolving_funcs[2];
- BOOL is_active; /* true if the async function state is valid */
- JSAsyncFunctionState func_state;
-} JSAsyncFunctionData;
-
typedef enum {
/* binary operators */
JS_OVOP_ADD,
@@ -810,6 +808,15 @@ typedef struct JSImportEntry {
int req_module_idx; /* in req_module_entries */
} JSImportEntry;
+typedef enum {
+ JS_MODULE_STATUS_UNLINKED,
+ JS_MODULE_STATUS_LINKING,
+ JS_MODULE_STATUS_LINKED,
+ JS_MODULE_STATUS_EVALUATING,
+ JS_MODULE_STATUS_EVALUATING_ASYNC,
+ JS_MODULE_STATUS_EVALUATED,
+} JSModuleStatus;
+
struct JSModuleDef {
JSRefCountHeader header; /* must come first, 32-bit */
JSAtom module_name;
@@ -834,11 +841,24 @@ struct JSModuleDef {
JSValue module_ns;
JSValue func_obj; /* only used for JS modules */
JSModuleInitFunc *init_func; /* only used for C modules */
+ BOOL has_tla : 8; /* true if func_obj contains await */
BOOL resolved : 8;
BOOL func_created : 8;
- BOOL instantiated : 8;
- BOOL evaluated : 8;
- BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */
+ JSModuleStatus status : 8;
+ /* temp use during js_module_link() & js_module_evaluate() */
+ int dfs_index, dfs_ancestor_index;
+ JSModuleDef *stack_prev;
+ /* temp use during js_module_evaluate() */
+ JSModuleDef **async_parent_modules;
+ int async_parent_modules_count;
+ int async_parent_modules_size;
+ int pending_async_dependencies;
+ BOOL async_evaluation;
+ int64_t async_evaluation_timestamp;
+ JSModuleDef *cycle_root;
+ JSValue promise; /* corresponds to spec field: capability */
+ JSValue resolving_funcs[2]; /* corresponds to spec field: capability */
+
/* true if evaluation yielded an exception. It is saved in
eval_exception */
BOOL eval_has_exception : 8;
@@ -907,8 +927,8 @@ struct JSObject {
union {
JSGCObjectHeader header;
struct {
- int _gc_ref_count; /* corresponds to header.ref_count */
- uint8_t _gc_mark; /* corresponds to header.mark/gc_obj_type */
+ 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 */
@@ -946,7 +966,7 @@ struct JSObject {
struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */
struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */
struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */
- struct JSAsyncFunctionData *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */
+ struct JSAsyncFunctionState *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */
struct JSAsyncFromSyncIteratorData *async_from_sync_iterator_data; /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */
struct JSAsyncGeneratorData *async_generator_data; /* JS_CLASS_ASYNC_GENERATOR */
struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */
@@ -989,8 +1009,9 @@ struct JSObject {
} u;
/* byte sizes: 40/48/72 */
};
+
enum {
- JS_ATOM_NULL_ = JS_ATOM_NULL,
+ __JS_ATOM_NULL = JS_ATOM_NULL,
#define DEF(name, str) JS_ATOM_ ## name,
#include "quickjs-atom.h"
#undef DEF
@@ -1036,8 +1057,8 @@ enum OPCodeEnum {
};
static int JS_InitAtoms(JSRuntime *rt);
-static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
- int atom_type);
+static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
+ int atom_type);
static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);
static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);
static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
@@ -1057,34 +1078,29 @@ static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_o
int argc, JSValueConst *argv);
static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
int argc, JSValueConst *argv);
-static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
+static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
JSValue val, BOOL is_array_ctor);
static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
JSValueConst val, int flags, int scope_idx);
-static maybe_unused void JS_DumpAtoms(JSRuntime *rt);
-static maybe_unused void JS_DumpString(JSRuntime *rt,
- const JSString *p);
-static maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
-static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
-static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
-static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
- JSValueConst val);
-static maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
-static maybe_unused void JS_PrintValue(JSContext *ctx,
+static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
+static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p);
+static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
+static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
+static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
+static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val);
+static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
+static __maybe_unused void JS_PrintValue(JSContext *ctx,
const char *str,
JSValueConst val);
-static maybe_unused void JS_DumpShapes(JSRuntime *rt);
+static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int magic);
static void js_array_finalizer(JSRuntime *rt, JSValue val);
-static void js_array_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
+static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_object_data_finalizer(JSRuntime *rt, JSValue val);
-static void js_object_data_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
+static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_c_function_finalizer(JSRuntime *rt, JSValue val);
-static void js_c_function_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
+static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val);
static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
JS_MarkFunc *mark_func);
@@ -1128,6 +1144,12 @@ static void js_operator_set_finalizer(JSRuntime *rt, JSValue val);
static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,
JS_MarkFunc *mark_func);
#endif
+
+#define HINT_STRING 0
+#define HINT_NUMBER 1
+#define HINT_NONE 2
+#define HINT_FORCE_ORDINARY (1 << 4) // don't try Symbol.toPrimitive
+static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint);
static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);
static int JS_ToBoolFree(JSContext *ctx, JSValue val);
static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);
@@ -1149,13 +1171,25 @@ typedef enum JSStrictEqModeEnum {
static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
JSStrictEqModeEnum eq_mode);
-static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2);
+static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2);
static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
static JSValue JS_ToObject(JSContext *ctx, JSValueConst val);
static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val);
static JSProperty *add_property(JSContext *ctx,
JSObject *p, JSAtom prop, int prop_flags);
+static JSValue JS_NewBigInt(JSContext *ctx);
+static inline bf_t *JS_GetBigInt(JSValueConst val)
+{
+ JSBigFloat *p = JS_VALUE_GET_PTR(val);
+ return &p->num;
+}
+static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
+ BOOL convert_to_safe_integer);
+static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);
+static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);
+static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);
+static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf);
#ifdef CONFIG_BIGNUM
static void js_float_env_finalizer(JSRuntime *rt, JSValue val);
static JSValue JS_NewBigFloat(JSContext *ctx);
@@ -1170,18 +1204,6 @@ static inline bfdec_t *JS_GetBigDecimal(JSValueConst val)
JSBigDecimal *p = JS_VALUE_GET_PTR(val);
return &p->num;
}
-static JSValue JS_NewBigInt(JSContext *ctx);
-static inline bf_t *JS_GetBigInt(JSValueConst val)
-{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- return &p->num;
-}
-static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
- BOOL convert_to_safe_integer);
-static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);
-static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);
-static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);
-static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf);
static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val);
static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,
BOOL allow_null_or_undefined);
@@ -1191,9 +1213,10 @@ static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);
static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);
static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
JSValueConst proto_val, BOOL throw_flag);
+
+static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, int throw_exception);
static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);
static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj);
-static int js_proxy_isArray(JSContext *ctx, JSValueConst obj);
static int JS_CreateProperty(JSContext *ctx, JSObject *p,
JSAtom prop, JSValueConst val,
JSValueConst getter, JSValueConst setter,
@@ -1211,11 +1234,17 @@ static JSValue js_typed_array_constructor(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv,
int classid);
+static JSValue js_typed_array_constructor_ta(JSContext *ctx,
+ JSValueConst new_target,
+ JSValueConst src_obj,
+ int classid);
static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p);
static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p);
static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx);
static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx,
BOOL is_arg);
+static void __async_func_free(JSRuntime *rt, JSAsyncFunctionState *s);
+static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s);
static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
JSValueConst this_obj,
int argc, JSValueConst *argv,
@@ -1235,12 +1264,14 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);
static JSValue js_new_promise_capability(JSContext *ctx,
JSValue *resolving_funcs,
JSValueConst ctor);
-static warn_unused int perform_promise_then(JSContext *ctx,
+static __exception int perform_promise_then(JSContext *ctx,
JSValueConst promise,
JSValueConst *resolve_reject,
JSValueConst *cap_resolving_funcs);
static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int magic);
+static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
static int js_string_compare(JSContext *ctx,
const JSString *p1, const JSString *p2);
static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val);
@@ -1252,17 +1283,15 @@ static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val);
static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc,
JSObject *p, JSAtom prop);
static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc);
-static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,
- JS_MarkFunc *mark_func);
static void JS_AddIntrinsicBasicObjects(JSContext *ctx);
static void js_free_shape(JSRuntime *rt, JSShape *sh);
static void js_free_shape_null(JSRuntime *rt, JSShape *sh);
static int js_shape_prepare_update(JSContext *ctx, JSObject *p,
JSShapeProperty **pprs);
static int init_shape_hash(JSRuntime *rt);
-static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
+static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
JSValueConst obj);
-static warn_unused int js_get_length64(JSContext *ctx, int64_t *pres,
+static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
JSValueConst obj);
static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len);
static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
@@ -1281,13 +1310,13 @@ static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);
static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,
JSGCObjectTypeEnum type);
static void remove_gc_object(JSGCObjectHeader *h);
-static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s);
static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
void *opaque);
static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p,
JSAtom atom, void *opaque);
-void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag);
+static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int is_map);
static const JSClassExoticMethods js_arguments_exotic_methods;
static const JSClassExoticMethods js_string_exotic_methods;
@@ -1349,14 +1378,12 @@ void *js_mallocz_rt(JSRuntime *rt, size_t size)
return memset(ptr, 0, size);
}
-#ifdef CONFIG_BIGNUM
/* called by libbf */
static void *js_bf_realloc(void *opaque, void *ptr, size_t size)
{
JSRuntime *rt = opaque;
return js_realloc_rt(rt, ptr, size);
}
-#endif /* CONFIG_BIGNUM */
/* Throw out of memory in case of error */
void *js_malloc(JSContext *ctx, size_t size)
@@ -1473,6 +1500,10 @@ static inline int is_digit(int c) {
return c >= '0' && c <= '9';
}
+static inline int string_get(const JSString *p, int idx) {
+ return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx];
+}
+
typedef struct JSClassShortDef {
JSAtom class_name;
JSClassFinalizer *finalizer;
@@ -1507,15 +1538,13 @@ static JSClassShortDef const js_std_class_def[] = {
{ JS_ATOM_Uint16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT16_ARRAY */
{ JS_ATOM_Int32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_INT32_ARRAY */
{ JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT32_ARRAY */
-#ifdef CONFIG_BIGNUM
{ JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_INT64_ARRAY */
{ JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_UINT64_ARRAY */
-#endif
{ JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT32_ARRAY */
{ JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT64_ARRAY */
{ JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_DATAVIEW */
-#ifdef CONFIG_BIGNUM
{ JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_INT */
+#ifdef CONFIG_BIGNUM
{ JS_ATOM_BigFloat, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_FLOAT */
{ JS_ATOM_BigFloatEnv, js_float_env_finalizer, NULL }, /* JS_CLASS_FLOAT_ENV */
{ JS_ATOM_BigDecimal, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_DECIMAL */
@@ -1550,7 +1579,6 @@ static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab,
return 0;
}
-#ifdef CONFIG_BIGNUM
static JSValue JS_ThrowUnsupportedOperation(JSContext *ctx)
{
return JS_ThrowTypeError(ctx, "unsupported operation");
@@ -1606,8 +1634,6 @@ static void set_dummy_numeric_ops(JSNumericOperations *ops)
ops->mul_pow10 = invalid_mul_pow10;
}
-#endif /* CONFIG_BIGNUM */
-
#if !defined(CONFIG_STACK_CHECK)
/* no stack limitation */
static inline uintptr_t js_get_stack_pointer(void)
@@ -1672,9 +1698,9 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
rt->malloc_state = ms;
rt->malloc_gc_threshold = 256 * 1024;
-#ifdef CONFIG_BIGNUM
bf_context_init(&rt->bf_ctx, js_bf_realloc, rt);
set_dummy_numeric_ops(&rt->bigint_ops);
+#ifdef CONFIG_BIGNUM
set_dummy_numeric_ops(&rt->bigfloat_ops);
set_dummy_numeric_ops(&rt->bigdecimal_ops);
#endif
@@ -1729,19 +1755,19 @@ void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque)
}
/* default memory allocation functions with memory limitation */
-static inline size_t js_def_malloc_usable_size(void *ptr)
+static size_t js_def_malloc_usable_size(const void *ptr)
{
#if defined(__APPLE__)
return malloc_size(ptr);
#elif defined(_WIN32)
- return _msize(ptr);
+ return _msize((void *)ptr);
#elif defined(EMSCRIPTEN)
return 0;
#elif defined(__linux__)
- return malloc_usable_size(ptr);
+ return malloc_usable_size((void *)ptr);
#else
/* change this to `return 0;` if compilation fails */
- return malloc_usable_size(ptr);
+ return malloc_usable_size((void *)ptr);
#endif
}
@@ -1805,18 +1831,7 @@ static const JSMallocFunctions def_malloc_funcs = {
js_def_malloc,
js_def_free,
js_def_realloc,
-#if defined(__APPLE__)
- malloc_size,
-#elif defined(_WIN32)
- (size_t (*)(const void *))_msize,
-#elif defined(EMSCRIPTEN)
- NULL,
-#elif defined(__linux__)
- (size_t (*)(const void *))malloc_usable_size,
-#else
- /* change this to `NULL,` if compilation fails */
- malloc_usable_size,
-#endif
+ js_def_malloc_usable_size,
};
JSRuntime *JS_NewRuntime(void)
@@ -2047,9 +2062,7 @@ void JS_FreeRuntime(JSRuntime *rt)
}
js_free_rt(rt, rt->class_array);
-#ifdef CONFIG_BIGNUM
bf_context_end(&rt->bf_ctx);
-#endif
#ifdef DUMP_LEAKS
/* only the atoms defined in JS_InitAtoms() should be left */
@@ -2187,8 +2200,8 @@ JSContext *JS_NewContextRaw(JSRuntime *rt)
}
ctx->rt = rt;
list_add_tail(&ctx->link, &rt->context_list);
-#ifdef CONFIG_BIGNUM
ctx->bf_ctx = &rt->bf_ctx;
+#ifdef CONFIG_BIGNUM
ctx->fp_env.prec = 113;
ctx->fp_env.flags = bf_set_exp_bits(15) | BF_RNDN | BF_FLAG_SUBNORMAL;
#endif
@@ -2221,9 +2234,7 @@ JSContext *JS_NewContext(JSRuntime *rt)
JS_AddIntrinsicMapSet(ctx);
JS_AddIntrinsicTypedArrays(ctx);
JS_AddIntrinsicPromise(ctx);
-#ifdef CONFIG_BIGNUM
JS_AddIntrinsicBigInt(ctx);
-#endif
return ctx;
}
@@ -2264,7 +2275,6 @@ JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id)
typedef enum JSFreeModuleEnum {
JS_FREE_MODULE_ALL,
JS_FREE_MODULE_NOT_RESOLVED,
- JS_FREE_MODULE_NOT_EVALUATED,
} JSFreeModuleEnum;
/* XXX: would be more efficient with separate module lists */
@@ -2274,8 +2284,7 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag)
list_for_each_safe(el, el1, &ctx->loaded_modules) {
JSModuleDef *m = list_entry(el, JSModuleDef, link);
if (flag == JS_FREE_MODULE_ALL ||
- (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved) ||
- (flag == JS_FREE_MODULE_NOT_EVALUATED && !m->evaluated)) {
+ (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved)) {
js_free_module_def(ctx, m);
}
}
@@ -2431,6 +2440,11 @@ static inline BOOL is_math_mode(JSContext *ctx)
JSStackFrame *sf = ctx->rt->current_stack_frame;
return (sf && (sf->js_mode & JS_MODE_MATH));
}
+#else
+static inline BOOL is_math_mode(JSContext *ctx)
+{
+ return FALSE;
+}
#endif
/* JSAtom support */
@@ -2442,7 +2456,7 @@ static inline BOOL is_math_mode(JSContext *ctx)
/* return the max count from the hash size */
#define JS_ATOM_COUNT_RESIZE(n) ((n) * 2)
-static inline BOOL JS_AtomIsConst(JSAtom v)
+static inline BOOL __JS_AtomIsConst(JSAtom v)
{
#if defined(DUMP_LEAKS) && DUMP_LEAKS > 1
return (int32_t)v <= 0;
@@ -2451,17 +2465,17 @@ static inline BOOL JS_AtomIsConst(JSAtom v)
#endif
}
-static inline BOOL JS_AtomIsTaggedInt(JSAtom v)
+static inline BOOL __JS_AtomIsTaggedInt(JSAtom v)
{
return (v & JS_ATOM_TAG_INT) != 0;
}
-static inline JSAtom JS_AtomFromUInt32(uint32_t v)
+static inline JSAtom __JS_AtomFromUInt32(uint32_t v)
{
return v | JS_ATOM_TAG_INT;
}
-static inline uint32_t JS_AtomToUInt32(JSAtom atom)
+static inline uint32_t __JS_AtomToUInt32(JSAtom atom)
{
return atom & ~JS_ATOM_TAG_INT;
}
@@ -2481,10 +2495,7 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p)
len = p->len;
if (len == 0 || len > 10)
return FALSE;
- if (p->is_wide_char)
- c = p->u.str16[0];
- else
- c = p->u.str8[0];
+ c = string_get(p, 0);
if (is_num(c)) {
if (c == '0') {
if (len != 1)
@@ -2493,10 +2504,7 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p)
} else {
n = c - '0';
for(i = 1; i < len; i++) {
- if (p->is_wide_char)
- c = p->u.str16[i];
- else
- c = p->u.str8[i];
+ c = string_get(p, i);
if (!is_num(c))
return FALSE;
n64 = (uint64_t)n * 10 + (c - '0');
@@ -2541,10 +2549,24 @@ static uint32_t hash_string(const JSString *str, uint32_t h)
return h;
}
-static maybe_unused void JS_DumpString(JSRuntime *rt,
- const JSString *p)
+static __maybe_unused void JS_DumpChar(JSRuntime *rt, int c, int sep)
+{
+ if (c == sep || c == '\\') {
+ putchar('\\');
+ putchar(c);
+ } else if (c >= ' ' && c <= 126) {
+ putchar(c);
+ } else if (c == '\n') {
+ putchar('\\');
+ putchar('n');
+ } else {
+ printf("\\u%04x", c);
+ }
+}
+
+static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p)
{
- int i, c, sep;
+ int i, sep;
if (p == NULL) {
printf("<null>");
@@ -2554,26 +2576,12 @@ static maybe_unused void JS_DumpString(JSRuntime *rt,
sep = (p->header.ref_count == 1) ? '\"' : '\'';
putchar(sep);
for(i = 0; i < p->len; i++) {
- if (p->is_wide_char)
- c = p->u.str16[i];
- else
- c = p->u.str8[i];
- if (c == sep || c == '\\') {
- putchar('\\');
- putchar(c);
- } else if (c >= ' ' && c <= 126) {
- putchar(c);
- } else if (c == '\n') {
- putchar('\\');
- putchar('n');
- } else {
- printf("\\u%04x", c);
- }
+ JS_DumpChar(rt, string_get(p, i), sep);
}
putchar(sep);
}
-static maybe_unused void JS_DumpAtoms(JSRuntime *rt)
+static __maybe_unused void JS_DumpAtoms(JSRuntime *rt)
{
JSAtomStruct *p;
int h, i;
@@ -2660,7 +2668,7 @@ static int JS_InitAtoms(JSRuntime *rt)
else
atom_type = JS_ATOM_TYPE_STRING;
len = strlen(p);
- if (JS_NewAtomInitImpl(rt, p, len, atom_type) == JS_ATOM_NULL)
+ if (__JS_NewAtomInit(rt, p, len, atom_type) == JS_ATOM_NULL)
return -1;
p = p + len + 1;
}
@@ -2671,7 +2679,7 @@ static JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v)
{
JSAtomStruct *p;
- if (!JS_AtomIsConst(v)) {
+ if (!__JS_AtomIsConst(v)) {
p = rt->atom_array[v];
p->header.ref_count++;
}
@@ -2683,7 +2691,7 @@ JSAtom JS_DupAtom(JSContext *ctx, JSAtom v)
JSRuntime *rt;
JSAtomStruct *p;
- if (!JS_AtomIsConst(v)) {
+ if (!__JS_AtomIsConst(v)) {
rt = ctx->rt;
p = rt->atom_array[v];
p->header.ref_count++;
@@ -2697,7 +2705,7 @@ static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v)
JSAtomStruct *p;
rt = ctx->rt;
- if (JS_AtomIsTaggedInt(v))
+ if (__JS_AtomIsTaggedInt(v))
return JS_ATOM_KIND_STRING;
p = rt->atom_array[v];
switch(p->atom_type) {
@@ -2743,7 +2751,7 @@ static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p)
/* string case (internal). Return JS_ATOM_NULL if error. 'str' is
freed. */
-static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
+static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
{
uint32_t h, h1, i;
JSAtomStruct *p;
@@ -2758,7 +2766,7 @@ static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
/* str is the atom, return its index */
i = js_get_atom_index(rt, str);
/* reduce string refcount and increase atom's unless constant */
- if (JS_AtomIsConst(i))
+ if (__JS_AtomIsConst(i))
str->header.ref_count--;
return i;
}
@@ -2774,7 +2782,7 @@ static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
p->atom_type == atom_type &&
p->len == len &&
js_string_memcmp(p, str, len) == 0) {
- if (!JS_AtomIsConst(i))
+ if (!__JS_AtomIsConst(i))
p->header.ref_count++;
goto done;
}
@@ -2899,8 +2907,8 @@ static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
}
/* only works with zero terminated 8 bit strings */
-static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
- int atom_type)
+static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
+ int atom_type)
{
JSString *p;
p = js_alloc_string_rt(rt, len, 0);
@@ -2908,10 +2916,11 @@ static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
return JS_ATOM_NULL;
memcpy(p->u.str8, str, len);
p->u.str8[len] = '\0';
- return JS_NewAtomImpl(rt, p, atom_type);
+ return __JS_NewAtom(rt, p, atom_type);
}
-static JSAtom JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
+/* Warning: str must be ASCII only */
+static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
int atom_type)
{
uint32_t h, h1, i;
@@ -2928,7 +2937,7 @@ static JSAtom JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
p->len == len &&
p->is_wide_char == 0 &&
memcmp(p->u.str8, str, len) == 0) {
- if (!JS_AtomIsConst(i))
+ if (!__JS_AtomIsConst(i))
p->header.ref_count++;
return i;
}
@@ -2980,7 +2989,7 @@ static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p)
assert(rt->atom_count >= 0);
}
-static void JS_FreeAtomImpl(JSRuntime *rt, uint32_t i)
+static void __JS_FreeAtom(JSRuntime *rt, uint32_t i)
{
JSAtomStruct *p;
@@ -2998,19 +3007,21 @@ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p)
if (is_num_string(&n, p)) {
if (n <= JS_ATOM_MAX_INT) {
js_free_string(rt, p);
- return JS_AtomFromUInt32(n);
+ return __JS_AtomFromUInt32(n);
}
}
/* XXX: should generate an exception */
- return JS_NewAtomImpl(rt, p, JS_ATOM_TYPE_STRING);
+ return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING);
}
+/* str is UTF-8 encoded */
JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)
{
JSValue val;
if (len == 0 || !is_digit(*str)) {
- JSAtom atom = JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
+ // XXX: this will not work if UTF-8 encoded str contains non ASCII bytes
+ JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
if (atom)
return atom;
}
@@ -3028,7 +3039,7 @@ JSAtom JS_NewAtom(JSContext *ctx, const char *str)
JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
{
if (n <= JS_ATOM_MAX_INT) {
- return JS_AtomFromUInt32(n);
+ return __JS_AtomFromUInt32(n);
} else {
char buf[11];
JSValue val;
@@ -3036,7 +3047,7 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
val = JS_NewString(ctx, buf);
if (JS_IsException(val))
return JS_ATOM_NULL;
- return JS_NewAtomImpl(ctx->rt, JS_VALUE_GET_STRING(val),
+ return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
JS_ATOM_TYPE_STRING);
}
}
@@ -3044,7 +3055,7 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
{
if ((uint64_t)n <= JS_ATOM_MAX_INT) {
- return JS_AtomFromUInt32((uint32_t)n);
+ return __JS_AtomFromUInt32((uint32_t)n);
} else {
char buf[24];
JSValue val;
@@ -3052,7 +3063,7 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
val = JS_NewString(ctx, buf);
if (JS_IsException(val))
return JS_ATOM_NULL;
- return JS_NewAtomImpl(ctx->rt, JS_VALUE_GET_STRING(val),
+ return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
JS_ATOM_TYPE_STRING);
}
}
@@ -3062,7 +3073,7 @@ static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type)
{
JSRuntime *rt = ctx->rt;
JSAtom atom;
- atom = JS_NewAtomImpl(rt, p, atom_type);
+ atom = __JS_NewAtom(rt, p, atom_type);
if (atom == JS_ATOM_NULL)
return JS_ThrowOutOfMemory(ctx);
return JS_MKPTR(JS_TAG_SYMBOL, rt->atom_array[atom]);
@@ -3075,7 +3086,7 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
JSRuntime *rt = ctx->rt;
JSString *p;
- assert(!JS_AtomIsTaggedInt(descr));
+ assert(!__JS_AtomIsTaggedInt(descr));
assert(descr < rt->atom_size);
p = rt->atom_array[descr];
JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
@@ -3088,8 +3099,8 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,
JSAtom atom)
{
- if (JS_AtomIsTaggedInt(atom)) {
- snprintf(buf, buf_size, "%u", JS_AtomToUInt32(atom));
+ if (__JS_AtomIsTaggedInt(atom)) {
+ snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom));
} else {
JSAtomStruct *p;
assert(atom < rt->atom_size);
@@ -3115,10 +3126,7 @@ static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,
return (const char *)str->u.str8;
}
for(i = 0; i < str->len; i++) {
- if (str->is_wide_char)
- c = str->u.str16[i];
- else
- c = str->u.str8[i];
+ c = string_get(str, i);
if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX)
break;
if (c < 128) {
@@ -3139,12 +3147,12 @@ static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom
return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom);
}
-static JSValue JS_AtomToValueImpl(JSContext *ctx, JSAtom atom, BOOL force_string)
+static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)
{
char buf[ATOM_GET_STR_BUF_SIZE];
- if (JS_AtomIsTaggedInt(atom)) {
- snprintf(buf, sizeof(buf), "%u", JS_AtomToUInt32(atom));
+ if (__JS_AtomIsTaggedInt(atom)) {
+ snprintf(buf, sizeof(buf), "%u", __JS_AtomToUInt32(atom));
return JS_NewString(ctx, buf);
} else {
JSRuntime *rt = ctx->rt;
@@ -3168,20 +3176,20 @@ static JSValue JS_AtomToValueImpl(JSContext *ctx, JSAtom atom, BOOL force_string
JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom)
{
- return JS_AtomToValueImpl(ctx, atom, FALSE);
+ return __JS_AtomToValue(ctx, atom, FALSE);
}
JSValue JS_AtomToString(JSContext *ctx, JSAtom atom)
{
- return JS_AtomToValueImpl(ctx, atom, TRUE);
+ return __JS_AtomToValue(ctx, atom, TRUE);
}
/* return TRUE if the atom is an array index (i.e. 0 <= index <=
2^32-2 and return its value */
static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom)
{
- if (JS_AtomIsTaggedInt(atom)) {
- *pval = JS_AtomToUInt32(atom);
+ if (__JS_AtomIsTaggedInt(atom)) {
+ *pval = __JS_AtomToUInt32(atom);
return TRUE;
} else {
JSRuntime *rt = ctx->rt;
@@ -3212,8 +3220,8 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
int c, len, ret;
JSValue num, str;
- if (JS_AtomIsTaggedInt(atom))
- return JS_NewInt32(ctx, JS_AtomToUInt32(atom));
+ if (__JS_AtomIsTaggedInt(atom))
+ return JS_NewInt32(ctx, __JS_AtomToUInt32(atom));
assert(atom < rt->atom_size);
p1 = rt->atom_array[atom];
if (p1->atom_type != JS_ATOM_TYPE_STRING)
@@ -3255,7 +3263,7 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
/* -0 case is specific */
if (c == '0' && len == 2) {
minus_zero:
- return JS_NewFloat64Impl(ctx, -0.0);
+ return __JS_NewFloat64(ctx, -0.0);
}
}
if (!is_num(c)) {
@@ -3300,14 +3308,14 @@ static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom)
void JS_FreeAtom(JSContext *ctx, JSAtom v)
{
- if (!JS_AtomIsConst(v))
- JS_FreeAtomImpl(ctx->rt, v);
+ if (!__JS_AtomIsConst(v))
+ __JS_FreeAtom(ctx->rt, v);
}
void JS_FreeAtomRT(JSRuntime *rt, JSAtom v)
{
- if (!JS_AtomIsConst(v))
- JS_FreeAtomImpl(rt, v);
+ if (!__JS_AtomIsConst(v))
+ __JS_FreeAtom(rt, v);
}
/* return TRUE if 'v' is a symbol with a string description */
@@ -3317,7 +3325,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
JSAtomStruct *p;
rt = ctx->rt;
- if (JS_AtomIsTaggedInt(v))
+ if (__JS_AtomIsTaggedInt(v))
return FALSE;
p = rt->atom_array[v];
return (((p->atom_type == JS_ATOM_TYPE_SYMBOL &&
@@ -3326,7 +3334,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
!(p->len == 0 && p->is_wide_char != 0));
}
-static maybe_unused void print_atom(JSContext *ctx, JSAtom atom)
+static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom)
{
char buf[ATOM_GET_STR_BUF_SIZE];
const char *p;
@@ -3425,19 +3433,37 @@ static inline BOOL JS_IsEmptyString(JSValueConst v)
/* JSClass support */
+#ifdef CONFIG_ATOMICS
+static pthread_mutex_t js_class_id_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
/* a new class ID is allocated if *pclass_id != 0 */
JSClassID JS_NewClassID(JSClassID *pclass_id)
{
JSClassID class_id;
- /* XXX: make it thread safe */
+#ifdef CONFIG_ATOMICS
+ pthread_mutex_lock(&js_class_id_mutex);
+#endif
class_id = *pclass_id;
if (class_id == 0) {
class_id = js_class_id_alloc++;
*pclass_id = class_id;
}
+#ifdef CONFIG_ATOMICS
+ pthread_mutex_unlock(&js_class_id_mutex);
+#endif
return class_id;
}
+JSClassID JS_GetClassID(JSValue v)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
+ return JS_INVALID_CLASS_ID;
+ p = JS_VALUE_GET_OBJ(v);
+ return p->class_id;
+}
+
BOOL JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id)
{
return (class_id < rt->class_count &&
@@ -3501,9 +3527,9 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def)
JSAtom name;
len = strlen(class_def->class_name);
- name = JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
+ name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
if (name == JS_ATOM_NULL) {
- name = JS_NewAtomInitImpl(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
+ name = __JS_NewAtomInit(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
if (name == JS_ATOM_NULL)
return -1;
}
@@ -3732,28 +3758,23 @@ static int string_buffer_putc(StringBuffer *s, uint32_t c)
{
if (unlikely(c >= 0x10000)) {
/* surrogate pair */
- c -= 0x10000;
- if (string_buffer_putc16(s, (c >> 10) + 0xd800))
+ if (string_buffer_putc16(s, get_hi_surrogate(c)))
return -1;
- c = (c & 0x3ff) + 0xdc00;
+ c = get_lo_surrogate(c);
}
return string_buffer_putc16(s, c);
}
-static int string_get(const JSString *p, int idx) {
- return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx];
-}
-
static int string_getc(const JSString *p, int *pidx)
{
int idx, c, c1;
idx = *pidx;
if (p->is_wide_char) {
c = p->u.str16[idx++];
- if (c >= 0xd800 && c < 0xdc00 && idx < p->len) {
+ if (is_hi_surrogate(c) && idx < p->len) {
c1 = p->u.str16[idx];
- if (c1 >= 0xdc00 && c1 < 0xe000) {
- c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
+ if (is_lo_surrogate(c1)) {
+ c = from_surrogate(c, c1);
idx++;
}
}
@@ -3951,9 +3972,8 @@ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len)
} else if (c <= 0x10FFFF) {
p = p_next;
/* surrogate pair */
- c -= 0x10000;
- string_buffer_putc16(b, (c >> 10) + 0xd800);
- c = (c & 0x3ff) + 0xdc00;
+ string_buffer_putc16(b, get_hi_surrogate(c));
+ c = get_lo_surrogate(c);
} else {
/* invalid char */
c = 0xfffd;
@@ -4091,13 +4111,12 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BO
if (c < 0x80) {
*q++ = c;
} else {
- if (c >= 0xd800 && c < 0xdc00) {
+ if (is_hi_surrogate(c)) {
if (pos < len && !cesu8) {
c1 = src[pos];
- if (c1 >= 0xdc00 && c1 < 0xe000) {
+ if (is_lo_surrogate(c1)) {
pos++;
- /* surrogate pair */
- c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
+ c = from_surrogate(c, c1);
} else {
/* Keep unmatched surrogate code points */
/* c = 0xfffd; */ /* error */
@@ -4130,7 +4149,7 @@ void JS_FreeCString(JSContext *ctx, const char *ptr)
if (!ptr)
return;
/* purposely removing constness */
- p = (JSString *)(void *)(ptr - offsetof(JSString, u));
+ p = container_of(ptr, JSString, u);
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
}
@@ -4230,7 +4249,43 @@ static JSValue JS_ConcatString1(JSContext *ctx,
return JS_MKPTR(JS_TAG_STRING, p);
}
-/* op1 and op2 are converted to strings. For convience, op1 or op2 =
+static BOOL JS_ConcatStringInPlace(JSContext *ctx, JSString *p1, JSValueConst op2) {
+ if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {
+ JSString *p2 = JS_VALUE_GET_STRING(op2);
+ size_t size1;
+
+ if (p2->len == 0)
+ return TRUE;
+ if (p1->header.ref_count != 1)
+ return FALSE;
+ size1 = js_malloc_usable_size(ctx, p1);
+ if (p1->is_wide_char) {
+ if (size1 >= sizeof(*p1) + ((p1->len + p2->len) << 1)) {
+ if (p2->is_wide_char) {
+ memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1);
+ p1->len += p2->len;
+ return TRUE;
+ } else {
+ size_t i;
+ for (i = 0; i < p2->len; i++) {
+ p1->u.str16[p1->len++] = p2->u.str8[i];
+ }
+ return TRUE;
+ }
+ }
+ } else if (!p2->is_wide_char) {
+ if (size1 >= sizeof(*p1) + p1->len + p2->len + 1) {
+ memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len);
+ p1->len += p2->len;
+ p1->u.str8[p1->len] = '\0';
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/* op1 and op2 are converted to strings. For convenience, op1 or op2 =
JS_EXCEPTION are accepted and return JS_EXCEPTION. */
static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)
{
@@ -4252,27 +4307,11 @@ static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)
}
}
p1 = JS_VALUE_GET_STRING(op1);
- p2 = JS_VALUE_GET_STRING(op2);
-
- /* XXX: could also check if p1 is empty */
- if (p2->len == 0) {
- goto ret_op1;
- }
- if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char
- && js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) {
- /* Concatenate in place in available space at the end of p1 */
- if (p1->is_wide_char) {
- memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1);
- p1->len += p2->len;
- } else {
- memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len);
- p1->len += p2->len;
- p1->u.str8[p1->len] = '\0';
- }
- ret_op1:
+ if (JS_ConcatStringInPlace(ctx, p1, op2)) {
JS_FreeValue(ctx, op2);
return op1;
}
+ p2 = JS_VALUE_GET_STRING(op2);
ret = JS_ConcatString1(ctx, p1, p2);
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -4509,6 +4548,7 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
JSShapeProperty *pr;
void *sh_alloc;
intptr_t h;
+ JSShape *old_sh;
sh = *psh;
new_size = max_int(count, sh->prop_size * 3 / 2);
@@ -4524,19 +4564,21 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
new_hash_size = sh->prop_hash_mask + 1;
while (new_hash_size < new_size)
new_hash_size = 2 * new_hash_size;
+ /* resize the property shapes. Using js_realloc() is not possible in
+ case the GC runs during the allocation */
+ old_sh = sh;
+ sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
+ if (!sh_alloc)
+ return -1;
+ sh = get_shape_from_alloc(sh_alloc, new_hash_size);
+ list_del(&old_sh->header.link);
+ /* copy all the shape properties */
+ memcpy(sh, old_sh,
+ sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
+ list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
+
if (new_hash_size != (sh->prop_hash_mask + 1)) {
- JSShape *old_sh;
/* resize the hash table and the properties */
- old_sh = sh;
- sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
- if (!sh_alloc)
- return -1;
- sh = get_shape_from_alloc(sh_alloc, new_hash_size);
- list_del(&old_sh->header.link);
- /* copy all the fields and the properties */
- memcpy(sh, old_sh,
- sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
- list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
new_hash_mask = new_hash_size - 1;
sh->prop_hash_mask = new_hash_mask;
memset(prop_hash_end(sh) - new_hash_size, 0,
@@ -4548,20 +4590,12 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
prop_hash_end(sh)[-h - 1] = i + 1;
}
}
- js_free(ctx, get_alloc_from_shape(old_sh));
} else {
- /* only resize the properties */
- list_del(&sh->header.link);
- sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh),
- get_shape_size(new_hash_size, new_size));
- if (unlikely(!sh_alloc)) {
- /* insert again in the GC list */
- list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
- return -1;
- }
- sh = get_shape_from_alloc(sh_alloc, new_hash_size);
- list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
+ /* just copy the previous hash table */
+ memcpy(prop_hash_end(sh) - new_hash_size, prop_hash_end(old_sh) - new_hash_size,
+ sizeof(prop_hash_end(sh)[0]) * new_hash_size);
}
+ js_free(ctx, get_alloc_from_shape(old_sh));
*psh = sh;
sh->prop_size = new_size;
return 0;
@@ -4670,7 +4704,7 @@ static int add_shape_property(JSContext *ctx, JSShape **psh,
pr = &prop[sh->prop_count++];
pr->atom = JS_DupAtom(ctx, atom);
pr->flags = prop_flags;
- sh->has_small_array_index |= JS_AtomIsTaggedInt(atom);
+ sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom);
/* add in hash table */
hash_mask = sh->prop_hash_mask;
h = atom & hash_mask;
@@ -4731,7 +4765,7 @@ static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh,
return NULL;
}
-static maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
+static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
{
char atom_buf[ATOM_GET_STR_BUF_SIZE];
int j;
@@ -4747,7 +4781,7 @@ static maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
printf("\n");
}
-static maybe_unused void JS_DumpShapes(JSRuntime *rt)
+static __maybe_unused void JS_DumpShapes(JSRuntime *rt)
{
int i;
JSShape *sh;
@@ -4838,10 +4872,8 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
case JS_CLASS_UINT16_ARRAY:
case JS_CLASS_INT32_ARRAY:
case JS_CLASS_UINT32_ARRAY:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
-#endif
case JS_CLASS_FLOAT32_ARRAY:
case JS_CLASS_FLOAT64_ARRAY:
p->is_exotic = 1;
@@ -4858,8 +4890,8 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
case JS_CLASS_BOOLEAN:
case JS_CLASS_SYMBOL:
case JS_CLASS_DATE:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT:
case JS_CLASS_BIG_DECIMAL:
#endif
@@ -4921,8 +4953,8 @@ static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj)
case JS_CLASS_BOOLEAN:
case JS_CLASS_SYMBOL:
case JS_CLASS_DATE:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT:
case JS_CLASS_BIG_DECIMAL:
#endif
@@ -4945,8 +4977,8 @@ static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val)
case JS_CLASS_BOOLEAN:
case JS_CLASS_SYMBOL:
case JS_CLASS_DATE:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT:
case JS_CLASS_BIG_DECIMAL:
#endif
@@ -5293,10 +5325,12 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref)
if (--var_ref->header.ref_count == 0) {
if (var_ref->is_detached) {
JS_FreeValueRT(rt, var_ref->value);
- remove_gc_object(&var_ref->header);
} else {
- list_del(&var_ref->header.link); /* still on the stack */
+ list_del(&var_ref->var_ref_link); /* still on the stack */
+ if (var_ref->async_func)
+ async_func_free(rt, var_ref->async_func);
}
+ remove_gc_object(&var_ref->header);
js_free_rt(rt, var_ref);
}
}
@@ -5394,7 +5428,7 @@ static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
if (var_refs) {
for(i = 0; i < b->closure_var_count; i++) {
JSVarRef *var_ref = var_refs[i];
- if (var_ref && var_ref->is_detached) {
+ if (var_ref) {
mark_func(rt, &var_ref->header);
}
}
@@ -5436,7 +5470,15 @@ static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JSForInIterator *it = p->u.for_in_iterator;
+ int i;
+
JS_FreeValueRT(rt, it->obj);
+ if (!it->is_array) {
+ for(i = 0; i < it->atom_count; i++) {
+ JS_FreeAtomRT(rt, it->tab_atom[i].atom);
+ }
+ js_free_rt(rt, it->tab_atom);
+ }
js_free_rt(rt, it);
}
@@ -5504,6 +5546,9 @@ static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp)
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
free_function_bytecode(rt, (JSFunctionBytecode *)gp);
break;
+ case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
+ __async_func_free(rt, (JSAsyncFunctionState *)gp);
+ break;
default:
abort();
}
@@ -5527,7 +5572,7 @@ static void free_zero_refcount(JSRuntime *rt)
}
/* called with the ref_count of 'v' reaches zero. */
-static void JS_FreeValueRTImpl(JSRuntime *rt, JSValue v)
+static void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
{
uint32_t tag = JS_VALUE_GET_TAG(v);
@@ -5573,15 +5618,17 @@ static void JS_FreeValueRTImpl(JSRuntime *rt, JSValue v)
case JS_TAG_MODULE:
abort(); /* never freed here */
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *bf = JS_VALUE_GET_PTR(v);
bf_delete(&bf->num);
js_free_rt(rt, bf);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL:
{
JSBigDecimal *bf = JS_VALUE_GET_PTR(v);
@@ -5602,9 +5649,9 @@ static void JS_FreeValueRTImpl(JSRuntime *rt, JSValue v)
}
}
-static void JS_FreeValueImpl(JSContext *ctx, JSValue v)
+static void __JS_FreeValue(JSContext *ctx, JSValue v)
{
- JS_FreeValueRTImpl(ctx->rt, v);
+ __JS_FreeValueRT(ctx->rt, v);
}
/* garbage collection */
@@ -5660,11 +5707,9 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
if (pr->u.getset.setter)
mark_func(rt, &pr->u.getset.setter->header);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
- if (pr->u.var_ref->is_detached) {
- /* Note: the tag does not matter
- provided it is a GC object */
- mark_func(rt, &pr->u.var_ref->header);
- }
+ /* Note: the tag does not matter
+ provided it is a GC object */
+ mark_func(rt, &pr->u.var_ref->header);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
js_autoinit_mark(rt, pr, mark_func);
}
@@ -5698,16 +5743,32 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
case JS_GC_OBJ_TYPE_VAR_REF:
{
JSVarRef *var_ref = (JSVarRef *)gp;
- /* only detached variable referenced are taken into account */
- assert(var_ref->is_detached);
- JS_MarkValue(rt, *var_ref->pvalue, mark_func);
+ if (var_ref->is_detached) {
+ JS_MarkValue(rt, *var_ref->pvalue, mark_func);
+ } else if (var_ref->async_func) {
+ mark_func(rt, &var_ref->async_func->header);
+ }
}
break;
case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
{
- JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp;
- if (s->is_active)
- async_func_mark(rt, &s->func_state, mark_func);
+ JSAsyncFunctionState *s = (JSAsyncFunctionState *)gp;
+ JSStackFrame *sf = &s->frame;
+ JSValue *sp;
+
+ if (!s->is_completed) {
+ JS_MarkValue(rt, sf->cur_func, mark_func);
+ JS_MarkValue(rt, s->this_val, mark_func);
+ /* sf->cur_sp = NULL if the function is running */
+ if (sf->cur_sp) {
+ /* if the function is running, cur_sp is not known so we
+ cannot mark the stack. Marking the variables is not needed
+ because a running function cannot be part of a removable
+ cycle */
+ for(sp = sf->arg_buf; sp < sf->cur_sp; sp++)
+ JS_MarkValue(rt, *sp, mark_func);
+ }
+ }
JS_MarkValue(rt, s->resolving_funcs[0], mark_func);
JS_MarkValue(rt, s->resolving_funcs[1], mark_func);
}
@@ -5815,12 +5876,13 @@ static void gc_free_cycles(JSRuntime *rt)
if (el == &rt->tmp_obj_list)
break;
p = list_entry(el, JSGCObjectHeader, link);
- /* Only need to free the GC object associated with JS
- values. The rest will be automatically removed because they
- must be referenced by them. */
+ /* Only need to free the GC object associated with JS values
+ or async functions. The rest will be automatically removed
+ because they must be referenced by them. */
switch(p->gc_obj_type) {
case JS_GC_OBJ_TYPE_JS_OBJECT:
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
+ case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
#ifdef DUMP_GC_FREE
if (!header_done) {
printf("Freeing cycles:\n");
@@ -5842,7 +5904,8 @@ static void gc_free_cycles(JSRuntime *rt)
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 ||
- p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
+ p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE ||
+ p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
js_free_rt(rt, p);
}
@@ -5944,13 +6007,13 @@ static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp)
case JS_TAG_STRING:
compute_jsstring_size(JS_VALUE_GET_STRING(val), hp);
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
case JS_TAG_BIG_DECIMAL:
+#endif
/* should track JSBigFloat usage */
break;
-#endif
}
}
@@ -6074,8 +6137,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
case JS_CLASS_BOOLEAN: /* u.object_data */
case JS_CLASS_SYMBOL: /* u.object_data */
case JS_CLASS_DATE: /* u.object_data */
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT: /* u.object_data */
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT: /* u.object_data */
case JS_CLASS_BIG_DECIMAL: /* u.object_data */
#endif
@@ -6167,10 +6230,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
case JS_CLASS_UINT16_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_INT32_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_UINT32_ARRAY: /* u.typed_array / u.array */
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_BIG_UINT64_ARRAY: /* u.typed_array / u.array */
-#endif
case JS_CLASS_FLOAT32_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_FLOAT64_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_DATAVIEW: /* u.typed_array */
@@ -6251,7 +6312,7 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
"BigNum "
#endif
CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n",
- (int)sizeof(void *) * 8, (int64_t)(ssize_t)s->malloc_limit);
+ (int)sizeof(void *) * 8, s->malloc_limit);
#if 1
if (rt) {
static const struct {
@@ -6297,10 +6358,10 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
if (obj_classes[0])
fprintf(fp, " %5d %2.0d %s\n", obj_classes[0], 0, "none");
for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) {
- if (obj_classes[class_id]) {
+ if (obj_classes[class_id] && class_id < rt->class_count) {
char buf[ATOM_GET_STR_BUF_SIZE];
fprintf(fp, " %5d %2.0d %s\n", obj_classes[class_id], class_id,
- JS_AtomGetStrRT(rt, buf, sizeof(buf), js_std_class_def[class_id - 1].class_name));
+ JS_AtomGetStrRT(rt, buf, sizeof(buf), rt->class_array[class_id].class_name));
}
}
if (obj_classes[JS_CLASS_INIT_COUNT])
@@ -6397,6 +6458,11 @@ JSValue JS_GetException(JSContext *ctx)
return val;
}
+JS_BOOL JS_HasException(JSContext *ctx)
+{
+ return !JS_IsNull(ctx->rt->current_exception);
+}
+
static void dbuf_put_leb128(DynBuf *s, uint32_t v)
{
uint32_t a;
@@ -6526,8 +6592,8 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func)
/* if filename != NULL, an additional level is added with the filename
and line number information (used for parse error). */
void build_backtrace(JSContext *ctx, JSValueConst error_obj,
- const char *filename, int line_num,
- int backtrace_flags)
+ const char *filename, int line_num,
+ int backtrace_flags)
{
JSStackFrame *sf;
JSValue str;
@@ -6698,7 +6764,7 @@ static int FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags,
}
/* never use it directly */
-static JSValue FORMAT_ATTR(3, 4) JS_ThrowTypeErrorAtomImpl(JSContext *ctx, JSAtom atom, const char *fmt, ...)
+static JSValue FORMAT_ATTR(3, 4) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
{
char buf[ATOM_GET_STR_BUF_SIZE];
return JS_ThrowTypeError(ctx, fmt,
@@ -6706,7 +6772,7 @@ static JSValue FORMAT_ATTR(3, 4) JS_ThrowTypeErrorAtomImpl(JSContext *ctx, JSAto
}
/* never use it directly */
-static JSValue FORMAT_ATTR(3, 4) JS_ThrowSyntaxErrorAtomImpl(JSContext *ctx, JSAtom atom, const char *fmt, ...)
+static JSValue FORMAT_ATTR(3, 4) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
{
char buf[ATOM_GET_STR_BUF_SIZE];
return JS_ThrowSyntaxError(ctx, fmt,
@@ -6715,8 +6781,8 @@ static JSValue FORMAT_ATTR(3, 4) JS_ThrowSyntaxErrorAtomImpl(JSContext *ctx, JSA
/* %s is replaced by 'atom'. The macro is used so that gcc can check
the format string. */
-#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) JS_ThrowTypeErrorAtomImpl(ctx, atom, fmt, "")
-#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) JS_ThrowSyntaxErrorAtomImpl(ctx, atom, fmt, "")
+#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "")
+#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "")
static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
{
@@ -6826,7 +6892,7 @@ static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)
return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name);
}
-static no_inline warn_unused int js_poll_interrupts_impl(JSContext *ctx)
+static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
{
JSRuntime *rt = ctx->rt;
ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
@@ -6841,10 +6907,10 @@ static no_inline warn_unused int js_poll_interrupts_impl(JSContext *ctx)
return 0;
}
-static inline warn_unused int js_poll_interrupts(JSContext *ctx)
+static inline __exception int js_poll_interrupts(JSContext *ctx)
{
if (unlikely(--ctx->interrupt_counter <= 0)) {
- return js_poll_interrupts_impl(ctx);
+ return __js_poll_interrupts(ctx);
} else {
return 0;
}
@@ -6931,10 +6997,10 @@ int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val)
static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val)
{
switch(JS_VALUE_GET_NORM_TAG(val)) {
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
val = ctx->class_proto[JS_CLASS_BIG_INT];
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
val = ctx->class_proto[JS_CLASS_BIG_FLOAT];
break;
@@ -7148,9 +7214,9 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
case JS_TAG_STRING:
{
JSString *p1 = JS_VALUE_GET_STRING(obj);
- if (JS_AtomIsTaggedInt(prop)) {
+ if (__JS_AtomIsTaggedInt(prop)) {
uint32_t idx, ch;
- idx = JS_AtomToUInt32(prop);
+ idx = __JS_AtomToUInt32(prop);
if (idx < p1->len) {
if (p1->is_wide_char)
ch = p1->u.str16[idx];
@@ -7208,8 +7274,8 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
if (unlikely(p->is_exotic)) {
/* exotic behaviors */
if (p->fast_array) {
- if (JS_AtomIsTaggedInt(prop)) {
- uint32_t idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ uint32_t idx = __JS_AtomToUInt32(prop);
if (idx < p->u.array.count) {
/* we avoid duplicating the code */
return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
@@ -7371,6 +7437,8 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,
return 0;
}
+/* add a private brand field to 'home_obj' if not already present and
+ if obj is != null add a private brand to it */
static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
{
JSObject *p, *p1;
@@ -7386,10 +7454,10 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
p = JS_VALUE_GET_OBJ(home_obj);
prs = find_own_property(&pr, p, JS_ATOM_Private_brand);
if (!prs) {
+ /* if the brand is not present, add it */
brand = JS_NewSymbolFromAtom(ctx, JS_ATOM_brand, JS_ATOM_TYPE_PRIVATE);
if (JS_IsException(brand))
return -1;
- /* if the brand is not present, add it */
pr = add_property(ctx, p, JS_ATOM_Private_brand, JS_PROP_C_W_E);
if (!pr) {
JS_FreeValue(ctx, brand);
@@ -7401,20 +7469,27 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
}
brand_atom = js_symbol_to_atom(ctx, brand);
- if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {
- JS_ThrowTypeErrorNotAnObject(ctx);
+ if (JS_IsObject(obj)) {
+ p1 = JS_VALUE_GET_OBJ(obj);
+ prs = find_own_property(&pr, p1, brand_atom);
+ if (unlikely(prs)) {
+ JS_FreeAtom(ctx, brand_atom);
+ JS_ThrowTypeError(ctx, "private method is already present");
+ return -1;
+ }
+ pr = add_property(ctx, p1, brand_atom, JS_PROP_C_W_E);
+ JS_FreeAtom(ctx, brand_atom);
+ if (!pr)
+ return -1;
+ pr->u.value = JS_UNDEFINED;
+ } else {
JS_FreeAtom(ctx, brand_atom);
- return -1;
}
- p1 = JS_VALUE_GET_OBJ(obj);
- pr = add_property(ctx, p1, brand_atom, JS_PROP_C_W_E);
- JS_FreeAtom(ctx, brand_atom);
- if (!pr)
- return -1;
- pr->u.value = JS_UNDEFINED;
return 0;
}
+/* return a boolean telling if the brand of the home object of 'func'
+ is present on 'obj' or -1 in case of exception */
static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
{
JSObject *p, *p1, *home_obj;
@@ -7423,11 +7498,8 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
JSValueConst brand;
/* get the home object of 'func' */
- if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) {
- not_obj:
- JS_ThrowTypeErrorNotAnObject(ctx);
- return -1;
- }
+ if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT))
+ goto not_obj;
p1 = JS_VALUE_GET_OBJ(func);
if (!js_class_has_bytecode(p1->class_id))
goto not_obj;
@@ -7445,15 +7517,14 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
goto not_obj;
/* get the brand array of 'obj' */
- if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
- goto not_obj;
- p = JS_VALUE_GET_OBJ(obj);
- prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, brand));
- if (!prs) {
- JS_ThrowTypeError(ctx, "invalid brand on object");
+ if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {
+ not_obj:
+ JS_ThrowTypeErrorNotAnObject(ctx);
return -1;
}
- return 0;
+ p = JS_VALUE_GET_OBJ(obj);
+ prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, brand));
+ return (prs != NULL);
}
static uint32_t js_string_obj_get_length(JSContext *ctx,
@@ -7503,7 +7574,7 @@ static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
/* return < 0 in case if exception, 0 if OK. ptab and its atoms must
be freed by the user. */
-static int warn_unused JS_GetOwnPropertyNamesInternal(JSContext *ctx,
+static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
JSPropertyEnum **ptab,
uint32_t *plen,
JSObject *p, int flags)
@@ -7653,7 +7724,7 @@ static int warn_unused JS_GetOwnPropertyNamesInternal(JSContext *ctx,
len = js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
add_array_keys:
for(i = 0; i < len; i++) {
- tab_atom[num_index].atom = JS_AtomFromUInt32(i);
+ tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
if (tab_atom[num_index].atom == JS_ATOM_NULL) {
js_free_prop_enum(ctx, tab_atom, num_index);
return -1;
@@ -7761,9 +7832,9 @@ retry:
if (p->is_exotic) {
if (p->fast_array) {
/* specific case for fast arrays */
- if (JS_AtomIsTaggedInt(prop)) {
+ if (__JS_AtomIsTaggedInt(prop)) {
uint32_t idx;
- idx = JS_AtomToUInt32(prop);
+ idx = __JS_AtomToUInt32(prop);
if (idx < p->u.array.count) {
if (desc) {
desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE |
@@ -7883,7 +7954,7 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)
if (tag == JS_TAG_INT &&
(uint32_t)JS_VALUE_GET_INT(val) <= JS_ATOM_MAX_INT) {
/* fast path for integer values */
- atom = JS_AtomFromUInt32(JS_VALUE_GET_INT(val));
+ atom = __JS_AtomFromUInt32(JS_VALUE_GET_INT(val));
} else if (tag == JS_TAG_SYMBOL) {
JSAtomStruct *p = JS_VALUE_GET_PTR(val);
atom = JS_DupAtom(ctx, js_get_atom_index(ctx->rt, p));
@@ -7910,40 +7981,46 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT &&
JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) {
JSObject *p;
- uint32_t idx, len;
+ uint32_t idx;
/* fast path for array access */
p = JS_VALUE_GET_OBJ(this_obj);
idx = JS_VALUE_GET_INT(prop);
- len = p->u.array.count;
- if (unlikely(idx >= len))
- goto slow_path;
switch(p->class_id) {
case JS_CLASS_ARRAY:
case JS_CLASS_ARGUMENTS:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_DupValue(ctx, p->u.array.u.values[idx]);
case JS_CLASS_INT8_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.int8_ptr[idx]);
case JS_CLASS_UINT8C_ARRAY:
case JS_CLASS_UINT8_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.uint8_ptr[idx]);
case JS_CLASS_INT16_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.int16_ptr[idx]);
case JS_CLASS_UINT16_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.uint16_ptr[idx]);
case JS_CLASS_INT32_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.int32_ptr[idx]);
case JS_CLASS_UINT32_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewUint32(ctx, p->u.array.u.uint32_ptr[idx]);
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]);
case JS_CLASS_BIG_UINT64_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);
-#endif
case JS_CLASS_FLOAT32_ARRAY:
- return JS_NewFloat64Impl(ctx, p->u.array.u.float_ptr[idx]);
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
+ return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]);
case JS_CLASS_FLOAT64_ARRAY:
- return JS_NewFloat64Impl(ctx, p->u.array.u.double_ptr[idx]);
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
+ return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]);
default:
goto slow_path;
}
@@ -7978,7 +8055,7 @@ static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx,
if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) {
/* fast path */
- present = JS_HasProperty(ctx, obj, JS_AtomFromUInt32(idx));
+ present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx));
if (present > 0) {
val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));
if (unlikely(JS_IsException(val)))
@@ -8075,7 +8152,7 @@ static JSProperty *add_property(JSContext *ctx,
/* can be called on Array or Arguments objects. return < 0 if
memory alloc error. */
-static no_inline warn_unused int convert_fast_array_to_array(JSContext *ctx,
+static no_inline __exception int convert_fast_array_to_array(JSContext *ctx,
JSObject *p)
{
JSProperty *pr;
@@ -8097,8 +8174,8 @@ static no_inline warn_unused int convert_fast_array_to_array(JSContext *ctx,
tab = p->u.array.u.values;
for(i = 0; i < len; i++) {
/* add_property cannot fail here but
- JS_AtomFromUInt32(i) fails for i > INT32_MAX */
- pr = add_property(ctx, p, JS_AtomFromUInt32(i), JS_PROP_C_W_E);
+ __JS_AtomFromUInt32(i) fails for i > INT32_MAX */
+ pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E);
pr->u.value = *tab++;
}
js_free(ctx, p->u.array.u.values);
@@ -8203,7 +8280,7 @@ static int call_setter(JSContext *ctx, JSObject *setter,
func = JS_MKPTR(JS_TAG_OBJECT, setter);
/* Note: the field could be removed in the setter */
func = JS_DupValue(ctx, func);
- ret = JS_CallFree(ctx, func, this_obj, 1, &val);
+ ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val);
JS_FreeValue(ctx, val);
if (JS_IsException(ret))
return -1;
@@ -8360,126 +8437,45 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p,
return TRUE;
}
-static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)
+/* Allocate a new fast array. Its 'length' property is set to zero. It
+ maximum size is 2^31-1 elements. For convenience, 'len' is a 64 bit
+ integer. WARNING: the content of the array is not initialized. */
+static JSValue js_allocate_fast_array(JSContext *ctx, int64_t len)
{
- JS_FreeValue(ctx, desc->getter);
- JS_FreeValue(ctx, desc->setter);
- JS_FreeValue(ctx, desc->value);
-}
-
-/* generic (and slower) version of JS_SetProperty() for
- * Reflect.set(). 'obj' must be an object. */
-static int JS_SetPropertyGeneric(JSContext *ctx,
- JSValueConst obj, JSAtom prop,
- JSValue val, JSValueConst this_obj,
- int flags)
-{
- int ret;
- JSPropertyDescriptor desc;
- JSValue obj1;
+ JSValue arr;
JSObject *p;
- obj1 = JS_DupValue(ctx, obj);
- for(;;) {
- p = JS_VALUE_GET_OBJ(obj1);
- if (p->is_exotic) {
- const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
- if (em && em->set_property) {
- ret = em->set_property(ctx, obj1, prop,
- val, this_obj, flags);
- JS_FreeValue(ctx, obj1);
- JS_FreeValue(ctx, val);
- return ret;
- }
- }
-
- ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
- if (ret < 0) {
- JS_FreeValue(ctx, obj1);
- JS_FreeValue(ctx, val);
- return ret;
- }
- if (ret) {
- if (desc.flags & JS_PROP_GETSET) {
- JSObject *setter;
- if (JS_IsUndefined(desc.setter))
- setter = NULL;
- else
- setter = JS_VALUE_GET_OBJ(desc.setter);
- ret = call_setter(ctx, setter, this_obj, val, flags);
- JS_FreeValue(ctx, desc.getter);
- JS_FreeValue(ctx, desc.setter);
- JS_FreeValue(ctx, obj1);
- return ret;
- } else {
- JS_FreeValue(ctx, desc.value);
- if (!(desc.flags & JS_PROP_WRITABLE)) {
- JS_FreeValue(ctx, obj1);
- goto read_only_error;
- }
- }
- break;
- }
- /* Note: at this point 'obj1' cannot be a proxy. XXX: may have
- to check recursion */
- obj1 = JS_GetPrototypeFree(ctx, obj1);
- if (JS_IsNull(obj1))
- break;
- }
- JS_FreeValue(ctx, obj1);
-
- if (!JS_IsObject(this_obj)) {
- 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 */
- ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
- if (ret < 0) {
- JS_FreeValue(ctx, val);
- return ret;
- }
- if (ret) {
- if (desc.flags & JS_PROP_GETSET) {
- JS_FreeValue(ctx, desc.getter);
- JS_FreeValue(ctx, desc.setter);
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden");
- } else {
- JS_FreeValue(ctx, desc.value);
- if (!(desc.flags & JS_PROP_WRITABLE) ||
- p->class_id == JS_CLASS_MODULE_NS) {
- read_only_error:
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);
- }
+ if (len > INT32_MAX)
+ return JS_ThrowRangeError(ctx, "invalid array length");
+ arr = JS_NewArray(ctx);
+ if (JS_IsException(arr))
+ return arr;
+ if (len > 0) {
+ p = JS_VALUE_GET_OBJ(arr);
+ if (expand_fast_array(ctx, p, len) < 0) {
+ JS_FreeValue(ctx, arr);
+ return JS_EXCEPTION;
}
- ret = JS_DefineProperty(ctx, this_obj, prop, val,
- JS_UNDEFINED, JS_UNDEFINED,
- JS_PROP_HAS_VALUE);
- JS_FreeValue(ctx, val);
- return ret;
+ p->u.array.count = len;
}
+ return arr;
+}
- ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,
- flags |
- JS_PROP_HAS_VALUE |
- JS_PROP_HAS_ENUMERABLE |
- JS_PROP_HAS_WRITABLE |
- JS_PROP_HAS_CONFIGURABLE |
- JS_PROP_C_W_E);
- JS_FreeValue(ctx, val);
- return ret;
+static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)
+{
+ JS_FreeValue(ctx, desc->getter);
+ JS_FreeValue(ctx, desc->setter);
+ JS_FreeValue(ctx, desc->value);
}
/* return -1 in case of exception or TRUE or FALSE. Warning: 'val' is
freed by the function. 'flags' is a bitmask of JS_PROP_NO_ADD,
JS_PROP_THROW or JS_PROP_THROW_STRICT. If JS_PROP_NO_ADD is set,
- the new property is not added and an error is raised. */
-int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValue val, int flags)
+ the new property is not added and an error is raised. 'this_obj' is
+ the receiver. If obj != this_obj, then obj must be an object
+ (Reflect.set case). */
+int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
+ JSAtom prop, JSValue val, JSValueConst this_obj, int flags)
{
JSObject *p, *p1;
JSShapeProperty *prs;
@@ -8492,25 +8488,37 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
#endif
tag = JS_VALUE_GET_TAG(this_obj);
if (unlikely(tag != JS_TAG_OBJECT)) {
- switch(tag) {
- case JS_TAG_NULL:
- JS_FreeValue(ctx, val);
- JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);
- return -1;
- case JS_TAG_UNDEFINED:
- JS_FreeValue(ctx, val);
- JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);
- return -1;
- default:
- /* even on a primitive type we can have setters on the prototype */
+ if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
p = NULL;
- p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, this_obj));
+ p1 = JS_VALUE_GET_OBJ(obj);
goto prototype_lookup;
+ } else {
+ switch(tag) {
+ case JS_TAG_NULL:
+ JS_FreeValue(ctx, val);
+ JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);
+ return -1;
+ case JS_TAG_UNDEFINED:
+ JS_FreeValue(ctx, val);
+ JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);
+ return -1;
+ default:
+ /* even on a primitive type we can have setters on the prototype */
+ p = NULL;
+ p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj));
+ goto prototype_lookup;
+ }
}
+ } else {
+ p = JS_VALUE_GET_OBJ(this_obj);
+ p1 = JS_VALUE_GET_OBJ(obj);
+ if (unlikely(p != p1))
+ goto retry2;
}
- p = JS_VALUE_GET_OBJ(this_obj);
-retry:
- prs = find_own_property(&pr, p, prop);
+
+ /* fast path if obj == this_obj */
+ retry:
+ prs = find_own_property(&pr, p1, prop);
if (prs) {
if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |
JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {
@@ -8543,12 +8551,11 @@ retry:
}
}
- p1 = p;
for(;;) {
if (p1->is_exotic) {
if (p1->fast_array) {
- if (JS_AtomIsTaggedInt(prop)) {
- uint32_t idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ uint32_t idx = __JS_AtomToUInt32(prop);
if (idx < p1->u.array.count) {
if (unlikely(p == p1))
return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags);
@@ -8567,11 +8574,19 @@ retry:
return -1;
}
typed_array_oob:
- val = JS_ToNumberFree(ctx, val);
- JS_FreeValue(ctx, val);
- if (JS_IsException(val))
- return -1;
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");
+ /* must convert the argument even if out of bound access */
+ if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY ||
+ p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) {
+ int64_t v;
+ if (JS_ToBigInt64Free(ctx, &v, val))
+ return -1;
+ } else {
+ val = JS_ToNumberFree(ctx, val);
+ JS_FreeValue(ctx, val);
+ if (JS_IsException(val))
+ return -1;
+ }
+ return TRUE;
}
}
} else {
@@ -8643,9 +8658,7 @@ retry:
return -1;
goto retry2;
} else if (!(prs->flags & JS_PROP_WRITABLE)) {
- read_only_prop:
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);
+ goto read_only_prop;
}
}
}
@@ -8666,17 +8679,57 @@ retry:
return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible");
}
- if (p->is_exotic) {
- if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&
- JS_AtomIsTaggedInt(prop)) {
- uint32_t idx = JS_AtomToUInt32(prop);
- if (idx == p->u.array.count) {
- /* fast case */
- return add_fast_array_element(ctx, p, val, flags);
+ if (likely(p == JS_VALUE_GET_OBJ(obj))) {
+ if (p->is_exotic) {
+ if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&
+ __JS_AtomIsTaggedInt(prop)) {
+ uint32_t idx = __JS_AtomToUInt32(prop);
+ if (idx == p->u.array.count) {
+ /* fast case */
+ return add_fast_array_element(ctx, p, val, flags);
+ } else {
+ goto generic_create_prop;
+ }
} else {
goto generic_create_prop;
}
} else {
+ pr = add_property(ctx, p, prop, JS_PROP_C_W_E);
+ if (unlikely(!pr)) {
+ JS_FreeValue(ctx, val);
+ return -1;
+ }
+ pr->u.value = val;
+ return TRUE;
+ }
+ } else {
+ /* generic case: modify the property in this_obj if it already exists */
+ ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
+ if (ret < 0) {
+ JS_FreeValue(ctx, val);
+ return ret;
+ }
+ if (ret) {
+ if (desc.flags & JS_PROP_GETSET) {
+ JS_FreeValue(ctx, desc.getter);
+ JS_FreeValue(ctx, desc.setter);
+ JS_FreeValue(ctx, val);
+ return JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden");
+ } else {
+ JS_FreeValue(ctx, desc.value);
+ if (!(desc.flags & JS_PROP_WRITABLE) ||
+ p->class_id == JS_CLASS_MODULE_NS) {
+ read_only_prop:
+ JS_FreeValue(ctx, val);
+ return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);
+ }
+ }
+ ret = JS_DefineProperty(ctx, this_obj, prop, val,
+ JS_UNDEFINED, JS_UNDEFINED,
+ JS_PROP_HAS_VALUE);
+ JS_FreeValue(ctx, val);
+ return ret;
+ } else {
generic_create_prop:
ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,
flags |
@@ -8689,14 +8742,6 @@ retry:
return ret;
}
}
-
- pr = add_property(ctx, p, prop, JS_PROP_C_W_E);
- if (unlikely(!pr)) {
- JS_FreeValue(ctx, val);
- return -1;
- }
- pr->u.value = val;
- return TRUE;
}
/* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */
@@ -8720,7 +8765,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
JSShape *sh1;
/* fast path to add an element to the array */
- if (idx != p->u.array.count ||
+ if (idx != (uint32_t)p->u.array.count ||
!p->fast_array || !p->extensible)
goto slow_path;
/* check if prototype chain has a numeric property */
@@ -8781,7 +8826,6 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
goto ta_out_of_bound;
p->u.array.u.uint32_ptr[idx] = v;
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
/* XXX: need specific conversion function */
@@ -8794,7 +8838,6 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
p->u.array.u.uint64_ptr[idx] = v;
}
break;
-#endif
case JS_CLASS_FLOAT32_ARRAY:
if (JS_ToFloat64Free(ctx, &d, val))
return -1;
@@ -8807,7 +8850,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
return -1;
if (unlikely(idx >= (uint32_t)p->u.array.count)) {
ta_out_of_bound:
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");
+ return TRUE;
}
p->u.array.u.double_ptr[idx] = d;
break;
@@ -8825,7 +8868,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
JS_FreeValue(ctx, val);
return -1;
}
- ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, flags);
+ ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, flags);
JS_FreeAtom(ctx, atom);
return ret;
}
@@ -8865,7 +8908,7 @@ int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
JSAtom atom;
int ret;
atom = JS_NewAtom(ctx, prop);
- ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, JS_PROP_THROW);
+ ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW);
JS_FreeAtom(ctx, atom);
return ret;
}
@@ -8895,8 +8938,8 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p,
uint32_t idx, len;
if (p->fast_array) {
- if (JS_AtomIsTaggedInt(prop)) {
- idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ idx = __JS_AtomToUInt32(prop);
if (idx == p->u.array.count) {
if (!p->extensible)
goto not_extensible;
@@ -9205,15 +9248,19 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
spaces. */
if (!js_same_value(ctx, val, *pr->u.var_ref->pvalue))
goto not_configurable;
+ } else {
+ /* update the reference */
+ set_value(ctx, pr->u.var_ref->pvalue,
+ JS_DupValue(ctx, val));
}
- /* update the reference */
- set_value(ctx, pr->u.var_ref->pvalue,
- JS_DupValue(ctx, val));
}
/* if writable is set to false, no longer a
reference (for mapped arguments) */
if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) {
JSValue val1;
+ if (p->class_id == JS_CLASS_MODULE_NS) {
+ return JS_ThrowTypeErrorOrFalse(ctx, flags, "module namespace properties have writable = false");
+ }
if (js_shape_prepare_update(ctx, p, &prs))
return -1;
val1 = JS_DupValue(ctx, *pr->u.var_ref->pvalue);
@@ -9272,8 +9319,8 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
uint32_t idx;
uint32_t prop_flags;
if (p->class_id == JS_CLASS_ARRAY) {
- if (JS_AtomIsTaggedInt(prop)) {
- idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ idx = __JS_AtomToUInt32(prop);
if (idx < p->u.array.count) {
prop_flags = get_prop_flags(flags, JS_PROP_C_W_E);
if (prop_flags != JS_PROP_C_W_E)
@@ -9296,7 +9343,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
JSValue num;
int ret;
- if (!JS_AtomIsTaggedInt(prop)) {
+ if (!__JS_AtomIsTaggedInt(prop)) {
/* slow path with to handle all numeric indexes */
num = JS_AtomIsNumericIndex1(ctx, prop);
if (JS_IsUndefined(num))
@@ -9317,12 +9364,12 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
if (ret) {
return JS_ThrowTypeErrorOrFalse(ctx, flags, "negative index in typed array");
}
- if (!JS_AtomIsTaggedInt(prop))
+ if (!__JS_AtomIsTaggedInt(prop))
goto typed_array_oob;
}
- idx = JS_AtomToUInt32(prop);
+ idx = __JS_AtomToUInt32(prop);
/* if the typed array is detached, p->u.array.count = 0 */
- if (idx >= typed_array_get_length(ctx, p)) {
+ if (idx >= p->u.array.count) {
typed_array_oob:
return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array");
}
@@ -9726,11 +9773,11 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
struct LookupResult result = ctx->scopeLookup(ctx, prop);
if (result.useResult) {
JS_FreeValue(ctx, result.value);
- return JS_SetPropertyInternal(ctx, result.scope, prop, val, flags);
+ return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, result.scope, flags);
}
}
- return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags);
+ return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, ctx->global_obj, flags);
}
/* return -1, FALSE or TRUE. return FALSE if not configurable or
@@ -9765,7 +9812,7 @@ int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int fl
if ((uint64_t)idx <= JS_ATOM_MAX_INT) {
/* fast path for fast arrays */
- return JS_DeleteProperty(ctx, obj, JS_AtomFromUInt32(idx), flags);
+ return JS_DeleteProperty(ctx, obj, __JS_AtomFromUInt32(idx), flags);
}
prop = JS_NewAtomInt64(ctx, idx);
if (prop == JS_ATOM_NULL)
@@ -9894,12 +9941,6 @@ void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id)
return p;
}
-#define HINT_STRING 0
-#define HINT_NUMBER 1
-#define HINT_NONE 2
-/* don't try Symbol.toPrimitive */
-#define HINT_FORCE_ORDINARY (1 << 4)
-
static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
{
int i;
@@ -9933,7 +9974,7 @@ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
break;
}
arg = JS_AtomToString(ctx, atom);
- ret = JS_CallFree(ctx, method, val, 1, &arg);
+ ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg);
JS_FreeValue(ctx, arg);
if (JS_IsException(ret))
goto exception;
@@ -10015,9 +10056,10 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val)
JS_FreeValue(ctx, val);
return ret;
}
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
BOOL ret;
@@ -10025,6 +10067,7 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val)
JS_FreeValue(ctx, val);
return ret;
}
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL:
{
JSBigDecimal *p = JS_VALUE_GET_PTR(val);
@@ -10094,12 +10137,13 @@ static inline int to_digit(int c)
}
/* XXX: remove */
-static double js_strtod(const char *p, int radix, BOOL is_float)
+static double js_strtod(const char *str, int radix, BOOL is_float)
{
double d;
int c;
if (!is_float || radix != 10) {
+ const char *p = str;
uint64_t n_max, n;
int int_exp, is_neg;
@@ -10126,6 +10170,8 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
if (n <= n_max) {
n = n * radix + c;
} else {
+ if (radix == 10)
+ goto strtod_case;
int_exp++;
}
p++;
@@ -10137,7 +10183,8 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
if (is_neg)
d = -d;
} else {
- d = safe_strtod(p, NULL);
+ strtod_case:
+ d = safe_strtod(str, NULL);
}
return d;
}
@@ -10155,15 +10202,16 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
#define ATOD_TYPE_MASK (3 << 7)
#define ATOD_TYPE_FLOAT64 (0 << 7)
#define ATOD_TYPE_BIG_INT (1 << 7)
+#ifdef CONFIG_BIGNUM
#define ATOD_TYPE_BIG_FLOAT (2 << 7)
#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)
+#endif
/* accept -0x1 */
#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)
-#ifdef CONFIG_BIGNUM
static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,
int radix, int flags, slimb_t *pexponent)
{
@@ -10179,10 +10227,15 @@ static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,
JS_FreeValue(ctx, val);
return JS_ThrowOutOfMemory(ctx);
}
+#ifdef CONFIG_BIGNUM
val = JS_CompactBigInt1(ctx, val, (flags & ATOD_MODE_BIGINT) != 0);
+#else
+ val = JS_CompactBigInt1(ctx, val, FALSE);
+#endif
return val;
}
+#ifdef CONFIG_BIGNUM
static JSValue js_string_to_bigfloat(JSContext *ctx, const char *buf,
int radix, int flags, slimb_t *pexponent)
{
@@ -10228,7 +10281,6 @@ static JSValue js_string_to_bigdecimal(JSContext *ctx, const char *buf,
}
return val;
}
-
#endif
/* return an exception in case of memory error. Return JS_NAN if
@@ -10303,8 +10355,11 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
} else {
no_radix_prefix:
if (!(flags & ATOD_INT_ONLY) &&
- (atod_type == ATOD_TYPE_FLOAT64 ||
- atod_type == ATOD_TYPE_BIG_FLOAT) &&
+ (atod_type == ATOD_TYPE_FLOAT64
+#ifdef CONFIG_BIGNUM
+ || atod_type == ATOD_TYPE_BIG_FLOAT
+#endif
+ ) &&
strstart(p, "Infinity", &p)) {
#ifdef CONFIG_BIGNUM
if (atod_type == ATOD_TYPE_BIG_FLOAT) {
@@ -10350,8 +10405,11 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) {
const char *p1 = p + 1;
is_float = TRUE;
- if (*p1 == '+' || *p1 == '-')
+ if (*p1 == '+') {
+ p1++;
+ } else if (*p1 == '-') {
p1++;
+ }
if (is_digit((uint8_t)*p1)) {
p = p1 + 1;
while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1])))
@@ -10381,36 +10439,40 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
}
buf[j] = '\0';
-#ifdef CONFIG_BIGNUM
if (flags & ATOD_ACCEPT_SUFFIX) {
if (*p == 'n') {
p++;
atod_type = ATOD_TYPE_BIG_INT;
- } else if (*p == 'l') {
+ } else
+#ifdef CONFIG_BIGNUM
+ if (*p == 'l') {
p++;
atod_type = ATOD_TYPE_BIG_FLOAT;
} else if (*p == 'm') {
p++;
atod_type = ATOD_TYPE_BIG_DECIMAL;
- } else {
- if (flags & ATOD_MODE_BIGINT) {
- if (!is_float)
- atod_type = ATOD_TYPE_BIG_INT;
- if (has_legacy_octal)
- goto fail;
- } else {
- if (is_float && radix != 10)
- goto fail;
- }
+ } else if (flags & ATOD_MODE_BIGINT) {
+ if (!is_float)
+ atod_type = ATOD_TYPE_BIG_INT;
+ if (has_legacy_octal)
+ goto fail;
+ } else
+#endif
+ {
+ if (is_float && radix != 10)
+ goto fail;
}
} else {
if (atod_type == ATOD_TYPE_FLOAT64) {
+#ifdef CONFIG_BIGNUM
if (flags & ATOD_MODE_BIGINT) {
if (!is_float)
atod_type = ATOD_TYPE_BIG_INT;
if (has_legacy_octal)
goto fail;
- } else {
+ } else
+#endif
+ {
if (is_float && radix != 10)
goto fail;
}
@@ -10431,6 +10493,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
goto fail;
val = ctx->rt->bigint_ops.from_string(ctx, buf, radix, flags, NULL);
break;
+#ifdef CONFIG_BIGNUM
case ATOD_TYPE_BIG_FLOAT:
if (has_legacy_octal)
goto fail;
@@ -10442,19 +10505,10 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
goto fail;
val = ctx->rt->bigdecimal_ops.from_string(ctx, buf, radix, flags, NULL);
break;
+#endif
default:
abort();
}
-#else
- {
- double d;
- (void)has_legacy_octal;
- if (is_float && radix != 10)
- goto fail;
- d = js_strtod(buf, radix, is_float);
- val = JS_NewFloat64(ctx, d);
- }
-#endif
done:
if (buf_allocated)
@@ -10492,18 +10546,18 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,
redo:
tag = JS_VALUE_GET_NORM_TAG(val);
switch(tag) {
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_DECIMAL:
+ case JS_TAG_BIG_INT:
if (flag != TON_FLAG_NUMERIC) {
JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert bigdecimal to number");
+ return JS_ThrowTypeError(ctx, "cannot convert bigint to number");
}
ret = val;
break;
- case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
+ case JS_TAG_BIG_DECIMAL:
if (flag != TON_FLAG_NUMERIC) {
JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert bigint to number");
+ return JS_ThrowTypeError(ctx, "cannot convert bigdecimal to number");
}
ret = val;
break;
@@ -10586,7 +10640,7 @@ static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val)
return JS_ToNumericFree(ctx, JS_DupValue(ctx, val));
}
-static warn_unused int JS_ToFloat64FreeImpl(JSContext *ctx, double *pres,
+static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,
JSValue val)
{
double d;
@@ -10605,9 +10659,10 @@ static warn_unused int JS_ToFloat64FreeImpl(JSContext *ctx, double *pres,
case JS_TAG_FLOAT64:
d = JS_VALUE_GET_FLOAT64(val);
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
/* XXX: there can be a double rounding issue with some
@@ -10617,7 +10672,6 @@ static warn_unused int JS_ToFloat64FreeImpl(JSContext *ctx, double *pres,
JS_FreeValue(ctx, val);
}
break;
-#endif
default:
abort();
}
@@ -10637,7 +10691,7 @@ static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val)
*pres = JS_VALUE_GET_FLOAT64(val);
return 0;
} else {
- return JS_ToFloat64FreeImpl(ctx, pres, val);
+ return __JS_ToFloat64Free(ctx, pres, val);
}
}
@@ -10652,7 +10706,7 @@ static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val)
}
/* same as JS_ToNumber() but return 0 in case of NaN/Undefined */
-static maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
+static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
{
uint32_t tag;
JSValue ret;
@@ -10685,6 +10739,10 @@ static maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
BOOL is_nan;
a = JS_ToBigFloat(ctx, &a_s, val);
+ if (!a) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
if (!bf_is_finite(a)) {
is_nan = bf_is_nan(a);
if (is_nan)
@@ -10815,7 +10873,7 @@ static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val)
} else {
if (d < INT64_MIN)
*pres = INT64_MIN;
- else if (d > INT64_MAX)
+ else if (d >= 0x1p63) /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */
*pres = INT64_MAX;
else
*pres = (int64_t)d;
@@ -11067,7 +11125,7 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)
return 0;
}
-static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
+static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
JSValue val, BOOL is_array_ctor)
{
uint32_t tag, len;
@@ -11085,9 +11143,10 @@ static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
len = v;
}
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
bf_t a;
@@ -11102,11 +11161,12 @@ static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
goto fail;
}
break;
-#endif
default:
if (JS_TAG_IS_FLOAT64(tag)) {
double d;
d = JS_VALUE_GET_FLOAT64(val);
+ if (!(d >= 0 && d <= UINT32_MAX))
+ goto fail;
len = (uint32_t)d;
if (len != d)
goto fail;
@@ -11169,7 +11229,7 @@ int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val)
/* convert a value to a length between 0 and MAX_SAFE_INTEGER.
return -1 for exception */
-static warn_unused int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
+static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
JSValue val)
{
int res = JS_ToInt64Clamp(ctx, plen, val, 0, MAX_SAFE_INTEGER, 0);
@@ -11206,13 +11266,13 @@ static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val)
u.d = JS_VALUE_GET_FLOAT64(val);
return (u.u64 >> 63);
}
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
/* Note: integer zeros are not necessarily positive */
return p->num.sign && !bf_is_zero(&p->num);
}
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
@@ -11231,8 +11291,6 @@ static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val)
}
}
-#ifdef CONFIG_BIGNUM
-
static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)
{
JSValue ret;
@@ -11262,6 +11320,8 @@ static JSValue js_bigint_to_string(JSContext *ctx, JSValueConst val)
return js_bigint_to_string1(ctx, val, 10);
}
+#ifdef CONFIG_BIGNUM
+
static JSValue js_ftoa(JSContext *ctx, JSValueConst val1, int radix,
limb_t prec, bf_flags_t flags)
{
@@ -11274,6 +11334,10 @@ static JSValue js_ftoa(JSContext *ctx, JSValueConst val1, int radix,
if (JS_IsException(val))
return val;
a = JS_ToBigFloat(ctx, &a_s, val);
+ if (!a) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
saved_sign = a->sign;
if (a->expn == BF_EXP_ZERO)
a->sign = 0;
@@ -11330,6 +11394,8 @@ static JSValue js_bigdecimal_to_string1(JSContext *ctx, JSValueConst val,
int saved_sign;
a = JS_ToBigDecimal(ctx, val);
+ if (!a)
+ return JS_EXCEPTION;
saved_sign = a->sign;
if (a->expn == BF_EXP_ZERO)
a->sign = 0;
@@ -11351,6 +11417,8 @@ static JSValue js_bigdecimal_to_string(JSContext *ctx, JSValueConst val)
#endif /* CONFIG_BIGNUM */
/* 2 <= base <= 36 */
+static char const digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
static char *i64toa(char *buf_end, int64_t n, unsigned int base)
{
char *q = buf_end;
@@ -11362,15 +11430,20 @@ static char *i64toa(char *buf_end, int64_t n, unsigned int base)
n = -n;
}
*--q = '\0';
- do {
- digit = (uint64_t)n % base;
- n = (uint64_t)n / base;
- if (digit < 10)
- digit += '0';
- else
- digit += 'a' - 10;
- *--q = digit;
- } while (n != 0);
+ if (base == 10) {
+ /* division by known base uses multiplication */
+ do {
+ digit = (uint64_t)n % 10;
+ n = (uint64_t)n / 10;
+ *--q = '0' + digit;
+ } while (n != 0);
+ } else {
+ do {
+ digit = (uint64_t)n % base;
+ n = (uint64_t)n / base;
+ *--q = digits[digit];
+ } while (n != 0);
+ }
if (is_neg)
*--q = '-';
return q;
@@ -11460,20 +11533,20 @@ static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf,
return n_digits;
}
-static int js_fcvt1(char *buf, int buf_size, double d, int n_digits,
+static int js_fcvt1(char (*buf)[JS_DTOA_BUF_SIZE], double d, int n_digits,
int rounding_mode)
{
int n;
if (rounding_mode != FE_TONEAREST)
fesetround(rounding_mode);
- n = snprintf(buf, buf_size, "%.*f", n_digits, d);
+ n = snprintf(*buf, sizeof(*buf), "%.*f", n_digits, d);
if (rounding_mode != FE_TONEAREST)
fesetround(FE_TONEAREST);
- assert(n < buf_size);
+ assert(n < sizeof(*buf));
return n;
}
-static void js_fcvt(char *buf, int buf_size, double d, int n_digits)
+static void js_fcvt(char (*buf)[JS_DTOA_BUF_SIZE], double d, int n_digits)
{
int rounding_mode;
rounding_mode = FE_TONEAREST;
@@ -11487,12 +11560,12 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits)
zero (RNDNA), but in printf the "ties" case is not specified
(for example it is RNDN for glibc, RNDNA for Windows), so we
must round manually. */
- n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_TONEAREST);
+ n1 = js_fcvt1(&buf1, d, n_digits + 1, FE_TONEAREST);
rounding_mode = FE_TONEAREST;
/* XXX: could use 2 digits to reduce the average running time */
if (buf1[n1 - 1] == '5') {
- n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_DOWNWARD);
- n2 = js_fcvt1(buf2, sizeof(buf2), d, n_digits + 1, FE_UPWARD);
+ n1 = js_fcvt1(&buf1, d, n_digits + 1, FE_DOWNWARD);
+ n2 = js_fcvt1(&buf2, d, n_digits + 1, FE_UPWARD);
if (n1 == n2 && memcmp(buf1, buf2, n1) == 0) {
/* exact result: round away from zero */
if (buf1[0] == '-')
@@ -11503,7 +11576,7 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits)
}
}
#endif /* CONFIG_PRINTF_RNDN */
- js_fcvt1(buf, buf_size, d, n_digits, rounding_mode);
+ js_fcvt1(buf, d, n_digits, rounding_mode);
}
/* radix != 10 is only supported with flags = JS_DTOA_VAR_FORMAT */
@@ -11519,33 +11592,35 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits)
/* XXX: slow and maybe not fully correct. Use libbf when it is fast enough.
XXX: radix != 10 is only supported for small integers
*/
-static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags)
+static void js_dtoa1(char (*buf)[JS_DTOA_BUF_SIZE], double d,
+ int radix, int n_digits, int flags)
{
char *q;
if (!isfinite(d)) {
if (isnan(d)) {
- strcpy(buf, "NaN");
+ pstrcpy(*buf, sizeof(*buf), "NaN");
+ } else if (d < 0) {
+ pstrcpy(*buf, sizeof(*buf), "-Infinity");
} else {
- q = buf;
- if (d < 0)
- *q++ = '-';
- strcpy(q, "Infinity");
+ pstrcpy(*buf, sizeof(*buf), "Infinity");
}
} else if (flags == JS_DTOA_VAR_FORMAT) {
int64_t i64;
char buf1[70], *ptr;
+ if (d > (double)MAX_SAFE_INTEGER || d < (double)-MAX_SAFE_INTEGER)
+ goto generic_conv;
i64 = (int64_t)d;
- if (d != i64 || i64 > MAX_SAFE_INTEGER || i64 < -MAX_SAFE_INTEGER)
+ if (d != i64)
goto generic_conv;
/* fast path for integers */
ptr = i64toa(buf1 + sizeof(buf1), i64, radix);
- strcpy(buf, ptr);
+ pstrcpy(*buf, sizeof(*buf), ptr);
} else {
if (d == 0.0)
d = 0.0; /* convert -0 to 0 */
if (flags == JS_DTOA_FRAC_FORMAT) {
- js_fcvt(buf, JS_DTOA_BUF_SIZE, d, n_digits);
+ js_fcvt(buf, d, n_digits);
} else {
char buf1[JS_DTOA_BUF_SIZE];
int sign, decpt, k, n, i, p, n_max;
@@ -11560,7 +11635,7 @@ static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags)
/* the number has k digits (k >= 1) */
k = js_ecvt(d, n_digits, &decpt, &sign, buf1, is_fixed);
n = decpt; /* d=10^(n-k)*(buf1) i.e. d= < x.yyyy 10^(n-1) */
- q = buf;
+ q = *buf;
if (sign)
*q++ = '-';
if (flags & JS_DTOA_FORCE_EXP)
@@ -11602,7 +11677,7 @@ static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags)
p = n - 1;
if (p >= 0)
*q++ = '+';
- sprintf(q, "%d", p);
+ snprintf(q, *buf + sizeof(*buf) - q, "%d", p);
}
}
}
@@ -11612,10 +11687,84 @@ static JSValue js_dtoa(JSContext *ctx,
double d, int radix, int n_digits, int flags)
{
char buf[JS_DTOA_BUF_SIZE];
- js_dtoa1(buf, d, radix, n_digits, flags);
+ js_dtoa1(&buf, d, radix, n_digits, flags);
return JS_NewString(ctx, buf);
}
+static JSValue js_dtoa_radix(JSContext *ctx, double d, int radix)
+{
+ char buf[2200], *ptr, *ptr2;
+ /* d is finite */
+ int sign = d < 0;
+ int digit;
+ double frac, d0;
+ int64_t n0 = 0;
+ d = fabs(d);
+ d0 = trunc(d);
+ frac = d - d0;
+ ptr = buf + 1100;
+ *ptr = '\0';
+ if (d0 <= MAX_SAFE_INTEGER) {
+ int64_t n = n0 = (int64_t)d0;
+ while (n >= radix) {
+ digit = n % radix;
+ n = n / radix;
+ *--ptr = digits[digit];
+ }
+ *--ptr = digits[(int)n];
+ } else {
+ /* no decimals */
+ while (d0 >= radix) {
+ digit = fmod(d0, radix);
+ d0 = trunc(d0 / radix);
+ if (d0 >= MAX_SAFE_INTEGER)
+ digit = 0;
+ *--ptr = digits[digit];
+ }
+ *--ptr = digits[(int)d0];
+ goto done;
+ }
+ if (frac != 0) {
+ double log2_radix = log2(radix);
+ double prec = 1023 + 51; // handle subnormals
+ ptr2 = buf + 1100;
+ *ptr2++ = '.';
+ while (frac != 0 && n0 <= MAX_SAFE_INTEGER/2 && prec > 0) {
+ frac *= radix;
+ digit = trunc(frac);
+ frac -= digit;
+ *ptr2++ = digits[digit];
+ n0 = n0 * radix + digit;
+ prec -= log2_radix;
+ }
+ *ptr2 = '\0';
+ if (frac * radix >= radix / 2) {
+ char nine = digits[radix - 1];
+ // round to closest
+ while (ptr2[-1] == nine)
+ *--ptr2 = '\0';
+ if (ptr2[-1] == '.') {
+ *--ptr2 = '\0';
+ while (ptr2[-1] == nine)
+ *--ptr2 = '0';
+ }
+ if (ptr2 - 1 == ptr)
+ *--ptr = '1';
+ else
+ ptr2[-1] += 1;
+ } else {
+ while (ptr2[-1] == '0')
+ *--ptr2 = '\0';
+ if (ptr2[-1] == '.')
+ *--ptr2 = '\0';
+ }
+ }
+done:
+ ptr[-1] = '-';
+ ptr -= sign;
+ return JS_NewString(ctx, ptr);
+}
+
JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToPropertyKey)
{
uint32_t tag;
@@ -11662,9 +11811,9 @@ JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToProperty
case JS_TAG_FLOAT64:
return js_dtoa(ctx, JS_VALUE_GET_FLOAT64(val), 10, 0,
JS_DTOA_VAR_FORMAT);
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
return ctx->rt->bigint_ops.to_string(ctx, val);
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
return ctx->rt->bigfloat_ops.to_string(ctx, val);
case JS_TAG_BIG_DECIMAL:
@@ -11756,7 +11905,7 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
goto fail;
break;
default:
- if (c < 32 || (c >= 0xd800 && c < 0xe000)) {
+ if (c < 32 || is_surrogate(c)) {
snprintf(buf, sizeof(buf), "\\u%04x", c);
if (string_buffer_puts8(b, buf))
goto fail;
@@ -11777,14 +11926,14 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
return JS_EXCEPTION;
}
-static maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)
+static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)
{
printf("%14s %4s %4s %14s %10s %s\n",
"ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");
}
/* for debug only: dump an object without side effect */
-static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
+static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
{
uint32_t i;
char atom_buf[ATOM_GET_STR_BUF_SIZE];
@@ -11825,10 +11974,8 @@ static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
case JS_CLASS_UINT16_ARRAY:
case JS_CLASS_INT32_ARRAY:
case JS_CLASS_UINT32_ARRAY:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
-#endif
case JS_CLASS_FLOAT32_ARRAY:
case JS_CLASS_FLOAT64_ARRAY:
{
@@ -11861,7 +12008,7 @@ static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
printf("[autoinit %p %d %p]",
(void *)js_autoinit_get_realm(pr),
js_autoinit_get_id(pr),
- pr->u.init.opaque);
+ (void *)pr->u.init.opaque);
} else {
JS_DumpValueShort(rt, pr->u.value);
}
@@ -11890,7 +12037,7 @@ static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
printf("\n");
}
-static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
+static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
{
if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
JS_DumpObject(rt, (JSObject *)p);
@@ -11922,7 +12069,7 @@ static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
}
}
-static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
+static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
JSValueConst val)
{
uint32_t tag = JS_VALUE_GET_NORM_TAG(val);
@@ -11955,7 +12102,6 @@ static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
case JS_TAG_FLOAT64:
printf("%.14g", JS_VALUE_GET_FLOAT64(val));
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
@@ -11966,6 +12112,7 @@ static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
bf_realloc(&rt->bf_ctx, str, 0);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
@@ -12027,13 +12174,13 @@ static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
}
}
-static maybe_unused void JS_DumpValue(JSContext *ctx,
+static __maybe_unused void JS_DumpValue(JSContext *ctx,
JSValueConst val)
{
JS_DumpValueShort(ctx->rt, val);
}
-static maybe_unused void JS_PrintValue(JSContext *ctx,
+static __maybe_unused void JS_PrintValue(JSContext *ctx,
const char *str,
JSValueConst val)
{
@@ -12043,15 +12190,14 @@ static maybe_unused void JS_PrintValue(JSContext *ctx,
}
/* return -1 if exception (proxy case) or TRUE/FALSE */
+// TODO: should take flags to make proxy resolution and exceptions optional
int JS_IsArray(JSContext *ctx, JSValueConst val)
{
- JSObject *p;
+ if (js_resolve_proxy(ctx, &val, TRUE))
+ return -1;
if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) {
- p = JS_VALUE_GET_OBJ(val);
- if (unlikely(p->class_id == JS_CLASS_PROXY))
- return js_proxy_isArray(ctx, val);
- else
- return p->class_id == JS_CLASS_ARRAY;
+ JSObject *p = JS_VALUE_GET_OBJ(val);
+ return p->class_id == JS_CLASS_ARRAY;
} else {
return FALSE;
}
@@ -12067,8 +12213,6 @@ static double js_pow(double a, double b)
}
}
-#ifdef CONFIG_BIGNUM
-
JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v)
{
JSValue val;
@@ -12113,70 +12257,6 @@ JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
return val;
}
-/* if the returned bigfloat is allocated it is equal to
- 'buf'. Otherwise it is a pointer to the bigfloat in 'val'. Return
- NULL in case of error. */
-static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val)
-{
- uint32_t tag;
- bf_t *r;
- JSBigFloat *p;
-
- tag = JS_VALUE_GET_NORM_TAG(val);
- switch(tag) {
- case JS_TAG_INT:
- case JS_TAG_BOOL:
- case JS_TAG_NULL:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- if (bf_set_si(r, JS_VALUE_GET_INT(val)))
- goto fail;
- break;
- case JS_TAG_FLOAT64:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) {
- fail:
- bf_delete(r);
- return NULL;
- }
- break;
- case JS_TAG_BIG_INT:
- case JS_TAG_BIG_FLOAT:
- p = JS_VALUE_GET_PTR(val);
- r = &p->num;
- break;
- case JS_TAG_UNDEFINED:
- default:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- bf_set_nan(r);
- break;
- }
- return r;
-}
-
-/* return NULL if invalid type */
-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:
- p = JS_VALUE_GET_PTR(val);
- r = &p->num;
- break;
- default:
- JS_ThrowTypeError(ctx, "bigdecimal expected");
- r = NULL;
- break;
- }
- return r;
-}
-
/* return NaN if bad bigint literal */
static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)
{
@@ -12194,8 +12274,10 @@ static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)
val = JS_NewBigInt64(ctx, 0);
} else {
flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT;
+#ifdef CONFIG_BIGNUM
if (is_math_mode(ctx))
flags |= ATOD_MODE_BIGINT;
+#endif
val = js_atof(ctx, p, &p, 0, flags);
p += skip_spaces(p);
if (!JS_IsException(val)) {
@@ -12256,6 +12338,7 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)
p = JS_VALUE_GET_PTR(val);
r = &p->num;
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
if (!is_math_mode(ctx))
goto fail;
@@ -12268,6 +12351,7 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)
bf_rint(r, BF_RNDZ);
JS_FreeValue(ctx, val);
break;
+#endif
case JS_TAG_STRING:
val = JS_StringToBigIntErr(ctx, val);
if (JS_IsException(val))
@@ -12328,7 +12412,7 @@ static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf)
} else {
JSBigFloat *p = (JSBigFloat *)((uint8_t *)a -
offsetof(JSBigFloat, num));
- JS_FreeValue(ctx, JS_MKPTR(JS_TAG_BIG_FLOAT, p));
+ JS_FreeValue(ctx, JS_MKPTR(JS_TAG_BIG_INT, p));
}
}
@@ -12363,28 +12447,6 @@ static JSBigFloat *js_new_bf(JSContext *ctx)
return p;
}
-static JSValue JS_NewBigFloat(JSContext *ctx)
-{
- JSBigFloat *p;
- p = js_malloc(ctx, sizeof(*p));
- if (!p)
- return JS_EXCEPTION;
- p->header.ref_count = 1;
- bf_init(ctx->bf_ctx, &p->num);
- return JS_MKPTR(JS_TAG_BIG_FLOAT, p);
-}
-
-static JSValue JS_NewBigDecimal(JSContext *ctx)
-{
- JSBigDecimal *p;
- p = js_malloc(ctx, sizeof(*p));
- if (!p)
- return JS_EXCEPTION;
- p->header.ref_count = 1;
- bfdec_init(ctx->bf_ctx, &p->num);
- return JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
-}
-
static JSValue JS_NewBigInt(JSContext *ctx)
{
JSBigFloat *p;
@@ -12426,6 +12488,110 @@ static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val)
return JS_CompactBigInt1(ctx, val, is_math_mode(ctx));
}
+static JSValue throw_bf_exception(JSContext *ctx, int status)
+{
+ const char *str;
+ if (status & BF_ST_MEM_ERROR)
+ return JS_ThrowOutOfMemory(ctx);
+ if (status & BF_ST_DIVIDE_ZERO) {
+ str = "division by zero";
+ } else if (status & BF_ST_INVALID_OP) {
+ str = "invalid operation";
+ } else {
+ str = "integer overflow";
+ }
+ return JS_ThrowRangeError(ctx, "%s", str);
+}
+
+/* if the returned bigfloat is allocated it is equal to
+ 'buf'. Otherwise it is a pointer to the bigfloat in 'val'. Return
+ NULL in case of error. */
+static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val)
+{
+ uint32_t tag;
+ bf_t *r;
+ JSBigFloat *p;
+
+ tag = JS_VALUE_GET_NORM_TAG(val);
+ switch(tag) {
+ case JS_TAG_INT:
+ case JS_TAG_BOOL:
+ case JS_TAG_NULL:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ if (bf_set_si(r, JS_VALUE_GET_INT(val)))
+ goto fail;
+ break;
+ case JS_TAG_FLOAT64:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) {
+ fail:
+ bf_delete(r);
+ return NULL;
+ }
+ break;
+ case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
+ case JS_TAG_BIG_FLOAT:
+#endif
+ p = JS_VALUE_GET_PTR(val);
+ r = &p->num;
+ break;
+ case JS_TAG_UNDEFINED:
+ default:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ bf_set_nan(r);
+ break;
+ }
+ return r;
+}
+
+#ifdef CONFIG_BIGNUM
+/* return NULL if invalid type */
+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:
+ p = JS_VALUE_GET_PTR(val);
+ r = &p->num;
+ break;
+ default:
+ JS_ThrowTypeError(ctx, "bigdecimal expected");
+ r = NULL;
+ break;
+ }
+ return r;
+}
+
+static JSValue JS_NewBigFloat(JSContext *ctx)
+{
+ JSBigFloat *p;
+ p = js_malloc(ctx, sizeof(*p));
+ if (!p)
+ return JS_EXCEPTION;
+ p->header.ref_count = 1;
+ bf_init(ctx->bf_ctx, &p->num);
+ return JS_MKPTR(JS_TAG_BIG_FLOAT, p);
+}
+
+static JSValue JS_NewBigDecimal(JSContext *ctx)
+{
+ JSBigDecimal *p;
+ p = js_malloc(ctx, sizeof(*p));
+ if (!p)
+ return JS_EXCEPTION;
+ p->header.ref_count = 1;
+ bfdec_init(ctx->bf_ctx, &p->num);
+ return JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
+}
+
/* must be kept in sync with JSOverloadableOperatorEnum */
/* XXX: use atoms ? */
static const char js_overloadable_operator_names[JS_OVOP_COUNT][4] = {
@@ -12516,7 +12682,7 @@ static JSObject *find_binary_op(JSBinaryOperatorDef *def,
/* return -1 if exception, 0 if no operator overloading, 1 if
overloaded operator called */
-static WARN_UNUSED int js_call_binary_op_fallback(JSContext *ctx,
+static __exception int js_call_binary_op_fallback(JSContext *ctx,
JSValue *pret,
JSValueConst op1,
JSValueConst op2,
@@ -12645,7 +12811,7 @@ static WARN_UNUSED int js_call_binary_op_fallback(JSContext *ctx,
/* try to call the operation on the operatorSet field of 'obj'. Only
used for "/" and "**" on the BigInt prototype in math mode */
-static WARN_UNUSED int js_call_binary_op_simple(JSContext *ctx,
+static __exception int js_call_binary_op_simple(JSContext *ctx,
JSValue *pret,
JSValueConst obj,
JSValueConst op1,
@@ -12702,7 +12868,7 @@ static WARN_UNUSED int js_call_binary_op_simple(JSContext *ctx,
/* return -1 if exception, 0 if no operator overloading, 1 if
overloaded operator called */
-static WARN_UNUSED int js_call_unary_op_fallback(JSContext *ctx,
+static __exception int js_call_unary_op_fallback(JSContext *ctx,
JSValue *pret,
JSValueConst op1,
OPCodeEnum op)
@@ -12749,46 +12915,37 @@ static WARN_UNUSED int js_call_unary_op_fallback(JSContext *ctx,
return -1;
}
-static JSValue throw_bf_exception(JSContext *ctx, int status)
-{
- const char *str;
- if (status & BF_ST_MEM_ERROR)
- return JS_ThrowOutOfMemory(ctx);
- if (status & BF_ST_DIVIDE_ZERO) {
- str = "division by zero";
- } else if (status & BF_ST_INVALID_OP) {
- str = "invalid operation";
- } else {
- str = "integer overflow";
- }
- return JS_ThrowRangeError(ctx, "%s", str);
-}
-
-static int js_unary_arith_bigint(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
+static int js_unary_arith_bigfloat(JSContext *ctx,
+ JSValue *pres, OPCodeEnum op, JSValue op1)
{
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_ThrowTypeError(ctx, "bigfloat argument with unary +");
JS_FreeValue(ctx, op1);
return -1;
}
- res = JS_NewBigInt(ctx);
+
+ res = JS_NewBigFloat(ctx);
if (JS_IsException(res)) {
JS_FreeValue(ctx, op1);
return -1;
}
- r = JS_GetBigInt(res);
- a = JS_ToBigInt(ctx, &a_s, op1);
+ r = JS_GetBigFloat(res);
+ a = JS_ToBigFloat(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, res);
+ JS_FreeValue(ctx, op1);
+ return -1;
+ }
ret = 0;
switch(op) {
case OP_inc:
case OP_dec:
v = 2 * (op - OP_dec) - 1;
- ret = bf_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
+ ret = bf_add_si(r, a, v, ctx->fp_env.prec, ctx->fp_env.flags);
break;
case OP_plus:
ret = bf_set(r, a);
@@ -12797,66 +12954,65 @@ static int js_unary_arith_bigint(JSContext *ctx,
ret = bf_set(r, a);
bf_neg(r);
break;
- case OP_not:
- ret = bf_add_si(r, a, 1, BF_PREC_INF, BF_RNDZ);
- bf_neg(r);
- break;
default:
abort();
}
- JS_FreeBigInt(ctx, a, &a_s);
+ if (a == &a_s)
+ bf_delete(a);
JS_FreeValue(ctx, op1);
- if (unlikely(ret)) {
+ if (unlikely(ret & BF_ST_MEM_ERROR)) {
JS_FreeValue(ctx, res);
throw_bf_exception(ctx, ret);
return -1;
}
- res = JS_CompactBigInt(ctx, res);
*pres = res;
return 0;
}
-static int js_unary_arith_bigfloat(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
+static int js_unary_arith_bigdecimal(JSContext *ctx,
+ JSValue *pres, OPCodeEnum op, JSValue op1)
{
- bf_t a_s, *r, *a;
+ bfdec_t *r, *a;
int ret, v;
JSValue res;
if (op == OP_plus && !is_math_mode(ctx)) {
- JS_ThrowTypeError(ctx, "bigfloat argument with unary +");
+ JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");
JS_FreeValue(ctx, op1);
return -1;
}
- res = JS_NewBigFloat(ctx);
+ res = JS_NewBigDecimal(ctx);
if (JS_IsException(res)) {
JS_FreeValue(ctx, op1);
return -1;
}
- r = JS_GetBigFloat(res);
- a = JS_ToBigFloat(ctx, &a_s, op1);
+ r = JS_GetBigDecimal(res);
+ a = JS_ToBigDecimal(ctx, op1);
+ if (!a) {
+ JS_FreeValue(ctx, res);
+ JS_FreeValue(ctx, op1);
+ return -1;
+ }
ret = 0;
switch(op) {
case OP_inc:
case OP_dec:
v = 2 * (op - OP_dec) - 1;
- ret = bf_add_si(r, a, v, ctx->fp_env.prec, ctx->fp_env.flags);
+ ret = bfdec_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
break;
case OP_plus:
- ret = bf_set(r, a);
+ ret = bfdec_set(r, a);
break;
case OP_neg:
- ret = bf_set(r, a);
- bf_neg(r);
+ ret = bfdec_set(r, a);
+ bfdec_neg(r);
break;
default:
abort();
}
- if (a == &a_s)
- bf_delete(a);
JS_FreeValue(ctx, op1);
- if (unlikely(ret & BF_ST_MEM_ERROR)) {
+ if (unlikely(ret)) {
JS_FreeValue(ctx, res);
throw_bf_exception(ctx, ret);
return -1;
@@ -12865,67 +13021,81 @@ static int js_unary_arith_bigfloat(JSContext *ctx,
return 0;
}
-static int js_unary_arith_bigdecimal(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
+#endif /* CONFIG_BIGNUM */
+
+static int js_unary_arith_bigint(JSContext *ctx,
+ JSValue *pres, OPCodeEnum op, JSValue op1)
{
- bfdec_t *r, *a;
+ bf_t a_s, *r, *a;
int ret, v;
JSValue res;
if (op == OP_plus && !is_math_mode(ctx)) {
- JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");
+ JS_ThrowTypeError(ctx, "bigint argument with unary +");
JS_FreeValue(ctx, op1);
return -1;
}
-
- res = JS_NewBigDecimal(ctx);
+ res = JS_NewBigInt(ctx);
if (JS_IsException(res)) {
JS_FreeValue(ctx, op1);
return -1;
}
- r = JS_GetBigDecimal(res);
- a = JS_ToBigDecimal(ctx, op1);
+ r = JS_GetBigInt(res);
+ a = JS_ToBigInt(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, res);
+ JS_FreeValue(ctx, op1);
+ return -1;
+ }
ret = 0;
switch(op) {
case OP_inc:
case OP_dec:
v = 2 * (op - OP_dec) - 1;
- ret = bfdec_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
+ ret = bf_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
break;
case OP_plus:
- ret = bfdec_set(r, a);
+ ret = bf_set(r, a);
break;
case OP_neg:
- ret = bfdec_set(r, a);
- bfdec_neg(r);
+ ret = bf_set(r, a);
+ bf_neg(r);
+ break;
+ case OP_not:
+ ret = bf_add_si(r, a, 1, BF_PREC_INF, BF_RNDZ);
+ bf_neg(r);
break;
default:
abort();
}
+ JS_FreeBigInt(ctx, a, &a_s);
JS_FreeValue(ctx, op1);
if (unlikely(ret)) {
JS_FreeValue(ctx, res);
throw_bf_exception(ctx, ret);
return -1;
}
+ res = JS_CompactBigInt(ctx, res);
*pres = res;
return 0;
}
-static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
+static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
JSValue *sp,
OPCodeEnum op)
{
- JSValue op1, val;
- int v, ret;
+ JSValue op1;
+ int v;
uint32_t tag;
op1 = sp[-1];
/* fast path for float64 */
if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)))
goto handle_float64;
+#ifdef CONFIG_BIGNUM
if (JS_IsObject(op1)) {
- ret = js_call_unary_op_fallback(ctx, &val, op1, op);
+ JSValue val;
+ int ret = js_call_unary_op_fallback(ctx, &val, op1, op);
if (ret < 0)
return -1;
if (ret) {
@@ -12934,7 +13104,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
return 0;
}
}
-
+#endif
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1))
goto exception;
@@ -12954,7 +13124,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
break;
case OP_neg:
if (v64 == 0) {
- sp[-1] = __JS_NewFloat64(ctx, -0.0);
+ sp[-1] = JS_NewFloat64(ctx, -0.0);
return 0;
} else {
v64 = -v64;
@@ -12971,6 +13141,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, op, op1))
goto exception;
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
if (ctx->rt->bigfloat_ops.unary_arith(ctx, sp - 1, op, op1))
goto exception;
@@ -12979,6 +13150,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
if (ctx->rt->bigdecimal_ops.unary_arith(ctx, sp - 1, op, op1))
goto exception;
break;
+#endif
default:
handle_float64:
{
@@ -13000,7 +13172,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
default:
abort();
}
- sp[-1] = __JS_NewFloat64(ctx, d);
+ sp[-1] = JS_NewFloat64(ctx, d);
}
break;
}
@@ -13010,7 +13182,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
return -1;
}
-static WARN_UNUSED int js_post_inc_slow(JSContext *ctx,
+static __exception int js_post_inc_slow(JSContext *ctx,
JSValue *sp, OPCodeEnum op)
{
JSValue op1;
@@ -13029,12 +13201,13 @@ static WARN_UNUSED int js_post_inc_slow(JSContext *ctx,
static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
{
- JSValue op1, val;
- int ret;
+ JSValue op1;
op1 = sp[-1];
+#ifdef CONFIG_BIGNUM
if (JS_IsObject(op1)) {
- ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not);
+ JSValue val;
+ int ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not);
if (ret < 0)
return -1;
if (ret) {
@@ -13043,7 +13216,7 @@ static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
return 0;
}
}
-
+#endif
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1))
goto exception;
@@ -13062,67 +13235,6 @@ static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
return -1;
}
-static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op,
- JSValue *pres, JSValue op1, JSValue op2)
-{
- 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);
- JS_FreeValue(ctx, op2);
- return -1;
- }
- r = JS_GetBigFloat(res);
- a = JS_ToBigFloat(ctx, &a_s, op1);
- b = JS_ToBigFloat(ctx, &b_s, op2);
- bf_init(ctx->bf_ctx, r);
- switch(op) {
- case OP_add:
- ret = bf_add(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_sub:
- ret = bf_sub(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_mul:
- ret = bf_mul(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_div:
- ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_math_mod:
- /* Euclidian remainder */
- ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
- BF_DIVREM_EUCLIDIAN);
- break;
- case OP_mod:
- ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
- BF_RNDZ);
- break;
- case OP_pow:
- ret = bf_pow(r, a, b, ctx->fp_env.prec,
- ctx->fp_env.flags | BF_POW_JS_QUIRKS);
- break;
- default:
- abort();
- }
- if (a == &a_s)
- bf_delete(a);
- if (b == &b_s)
- bf_delete(b);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (unlikely(ret & BF_ST_MEM_ERROR)) {
- JS_FreeValue(ctx, res);
- throw_bf_exception(ctx, ret);
- return -1;
- }
- *pres = res;
- return 0;
-}
-
static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
JSValue *pres, JSValue op1, JSValue op2)
{
@@ -13164,11 +13276,13 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
goto math_mode_div_pow;
}
break;
+#ifdef CONFIG_BIGNUM
case OP_math_mod:
/* Euclidian remainder */
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
BF_DIVREM_EUCLIDIAN) & BF_ST_INVALID_OP;
break;
+#endif
case OP_mod:
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
BF_RNDZ) & BF_ST_INVALID_OP;
@@ -13179,6 +13293,7 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
ret = BF_ST_INVALID_OP;
} else {
math_mode_div_pow:
+#ifdef CONFIG_BIGNUM
JS_FreeValue(ctx, res);
ret = js_call_binary_op_simple(ctx, &res, ctx->class_proto[JS_CLASS_BIG_INT], op1, op2, op);
if (ret != 0) {
@@ -13219,6 +13334,9 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
}
*pres = res;
return 0;
+#else
+ abort();
+#endif
}
} else {
ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUIRKS);
@@ -13278,6 +13396,79 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
return -1;
}
+#ifdef CONFIG_BIGNUM
+static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op,
+ JSValue *pres, JSValue op1, JSValue op2)
+{
+ bf_t a_s, b_s, *r, *a, *b;
+ int ret;
+ JSValue res;
+
+ res = JS_NewBigFloat(ctx);
+ if (JS_IsException(res))
+ goto fail;
+ r = JS_GetBigFloat(res);
+ a = JS_ToBigFloat(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, res);
+ goto fail;
+ }
+ b = JS_ToBigFloat(ctx, &b_s, op2);
+ if (!b) {
+ if (a == &a_s)
+ bf_delete(a);
+ JS_FreeValue(ctx, res);
+ goto fail;
+ }
+ bf_init(ctx->bf_ctx, r);
+ switch(op) {
+ case OP_add:
+ ret = bf_add(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
+ break;
+ case OP_sub:
+ ret = bf_sub(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
+ break;
+ case OP_mul:
+ ret = bf_mul(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
+ break;
+ case OP_div:
+ ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
+ break;
+ case OP_math_mod:
+ /* Euclidian remainder */
+ ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
+ BF_DIVREM_EUCLIDIAN);
+ break;
+ case OP_mod:
+ ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
+ BF_RNDZ);
+ break;
+ case OP_pow:
+ ret = bf_pow(r, a, b, ctx->fp_env.prec,
+ ctx->fp_env.flags | BF_POW_JS_QUIRKS);
+ break;
+ default:
+ abort();
+ }
+ if (a == &a_s)
+ bf_delete(a);
+ if (b == &b_s)
+ bf_delete(b);
+ JS_FreeValue(ctx, op1);
+ JS_FreeValue(ctx, op2);
+ if (unlikely(ret & BF_ST_MEM_ERROR)) {
+ JS_FreeValue(ctx, res);
+ throw_bf_exception(ctx, ret);
+ return -1;
+ }
+ *pres = res;
+ return 0;
+ fail:
+ JS_FreeValue(ctx, op1);
+ JS_FreeValue(ctx, op2);
+ return -1;
+}
+
/* b must be a positive integer */
static int js_bfdec_pow(bfdec_t *r, const bfdec_t *a, const bfdec_t *b)
{
@@ -13364,13 +13555,13 @@ static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op,
JS_FreeValue(ctx, op2);
return -1;
}
+#endif /* CONFIG_BIGNUM */
-static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
+static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
OPCodeEnum op)
{
- JSValue op1, op2, res;
+ JSValue op1, op2;
uint32_t tag1, tag2;
- int ret;
double d1, d2;
op1 = sp[-2];
@@ -13384,12 +13575,14 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
goto handle_float64;
}
+#ifdef CONFIG_BIGNUM
/* try to call an overloaded operator */
if ((tag1 == JS_TAG_OBJECT &&
(tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
(tag2 == JS_TAG_OBJECT &&
(tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
- ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
+ JSValue res;
+ int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
if (ret != 0) {
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -13401,6 +13594,7 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
}
}
}
+#endif
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1)) {
@@ -13430,15 +13624,16 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
(v < -MAX_SAFE_INTEGER || v > MAX_SAFE_INTEGER))
goto handle_bigint;
if (v == 0 && (v1 | v2) < 0) {
- sp[-2] = __JS_NewFloat64(ctx, -0.0);
+ sp[-2] = JS_NewFloat64(ctx, -0.0);
return 0;
}
break;
case OP_div:
if (is_math_mode(ctx))
goto handle_bigint;
- sp[-2] = __JS_NewFloat64(ctx, (double)v1 / (double)v2);
+ sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);
return 0;
+#ifdef CONFIG_BIGNUM
case OP_math_mod:
if (unlikely(v2 == 0)) {
throw_bf_exception(ctx, BF_ST_DIVIDE_ZERO);
@@ -13452,6 +13647,7 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
v += v2;
}
break;
+#endif
case OP_mod:
if (v1 < 0 || v2 <= 0) {
sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2));
@@ -13472,13 +13668,17 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
abort();
}
sp[-2] = JS_NewInt64(ctx, v);
- } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
+ } else
+#ifdef CONFIG_BIGNUM
+ if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
if (ctx->rt->bigdecimal_ops.binary_arith(ctx, op, sp - 2, op1, op2))
goto exception;
} else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2))
goto exception;
- } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
+ } else
+#endif
+ if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
handle_bigint:
if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
goto exception;
@@ -13507,6 +13707,7 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
case OP_mod:
dr = fmod(d1, d2);
break;
+#ifdef CONFIG_BIGNUM
case OP_math_mod:
d2 = fabs(d2);
dr = fmod(d1, d2);
@@ -13514,13 +13715,14 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
if (dr < 0)
dr += d2;
break;
+#endif
case OP_pow:
dr = js_pow(d1, d2);
break;
default:
abort();
}
- sp[-2] = __JS_NewFloat64(ctx, dr);
+ sp[-2] = JS_NewFloat64(ctx, dr);
}
return 0;
exception:
@@ -13529,11 +13731,10 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
return -1;
}
-static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
+static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
{
- JSValue op1, op2, res;
+ JSValue op1, op2;
uint32_t tag1, tag2;
- int ret;
op1 = sp[-2];
op2 = sp[-1];
@@ -13545,11 +13746,12 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
double d1, d2;
d1 = JS_VALUE_GET_FLOAT64(op1);
d2 = JS_VALUE_GET_FLOAT64(op2);
- sp[-2] = __JS_NewFloat64(ctx, d1 + d2);
+ sp[-2] = JS_NewFloat64(ctx, d1 + d2);
return 0;
}
if (tag1 == JS_TAG_OBJECT || tag2 == JS_TAG_OBJECT) {
+#ifdef CONFIG_BIGNUM
/* try to call an overloaded operator */
if ((tag1 == JS_TAG_OBJECT &&
(tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED &&
@@ -13557,8 +13759,9 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
(tag2 == JS_TAG_OBJECT &&
(tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED &&
tag1 != JS_TAG_STRING))) {
- ret = js_call_binary_op_fallback(ctx, &res, op1, op2, OP_add,
- FALSE, HINT_NONE);
+ JSValue res;
+ int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, OP_add,
+ FALSE, HINT_NONE);
if (ret != 0) {
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -13570,7 +13773,7 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
}
}
}
-
+#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -13613,13 +13816,17 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
v2 = JS_VALUE_GET_INT(op2);
v = (int64_t)v1 + (int64_t)v2;
sp[-2] = JS_NewInt64(ctx, v);
- } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
+ } else
+#ifdef CONFIG_BIGNUM
+ if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
if (ctx->rt->bigdecimal_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
goto exception;
} else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
goto exception;
- } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
+ } else
+#endif
+ if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
handle_bigint:
if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
goto exception;
@@ -13634,7 +13841,7 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
goto exception;
if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))
goto handle_bigint;
- sp[-2] = __JS_NewFloat64(ctx, d1 + d2);
+ sp[-2] = JS_NewFloat64(ctx, d1 + d2);
}
return 0;
exception:
@@ -13643,12 +13850,11 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
return -1;
}
-static no_inline WARN_UNUSED int js_binary_logic_slow(JSContext *ctx,
+static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
JSValue *sp,
OPCodeEnum op)
{
- JSValue op1, op2, res;
- int ret;
+ JSValue op1, op2;
uint32_t tag1, tag2;
uint32_t v1, v2, r;
@@ -13657,12 +13863,14 @@ static no_inline WARN_UNUSED int js_binary_logic_slow(JSContext *ctx,
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
+#ifdef CONFIG_BIGNUM
/* try to call an overloaded operator */
if ((tag1 == JS_TAG_OBJECT &&
(tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
(tag2 == JS_TAG_OBJECT &&
(tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
- ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
+ JSValue res;
+ int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
if (ret != 0) {
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -13674,6 +13882,7 @@ static no_inline WARN_UNUSED int js_binary_logic_slow(JSContext *ctx,
}
}
}
+#endif
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1)) {
@@ -13784,6 +13993,7 @@ static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op,
return res;
}
+#ifdef CONFIG_BIGNUM
static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,
JSValue op1, JSValue op2)
{
@@ -13803,8 +14013,8 @@ static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,
JS_FreeValue(ctx, op1);
return -1;
}
- a = JS_ToBigDecimal(ctx, op1);
- b = JS_ToBigDecimal(ctx, op2);
+ a = JS_ToBigDecimal(ctx, op1); /* cannot fail */
+ b = JS_ToBigDecimal(ctx, op2); /* cannot fail */
switch(op) {
case OP_lt:
@@ -13829,11 +14039,12 @@ static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,
JS_FreeValue(ctx, op2);
return res;
}
+#endif /* !CONFIG_BIGNUM */
static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
OPCodeEnum op)
{
- JSValue op1, op2, ret;
+ JSValue op1, op2;
int res;
uint32_t tag1, tag2;
@@ -13841,11 +14052,13 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
op2 = sp[-1];
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
+#ifdef CONFIG_BIGNUM
/* try to call an overloaded operator */
if ((tag1 == JS_TAG_OBJECT &&
(tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
(tag2 == JS_TAG_OBJECT &&
(tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
+ JSValue ret;
res = js_call_binary_op_fallback(ctx, &ret, op1, op2, op,
FALSE, HINT_NUMBER);
if (res != 0) {
@@ -13859,6 +14072,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
}
}
}
+#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -13933,6 +14147,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
+#ifdef CONFIG_BIGNUM
if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2);
if (res < 0)
@@ -13941,7 +14156,9 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2);
if (res < 0)
goto exception;
- } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
+ } else
+#endif
+ if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);
if (res < 0)
goto exception;
@@ -13989,14 +14206,20 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
static BOOL tag_is_number(uint32_t tag)
{
return (tag == JS_TAG_INT || tag == JS_TAG_BIG_INT ||
- tag == JS_TAG_FLOAT64 || tag == JS_TAG_BIG_FLOAT ||
- tag == JS_TAG_BIG_DECIMAL);
+ tag == JS_TAG_FLOAT64
+#ifdef CONFIG_BIGNUM
+ || tag == JS_TAG_BIG_FLOAT || tag == JS_TAG_BIG_DECIMAL
+#endif
+ );
}
-static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
+static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
BOOL is_neq)
{
- JSValue op1, op2, ret;
+ JSValue op1, op2;
+#ifdef CONFIG_BIGNUM
+ JSValue ret;
+#endif
int res;
uint32_t tag1, tag2;
@@ -14024,7 +14247,9 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
d2 = JS_VALUE_GET_INT(op2);
}
res = (d1 == d2);
- } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
+ } else
+#ifdef CONFIG_BIGNUM
+ if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
res = ctx->rt->bigdecimal_ops.compare(ctx, OP_eq, op1, op2);
if (res < 0)
goto exception;
@@ -14032,12 +14257,15 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
res = ctx->rt->bigfloat_ops.compare(ctx, OP_eq, op1, op2);
if (res < 0)
goto exception;
- } else {
+ } else
+#endif
+ {
res = ctx->rt->bigint_ops.compare(ctx, OP_eq, op1, op2);
if (res < 0)
goto exception;
}
} else if (tag1 == tag2) {
+#ifdef CONFIG_BIGNUM
if (tag1 == JS_TAG_OBJECT) {
/* try the fallback operator */
res = js_call_binary_op_fallback(ctx, &ret, op1, op2,
@@ -14054,6 +14282,7 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
}
}
}
+#endif
res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
} else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||
(tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {
@@ -14090,7 +14319,7 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
goto exception;
}
}
- res = js_strict_eq(ctx, op1, op2);
+ res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
} else if (tag1 == JS_TAG_BOOL) {
op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));
goto redo;
@@ -14101,7 +14330,7 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
(tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) ||
(tag2 == JS_TAG_OBJECT &&
(tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) {
-
+#ifdef CONFIG_BIGNUM
/* try the fallback operator */
res = js_call_binary_op_fallback(ctx, &ret, op1, op2,
is_neq ? OP_neq : OP_eq,
@@ -14116,7 +14345,7 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
return 0;
}
}
-
+#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -14188,6 +14417,7 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)
return -1;
}
+#ifdef CONFIG_BIGNUM
static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,
int64_t exponent)
{
@@ -14205,7 +14435,7 @@ static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,
if (ret & BF_ST_MEM_ERROR)
return JS_ThrowOutOfMemory(ctx);
else
- return __JS_NewFloat64(ctx, d);
+ return JS_NewFloat64(ctx, d);
}
static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)
@@ -14222,8 +14452,10 @@ static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)
op1 = sp[-2];
op2 = sp[-1];
a = JS_ToBigFloat(ctx, &a_s, op1);
- if (!a)
+ if (!a) {
+ JS_FreeValue(ctx, res);
return -1;
+ }
if (JS_IsBigInt(ctx, op2)) {
ret = JS_ToBigInt64(ctx, &e, op2);
} else {
@@ -14244,395 +14476,7 @@ static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)
sp[-2] = res;
return 0;
}
-
-#else /* !CONFIG_BIGNUM */
-
-static JSValue JS_ThrowUnsupportedBigint(JSContext *ctx)
-{
- return JS_ThrowTypeError(ctx, "bigint is not supported");
-}
-
-JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)
-{
- return JS_ThrowUnsupportedBigint(ctx);
-}
-
-JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
-{
- return JS_ThrowUnsupportedBigint(ctx);
-}
-
-int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
-{
- JS_ThrowUnsupportedBigint(ctx);
- *pres = 0;
- return -1;
-}
-
-static no_inline warn_unused int js_unary_arith_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
-{
- JSValue op1;
- double d;
-
- op1 = sp[-1];
- if (unlikely(JS_ToFloat64Free(ctx, &d, op1))) {
- sp[-1] = JS_UNDEFINED;
- return -1;
- }
- switch(op) {
- case OP_inc:
- d++;
- break;
- case OP_dec:
- d--;
- break;
- case OP_plus:
- break;
- case OP_neg:
- d = -d;
- break;
- default:
- abort();
- }
- sp[-1] = JS_NewFloat64(ctx, d);
- return 0;
-}
-
-/* specific case necessary for correct return value semantics */
-static warn_unused int js_post_inc_slow(JSContext *ctx,
- JSValue *sp, OPCodeEnum op)
-{
- JSValue op1;
- double d, r;
-
- op1 = sp[-1];
- if (unlikely(JS_ToFloat64Free(ctx, &d, op1))) {
- sp[-1] = JS_UNDEFINED;
- return -1;
- }
- r = d + 2 * (op - OP_post_dec) - 1;
- sp[0] = JS_NewFloat64(ctx, r);
- sp[-1] = JS_NewFloat64(ctx, d);
- return 0;
-}
-
-static no_inline warn_unused int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
- OPCodeEnum op)
-{
- JSValue op1, op2;
- double d1, d2, r;
-
- op1 = sp[-2];
- op2 = sp[-1];
- if (unlikely(JS_ToFloat64Free(ctx, &d1, op1))) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (unlikely(JS_ToFloat64Free(ctx, &d2, op2))) {
- goto exception;
- }
- switch(op) {
- case OP_sub:
- r = d1 - d2;
- break;
- case OP_mul:
- r = d1 * d2;
- break;
- case OP_div:
- r = d1 / d2;
- break;
- case OP_mod:
- r = fmod(d1, d2);
- break;
- case OP_pow:
- r = js_pow(d1, d2);
- break;
- default:
- abort();
- }
- sp[-2] = JS_NewFloat64(ctx, r);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline warn_unused int js_add_slow(JSContext *ctx, JSValue *sp)
-{
- JSValue op1, op2;
- uint32_t tag1, tag2;
-
- op1 = sp[-2];
- op2 = sp[-1];
- tag1 = JS_VALUE_GET_TAG(op1);
- tag2 = JS_VALUE_GET_TAG(op2);
- if ((tag1 == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag1)) &&
- (tag2 == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag2))) {
- goto add_numbers;
- } else {
- op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
- if (JS_IsException(op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- goto exception;
- }
- tag1 = JS_VALUE_GET_TAG(op1);
- tag2 = JS_VALUE_GET_TAG(op2);
- if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) {
- sp[-2] = JS_ConcatString(ctx, op1, op2);
- if (JS_IsException(sp[-2]))
- goto exception;
- } else {
- double d1, d2;
- add_numbers:
- if (JS_ToFloat64Free(ctx, &d1, op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (JS_ToFloat64Free(ctx, &d2, op2))
- goto exception;
- sp[-2] = JS_NewFloat64(ctx, d1 + d2);
- }
- }
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline warn_unused int js_binary_logic_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
-{
- JSValue op1, op2;
- uint32_t v1, v2, r;
-
- op1 = sp[-2];
- op2 = sp[-1];
- if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v2, op2)))
- goto exception;
- switch(op) {
- case OP_shl:
- r = v1 << (v2 & 0x1f);
- break;
- case OP_sar:
- r = (int)v1 >> (v2 & 0x1f);
- break;
- case OP_and:
- r = v1 & v2;
- break;
- case OP_or:
- r = v1 | v2;
- break;
- case OP_xor:
- r = v1 ^ v2;
- break;
- default:
- abort();
- }
- sp[-2] = JS_NewInt32(ctx, r);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
-{
- int32_t v1;
-
- if (unlikely(JS_ToInt32Free(ctx, &v1, sp[-1]))) {
- sp[-1] = JS_UNDEFINED;
- return -1;
- }
- sp[-1] = JS_NewInt32(ctx, ~v1);
- return 0;
-}
-
-static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
- OPCodeEnum op)
-{
- JSValue op1, op2;
- int res;
-
- op1 = sp[-2];
- op2 = sp[-1];
- op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);
- if (JS_IsException(op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NUMBER);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- goto exception;
- }
- if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING &&
- JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {
- JSString *p1, *p2;
- p1 = JS_VALUE_GET_STRING(op1);
- p2 = JS_VALUE_GET_STRING(op2);
- res = js_string_compare(ctx, p1, p2);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- switch(op) {
- case OP_lt:
- res = (res < 0);
- break;
- case OP_lte:
- res = (res <= 0);
- break;
- case OP_gt:
- res = (res > 0);
- break;
- default:
- case OP_gte:
- res = (res >= 0);
- break;
- }
- } else {
- double d1, d2;
- if (JS_ToFloat64Free(ctx, &d1, op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (JS_ToFloat64Free(ctx, &d2, op2))
- goto exception;
- switch(op) {
- case OP_lt:
- res = (d1 < d2); /* if NaN return false */
- break;
- case OP_lte:
- res = (d1 <= d2); /* if NaN return false */
- break;
- case OP_gt:
- res = (d1 > d2); /* if NaN return false */
- break;
- default:
- case OP_gte:
- res = (d1 >= d2); /* if NaN return false */
- break;
- }
- }
- sp[-2] = JS_NewBool(ctx, res);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline warn_unused int js_eq_slow(JSContext *ctx, JSValue *sp,
- BOOL is_neq)
-{
- JSValue op1, op2;
- int tag1, tag2;
- BOOL res;
-
- op1 = sp[-2];
- op2 = sp[-1];
- redo:
- tag1 = JS_VALUE_GET_NORM_TAG(op1);
- tag2 = JS_VALUE_GET_NORM_TAG(op2);
- if (tag1 == tag2 ||
- (tag1 == JS_TAG_INT && tag2 == JS_TAG_FLOAT64) ||
- (tag2 == JS_TAG_INT && tag1 == JS_TAG_FLOAT64)) {
- res = js_strict_eq(ctx, op1, op2);
- } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||
- (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {
- res = TRUE;
- } else if ((tag1 == JS_TAG_STRING && (tag2 == JS_TAG_INT ||
- tag2 == JS_TAG_FLOAT64)) ||
- (tag2 == JS_TAG_STRING && (tag1 == JS_TAG_INT ||
- tag1 == JS_TAG_FLOAT64))) {
- double d1;
- double d2;
- if (JS_ToFloat64Free(ctx, &d1, op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (JS_ToFloat64Free(ctx, &d2, op2))
- goto exception;
- res = (d1 == d2);
- } else if (tag1 == JS_TAG_BOOL) {
- op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));
- goto redo;
- } else if (tag2 == JS_TAG_BOOL) {
- op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));
- goto redo;
- } else if (tag1 == JS_TAG_OBJECT &&
- (tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64 || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) {
- op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
- if (JS_IsException(op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- goto redo;
- } else if (tag2 == JS_TAG_OBJECT &&
- (tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64 || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL)) {
- op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- goto exception;
- }
- goto redo;
- } else {
- /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */
- if ((JS_IsHTMLDDA(ctx, op1) &&
- (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||
- (JS_IsHTMLDDA(ctx, op2) &&
- (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {
- res = TRUE;
- } else {
- res = FALSE;
- }
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- }
- sp[-2] = JS_NewBool(ctx, res ^ is_neq);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)
-{
- JSValue op1, op2;
- uint32_t v1, v2, r;
-
- op1 = sp[-2];
- op2 = sp[-1];
- if (unlikely(JS_ToUint32Free(ctx, &v1, op1))) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (unlikely(JS_ToUint32Free(ctx, &v2, op2)))
- goto exception;
- r = v1 >> (v2 & 0x1f);
- sp[-2] = JS_NewUint32(ctx, r);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-#endif /* !CONFIG_BIGNUM */
+#endif
/* XXX: Should take JSValueConst arguments */
static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
@@ -14726,7 +14570,6 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
res = (d1 == d2); /* if NaN return false and +0 == -0 */
}
goto done_no_free;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
{
bf_t a_s, *a, b_s, *b;
@@ -14734,8 +14577,8 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
res = FALSE;
break;
}
- a = JS_ToBigFloat(ctx, &a_s, op1);
- b = JS_ToBigFloat(ctx, &b_s, op2);
+ a = JS_ToBigFloat(ctx, &a_s, op1); /* cannot fail */
+ b = JS_ToBigFloat(ctx, &b_s, op2); /* cannot fail */
res = bf_cmp_eq(a, b);
if (a == &a_s)
bf_delete(a);
@@ -14743,6 +14586,7 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
bf_delete(b);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
{
JSBigFloat *p1, *p2;
@@ -14793,9 +14637,16 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
return res;
}
-static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2)
+static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+{
+ return js_strict_eq2(ctx,
+ JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),
+ JS_EQ_STRICT);
+}
+
+BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2)
{
- return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
+ return js_strict_eq(ctx, op1, op2);
}
static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2)
@@ -14805,6 +14656,11 @@ static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2)
JS_EQ_SAME_VALUE);
}
+BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+{
+ return js_same_value(ctx, op1, op2);
+}
+
static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2)
{
return js_strict_eq2(ctx,
@@ -14812,16 +14668,21 @@ static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op
JS_EQ_SAME_VALUE_ZERO);
}
+BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+{
+ return js_same_value_zero(ctx, op1, op2);
+}
+
static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp,
BOOL is_neq)
{
BOOL res;
- res = js_strict_eq(ctx, sp[-2], sp[-1]);
+ res = js_strict_eq2(ctx, sp[-2], sp[-1], JS_EQ_STRICT);
sp[-2] = JS_NewBool(ctx, res ^ is_neq);
return 0;
}
-static warn_unused int js_operator_in(JSContext *ctx, JSValue *sp)
+static __exception int js_operator_in(JSContext *ctx, JSValue *sp)
{
JSValue op1, op2;
JSAtom atom;
@@ -14847,7 +14708,44 @@ static warn_unused int js_operator_in(JSContext *ctx, JSValue *sp)
return 0;
}
-static warn_unused int js_has_unscopable(JSContext *ctx, JSValueConst obj,
+static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp)
+{
+ JSValue op1, op2;
+ int ret;
+
+ op1 = sp[-2]; /* object */
+ op2 = sp[-1]; /* field name or method function */
+
+ if (JS_VALUE_GET_TAG(op1) != JS_TAG_OBJECT) {
+ JS_ThrowTypeError(ctx, "invalid 'in' operand");
+ return -1;
+ }
+ if (JS_IsObject(op2)) {
+ /* method: use the brand */
+ ret = JS_CheckBrand(ctx, op1, op2);
+ if (ret < 0)
+ return -1;
+ } else {
+ JSAtom atom;
+ JSObject *p;
+ JSShapeProperty *prs;
+ JSProperty *pr;
+ /* field */
+ atom = JS_ValueToAtom(ctx, op2);
+ if (unlikely(atom == JS_ATOM_NULL))
+ return -1;
+ p = JS_VALUE_GET_OBJ(op1);
+ prs = find_own_property(&pr, p, atom);
+ JS_FreeAtom(ctx, atom);
+ ret = (prs != NULL);
+ }
+ JS_FreeValue(ctx, op1);
+ JS_FreeValue(ctx, op2);
+ sp[-2] = JS_NewBool(ctx, ret);
+ return 0;
+}
+
+static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
JSAtom atom)
{
JSValue arr, val;
@@ -14865,7 +14763,7 @@ static warn_unused int js_has_unscopable(JSContext *ctx, JSValueConst obj,
return ret;
}
-static warn_unused int js_operator_instanceof(JSContext *ctx, JSValue *sp)
+static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)
{
JSValue op1, op2;
BOOL ret;
@@ -14881,17 +14779,17 @@ static warn_unused int js_operator_instanceof(JSContext *ctx, JSValue *sp)
return 0;
}
-static warn_unused int js_operator_typeof(JSContext *ctx, JSValueConst op1)
+static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
{
JSAtom atom;
uint32_t tag;
tag = JS_VALUE_GET_NORM_TAG(op1);
switch(tag) {
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
atom = JS_ATOM_bigint;
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
atom = JS_ATOM_bigfloat;
break;
@@ -14938,7 +14836,7 @@ static warn_unused int js_operator_typeof(JSContext *ctx, JSValueConst op1)
return atom;
}
-static warn_unused int js_operator_delete(JSContext *ctx, JSValue *sp)
+static __exception int js_operator_delete(JSContext *ctx, JSValue *sp)
{
JSValue op1, op2;
JSAtom atom;
@@ -15093,7 +14991,7 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
var_ref = get_var_ref(ctx, sf, i, TRUE);
if (!var_ref)
goto fail;
- pr = add_property(ctx, p, JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
+ pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
if (!pr) {
free_var_ref(ctx->rt, var_ref);
goto fail;
@@ -15145,10 +15043,10 @@ static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *
static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
{
- JSObject *p;
+ JSObject *p, *p1;
JSPropertyEnum *tab_atom;
int i;
- JSValue enum_obj, obj1;
+ JSValue enum_obj;
JSForInIterator *it;
uint32_t tag, tab_atom_count;
@@ -15171,40 +15069,16 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
it->is_array = FALSE;
it->obj = obj;
it->idx = 0;
- p = JS_VALUE_GET_OBJ(enum_obj);
- p->u.for_in_iterator = it;
+ it->tab_atom = NULL;
+ it->atom_count = 0;
+ it->in_prototype_chain = FALSE;
+ p1 = JS_VALUE_GET_OBJ(enum_obj);
+ p1->u.for_in_iterator = it;
if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)
return enum_obj;
- /* fast path: assume no enumerable properties in the prototype chain */
- obj1 = JS_DupValue(ctx, obj);
- for(;;) {
- obj1 = JS_GetPrototypeFree(ctx, obj1);
- if (JS_IsNull(obj1))
- break;
- if (JS_IsException(obj1))
- goto fail;
- if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
- JS_VALUE_GET_OBJ(obj1),
- JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
- JS_FreeValue(ctx, obj1);
- goto fail;
- }
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
- if (tab_atom_count != 0) {
- JS_FreeValue(ctx, obj1);
- goto slow_path;
- }
- /* must check for timeout to avoid infinite loop */
- if (js_poll_interrupts(ctx)) {
- JS_FreeValue(ctx, obj1);
- goto fail;
- }
- }
-
p = JS_VALUE_GET_OBJ(obj);
-
if (p->fast_array) {
JSShape *sh;
JSShapeProperty *prs;
@@ -15216,70 +15090,101 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
}
/* for fast arrays, we only store the number of elements */
it->is_array = TRUE;
- it->array_length = p->u.array.count;
+ it->atom_count = p->u.array.count;
} else {
normal_case:
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,
- JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY))
- goto fail;
- for(i = 0; i < tab_atom_count; i++) {
- JS_SetPropertyInternal(ctx, enum_obj, tab_atom[i].atom, JS_NULL, 0);
+ JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
+ JS_FreeValue(ctx, enum_obj);
+ return JS_EXCEPTION;
}
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
+ it->tab_atom = tab_atom;
+ it->atom_count = tab_atom_count;
}
return enum_obj;
+}
- slow_path:
- /* non enumerable properties hide the enumerables ones in the
- prototype chain */
- obj1 = JS_DupValue(ctx, obj);
+/* obj -> enum_obj */
+static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
+{
+ sp[-1] = build_for_in_iterator(ctx, sp[-1]);
+ if (JS_IsException(sp[-1]))
+ return -1;
+ return 0;
+}
+
+/* return -1 if exception, 0 if slow case, 1 if the enumeration is finished */
+static __exception int js_for_in_prepare_prototype_chain_enum(JSContext *ctx,
+ JSValueConst enum_obj)
+{
+ JSObject *p;
+ JSForInIterator *it;
+ JSPropertyEnum *tab_atom;
+ uint32_t tab_atom_count, i;
+ JSValue obj1;
+
+ p = JS_VALUE_GET_OBJ(enum_obj);
+ it = p->u.for_in_iterator;
+
+ /* check if there are enumerable properties in the prototype chain (fast path) */
+ obj1 = JS_DupValue(ctx, it->obj);
for(;;) {
+ obj1 = JS_GetPrototypeFree(ctx, obj1);
+ if (JS_IsNull(obj1))
+ break;
+ if (JS_IsException(obj1))
+ goto fail;
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
JS_VALUE_GET_OBJ(obj1),
- JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
+ JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
- for(i = 0; i < tab_atom_count; i++) {
- JS_DefinePropertyValue(ctx, enum_obj, tab_atom[i].atom, JS_NULL,
- (tab_atom[i].is_enumerable ?
- JS_PROP_ENUMERABLE : 0));
- }
js_free_prop_enum(ctx, tab_atom, tab_atom_count);
- obj1 = JS_GetPrototypeFree(ctx, obj1);
- if (JS_IsNull(obj1))
- break;
- if (JS_IsException(obj1))
- goto fail;
+ if (tab_atom_count != 0) {
+ JS_FreeValue(ctx, obj1);
+ goto slow_path;
+ }
/* must check for timeout to avoid infinite loop */
if (js_poll_interrupts(ctx)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
}
- return enum_obj;
+ JS_FreeValue(ctx, obj1);
+ return 1;
- fail:
- JS_FreeValue(ctx, enum_obj);
- return JS_EXCEPTION;
-}
+ slow_path:
+ /* add the visited properties, even if they are not enumerable */
+ if (it->is_array) {
+ if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
+ JS_VALUE_GET_OBJ(it->obj),
+ JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
+ goto fail;
+ }
+ it->is_array = FALSE;
+ it->tab_atom = tab_atom;
+ it->atom_count = tab_atom_count;
+ }
-/* obj -> enum_obj */
-static warn_unused int js_for_in_start(JSContext *ctx, JSValue *sp)
-{
- sp[-1] = build_for_in_iterator(ctx, sp[-1]);
- if (JS_IsException(sp[-1]))
- return -1;
+ for(i = 0; i < it->atom_count; i++) {
+ if (JS_DefinePropertyValue(ctx, enum_obj, it->tab_atom[i].atom, JS_NULL, JS_PROP_ENUMERABLE) < 0)
+ goto fail;
+ }
return 0;
+ fail:
+ return -1;
}
/* enum_obj -> enum_obj value done */
-static warn_unused int js_for_in_next(JSContext *ctx, JSValue *sp)
+static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
{
JSValueConst enum_obj;
JSObject *p;
JSAtom prop;
JSForInIterator *it;
+ JSPropertyEnum *tab_atom;
+ uint32_t tab_atom_count;
int ret;
enum_obj = sp[-1];
@@ -15292,28 +15197,68 @@ static warn_unused int js_for_in_next(JSContext *ctx, JSValue *sp)
it = p->u.for_in_iterator;
for(;;) {
- if (it->is_array) {
- if (it->idx >= it->array_length)
- goto done;
- prop = JS_AtomFromUInt32(it->idx);
- it->idx++;
+ if (it->idx >= it->atom_count) {
+ if (JS_IsNull(it->obj) || JS_IsUndefined(it->obj))
+ goto done; /* not an object */
+ /* no more property in the current object: look in the prototype */
+ if (!it->in_prototype_chain) {
+ ret = js_for_in_prepare_prototype_chain_enum(ctx, enum_obj);
+ if (ret < 0)
+ return -1;
+ if (ret)
+ goto done;
+ it->in_prototype_chain = TRUE;
+ }
+ it->obj = JS_GetPrototypeFree(ctx, it->obj);
+ if (JS_IsException(it->obj))
+ return -1;
+ if (JS_IsNull(it->obj))
+ goto done; /* no more prototype */
+
+ /* must check for timeout to avoid infinite loop */
+ if (js_poll_interrupts(ctx))
+ return -1;
+
+ if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
+ JS_VALUE_GET_OBJ(it->obj),
+ JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
+ return -1;
+ }
+ js_free_prop_enum(ctx, it->tab_atom, it->atom_count);
+ it->tab_atom = tab_atom;
+ it->atom_count = tab_atom_count;
+ it->idx = 0;
} else {
- JSShape *sh = p->shape;
- JSShapeProperty *prs;
- if (it->idx >= sh->prop_count)
- goto done;
- prs = get_shape_prop(sh) + it->idx;
- prop = prs->atom;
- it->idx++;
- if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE))
- continue;
+ if (it->is_array) {
+ prop = __JS_AtomFromUInt32(it->idx);
+ it->idx++;
+ } else {
+ BOOL is_enumerable;
+ prop = it->tab_atom[it->idx].atom;
+ is_enumerable = it->tab_atom[it->idx].is_enumerable;
+ it->idx++;
+ if (it->in_prototype_chain) {
+ /* slow case: we are in the prototype chain */
+ ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(enum_obj), prop);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ continue; /* already visited */
+ /* add to the visited property list */
+ if (JS_DefinePropertyValue(ctx, enum_obj, prop, JS_NULL,
+ JS_PROP_ENUMERABLE) < 0)
+ return -1;
+ }
+ if (!is_enumerable)
+ continue;
+ }
+ /* check if the property was deleted */
+ ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(it->obj), prop);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ break;
}
- /* check if the property was deleted */
- ret = JS_HasProperty(ctx, it->obj, prop);
- if (ret < 0)
- return ret;
- if (ret)
- break;
}
/* return the property */
sp[0] = JS_AtomToValue(ctx, prop);
@@ -15488,7 +15433,7 @@ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,
}
/* obj -> enum_rec (3 slots) */
-static warn_unused int js_for_of_start(JSContext *ctx, JSValue *sp,
+static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,
BOOL is_async)
{
JSValue op1, obj, method;
@@ -15509,7 +15454,7 @@ static warn_unused int js_for_of_start(JSContext *ctx, JSValue *sp,
objs. If 'done' is true or in case of exception, 'enum_rec' is set
to undefined. If 'done' is true, 'value' is always set to
undefined. */
-static warn_unused int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
+static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
{
JSValue value = JS_UNDEFINED;
int done = 1;
@@ -15555,7 +15500,7 @@ static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,
return JS_EXCEPTION;
}
-static warn_unused int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
+static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
{
JSValue obj, value;
BOOL done;
@@ -15631,7 +15576,7 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
return FALSE;
}
-static warn_unused int js_append_enumerate(JSContext *ctx, JSValue *sp)
+static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
{
JSValue iterator, enumobj, method, value;
int is_array_iterator;
@@ -15711,7 +15656,7 @@ exception:
return -1;
}
-static warn_unused int JS_CopyDataProperties(JSContext *ctx,
+static __exception int JS_CopyDataProperties(JSContext *ctx,
JSValueConst target,
JSValueConst source,
JSValueConst excluded,
@@ -15799,7 +15744,7 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,
struct list_head *el;
list_for_each(el, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, header.link);
+ var_ref = list_entry(el, JSVarRef, var_ref_link);
if (var_ref->var_idx == var_idx && var_ref->is_arg == is_arg) {
var_ref->header.ref_count++;
return var_ref;
@@ -15810,15 +15755,29 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,
if (!var_ref)
return NULL;
var_ref->header.ref_count = 1;
+ add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
var_ref->is_detached = FALSE;
var_ref->is_arg = is_arg;
var_ref->var_idx = var_idx;
- list_add_tail(&var_ref->header.link, &sf->var_ref_list);
+ list_add_tail(&var_ref->var_ref_link, &sf->var_ref_list);
+ if (sf->js_mode & JS_MODE_ASYNC) {
+ /* The stack frame is detached and may be destroyed at any
+ time so its reference count must be increased. Calling
+ close_var_refs() when destroying the stack frame is not
+ possible because it would change the graph between the GC
+ objects. Another solution could be to temporarily detach
+ the JSVarRef of async functions during the GC. It would
+ have the advantage of allowing the release of unused stack
+ frames in a cycle. */
+ var_ref->async_func = container_of(sf, JSAsyncFunctionState, frame);
+ var_ref->async_func->header.ref_count++;
+ } else {
+ var_ref->async_func = NULL;
+ }
if (is_arg)
var_ref->pvalue = &sf->arg_buf[var_idx];
else
var_ref->pvalue = &sf->var_buf[var_idx];
- var_ref->value = JS_UNDEFINED;
return var_ref;
}
@@ -16049,7 +16008,10 @@ static void close_var_refs(JSRuntime *rt, JSStackFrame *sf)
int var_idx;
list_for_each_safe(el, el1, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, header.link);
+ var_ref = list_entry(el, JSVarRef, var_ref_link);
+ /* no need to unlink var_ref->var_ref_link as the list is never used afterwards */
+ if (var_ref->async_func)
+ async_func_free(rt, var_ref->async_func);
var_idx = var_ref->var_idx;
if (var_ref->is_arg)
var_ref->value = JS_DupValueRT(rt, sf->arg_buf[var_idx]);
@@ -16058,7 +16020,6 @@ static void close_var_refs(JSRuntime *rt, JSStackFrame *sf)
var_ref->pvalue = &var_ref->value;
/* the reference is no longer to a local variable */
var_ref->is_detached = TRUE;
- add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
}
}
@@ -16069,14 +16030,15 @@ static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_
int var_idx = idx;
list_for_each_safe(el, el1, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, header.link);
+ var_ref = list_entry(el, JSVarRef, var_ref_link);
if (var_idx == var_ref->var_idx && var_ref->is_arg == is_arg) {
+ list_del(&var_ref->var_ref_link);
+ if (var_ref->async_func)
+ async_func_free(ctx->rt, var_ref->async_func);
var_ref->value = JS_DupValue(ctx, sf->var_buf[var_idx]);
var_ref->pvalue = &var_ref->value;
- list_del(&var_ref->header.link);
/* the reference is no longer to a local variable */
var_ref->is_detached = TRUE;
- add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
}
}
}
@@ -16133,7 +16095,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
arg_buf[i] = JS_UNDEFINED;
sf->arg_count = arg_count;
}
- sf->arg_buf = arg_buf;
+ sf->arg_buf = (JSValue*)arg_buf;
func = p->u.cfunc.c_function;
switch(cproto) {
@@ -16267,9 +16229,10 @@ typedef enum {
OP_SPECIAL_OBJECT_IMPORT_META,
} OPSpecialObjectEnum;
-#define FUNC_RET_AWAIT 0
-#define FUNC_RET_YIELD 1
-#define FUNC_RET_YIELD_STAR 2
+#define FUNC_RET_AWAIT 0
+#define FUNC_RET_YIELD 1
+#define FUNC_RET_YIELD_STAR 2
+#define FUNC_RET_INITIAL_YIELD 3
/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */
static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
@@ -16303,7 +16266,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
#include "quickjs-opcode.h"
[ OP_COUNT ... 255 ] = &&case_default
};
-#define SWITCH(pc) goto *dispatch_table[opcode = *(pc)++];
+#define SWITCH(pc) goto *dispatch_table[opcode = *pc++];
#define CASE(op) case_ ## op
#define DEFAULT case_default
#define BREAK SWITCH(pc)
@@ -16346,7 +16309,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
return JS_ThrowTypeError(caller_ctx, "not a function");
}
return call_func(caller_ctx, func_obj, this_obj, argc,
- argv, flags);
+ (JSValueConst *)argv, flags);
}
b = p->u.func.function_bytecode;
@@ -16500,12 +16463,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int arg = *pc++;
switch(arg) {
case OP_SPECIAL_OBJECT_ARGUMENTS:
- *sp++ = js_build_arguments(ctx, argc, argv);
+ *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv);
if (unlikely(JS_IsException(sp[-1])))
goto exception;
break;
case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS:
- *sp++ = js_build_mapped_arguments(ctx, argc, argv,
+ *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv,
sf, min_int(argc, b->arg_count));
if (unlikely(JS_IsException(sp[-1])))
goto exception;
@@ -16545,7 +16508,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
int first = get_u16(pc);
pc += 2;
- *sp++ = js_build_rest(ctx, first, argc, argv);
+ *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv);
if (unlikely(JS_IsException(sp[-1])))
goto exception;
}
@@ -16778,7 +16741,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
goto exception;
call_argv = sp - call_argc;
for(i = 0; i < call_argc; i++) {
- ret = JS_DefinePropertyValue(ctx, ret_val, JS_AtomFromUInt32(i), call_argv[i],
+ ret = JS_DefinePropertyValue(ctx, ret_val, __JS_AtomFromUInt32(i), call_argv[i],
JS_PROP_C_W_E | JS_PROP_THROW);
call_argv[i] = JS_UNDEFINED;
if (ret < 0) {
@@ -16797,7 +16760,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
magic = get_u16(pc);
pc += 2;
- ret_val = js_function_apply(ctx, sp[-3], 2, &sp[-2], magic);
+ ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic);
if (unlikely(JS_IsException(ret_val)))
goto exception;
JS_FreeValue(ctx, sp[-3]);
@@ -16834,8 +16797,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
BREAK;
CASE(OP_check_brand):
- if (JS_CheckBrand(ctx, sp[-2], sp[-1]) < 0)
- goto exception;
+ {
+ int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]);
+ if (ret < 0)
+ goto exception;
+ if (!ret) {
+ JS_ThrowTypeError(ctx, "invalid brand on object");
+ goto exception;
+ }
+ }
BREAK;
CASE(OP_add_brand):
if (JS_AddBrand(ctx, sp[-2], sp[-1]) < 0)
@@ -16930,7 +16900,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JS_EVAL_TYPE_DIRECT, scope_idx);
} else {
ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len,
- tab);
+ (JSValueConst *)tab);
}
free_arg_list(ctx, tab, len);
if (unlikely(JS_IsException(ret_val)))
@@ -17257,6 +17227,19 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp++;
}
BREAK;
+ CASE(OP_get_loc_checkthis):
+ {
+ int idx;
+ idx = get_u16(pc);
+ pc += 2;
+ if (unlikely(JS_IsUninitialized(var_buf[idx]))) {
+ JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, FALSE);
+ goto exception;
+ }
+ sp[0] = JS_DupValue(ctx, var_buf[idx]);
+ sp++;
+ }
+ BREAK;
CASE(OP_put_loc_check):
{
int idx;
@@ -17380,6 +17363,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op1 = sp[-1];
pc += 4;
+ /* quick and dirty test for JS_TAG_INT, JS_TAG_BOOL, JS_TAG_NULL and JS_TAG_UNDEFINED */
if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {
res = JS_VALUE_GET_INT(op1);
} else {
@@ -17526,26 +17510,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
sp--;
BREAK;
- CASE(OP_iterator_close_return):
+ CASE(OP_nip_catch):
{
JSValue ret_val;
- /* iter_obj next catch_offset ... ret_val ->
- ret_eval iter_obj next catch_offset */
+ /* catch_offset ... ret_val -> ret_eval */
ret_val = *--sp;
while (sp > stack_buf &&
JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_CATCH_OFFSET) {
JS_FreeValue(ctx, *--sp);
}
- if (unlikely(sp < stack_buf + 3)) {
- JS_ThrowInternalError(ctx, "iterator_close_return");
+ if (unlikely(sp == stack_buf)) {
+ JS_ThrowInternalError(ctx, "nip_catch");
JS_FreeValue(ctx, ret_val);
goto exception;
}
- sp[0] = sp[-1];
- sp[-1] = sp[-2];
- sp[-2] = sp[-3];
- sp[-3] = ret_val;
- sp++;
+ sp[-1] = ret_val;
}
BREAK;
@@ -17554,7 +17533,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue ret;
ret = JS_Call(ctx, sp[-3], sp[-4],
- 1, (sp - 1));
+ 1, (JSValueConst *)(sp - 1));
if (JS_IsException(ret))
goto exception;
JS_FreeValue(ctx, sp[-1]);
@@ -17582,7 +17561,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
0, NULL);
} else {
ret = JS_CallFree(ctx, method, sp[-4],
- 1, (sp - 1));
+ 1, (JSValueConst *)(sp - 1));
}
if (JS_IsException(ret))
goto exception;
@@ -17646,7 +17625,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
atom = get_u32(pc);
pc += 4;
- ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1],
+ ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1], sp[-2],
JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-2]);
sp -= 2;
@@ -17945,8 +17924,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
atom = JS_ValueToAtom(ctx, sp[-2]);
if (unlikely(atom == JS_ATOM_NULL))
goto exception;
- ret = JS_SetPropertyGeneric(ctx, sp[-3], atom, sp[-1], sp[-4],
- JS_PROP_THROW_STRICT);
+ ret = JS_SetPropertyInternal(ctx, sp[-3], atom, sp[-1], sp[-4],
+ JS_PROP_THROW_STRICT);
JS_FreeAtom(ctx, atom);
JS_FreeValue(ctx, sp[-4]);
JS_FreeValue(ctx, sp[-3]);
@@ -18005,9 +17984,14 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-2] = JS_NewInt32(ctx, r);
sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
- sp[-2] = JS_NewFloat64Impl(ctx, JS_VALUE_GET_FLOAT64(op1) +
+ sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) +
JS_VALUE_GET_FLOAT64(op2));
sp--;
+ } else if (JS_IsString(op1) && JS_IsString(op2)) {
+ sp[-2] = JS_ConcatString(ctx, op1, op2);
+ sp--;
+ if (JS_IsException(sp[-1]))
+ goto exception;
} else {
add_slow:
if (js_add_slow(ctx, sp))
@@ -18018,38 +18002,45 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_add_loc):
{
+ JSValue op2;
JSValue *pv;
int idx;
idx = *pc;
pc += 1;
+ op2 = sp[-1];
pv = &var_buf[idx];
- if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) {
+ if (likely(JS_VALUE_IS_BOTH_INT(*pv, op2))) {
int64_t r;
- r = (int64_t)JS_VALUE_GET_INT(*pv) +
- JS_VALUE_GET_INT(sp[-1]);
+ r = (int64_t)JS_VALUE_GET_INT(*pv) + JS_VALUE_GET_INT(op2);
if (unlikely((int)r != r))
goto add_loc_slow;
*pv = JS_NewInt32(ctx, r);
sp--;
+ } else if (JS_VALUE_IS_BOTH_FLOAT(*pv, op2)) {
+ *pv = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(*pv) +
+ JS_VALUE_GET_FLOAT64(op2));
+ sp--;
} else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) {
- JSValue op1;
- op1 = sp[-1];
sp--;
- op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
- if (JS_IsException(op1))
- goto exception;
- op1 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op1);
- if (JS_IsException(op1))
+ op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
+ if (JS_IsException(op2))
goto exception;
- set_value(ctx, pv, op1);
+ if (JS_ConcatStringInPlace(ctx, JS_VALUE_GET_STRING(*pv), op2)) {
+ JS_FreeValue(ctx, op2);
+ } else {
+ op2 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op2);
+ if (JS_IsException(op2))
+ goto exception;
+ set_value(ctx, pv, op2);
+ }
} else {
JSValue ops[2];
add_loc_slow:
/* In case of exception, js_add_slow frees ops[0]
and ops[1], so we must duplicate *pv */
ops[0] = JS_DupValue(ctx, *pv);
- ops[1] = sp[-1];
+ ops[1] = op2;
sp--;
if (js_add_slow(ctx, ops + 2))
goto exception;
@@ -18070,8 +18061,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-2] = JS_NewInt32(ctx, r);
sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
- sp[-2] = JS_NewFloat64Impl(ctx, JS_VALUE_GET_FLOAT64(op1) -
- JS_VALUE_GET_FLOAT64(op2));
+ sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) -
+ JS_VALUE_GET_FLOAT64(op2));
sp--;
} else {
goto binary_arith_slow;
@@ -18113,7 +18104,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
#endif
d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);
mul_fp_res:
- sp[-2] = JS_NewFloat64Impl(ctx, d);
+ sp[-2] = __JS_NewFloat64(ctx, d);
sp--;
} else {
goto binary_arith_slow;
@@ -18205,7 +18196,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
} else if (JS_TAG_IS_FLOAT64(tag)) {
d = -JS_VALUE_GET_FLOAT64(op1);
neg_fp_res:
- sp[-1] = JS_NewFloat64Impl(ctx, d);
+ sp[-1] = __JS_NewFloat64(ctx, d);
} else {
if (js_unary_arith_slow(ctx, sp, opcode))
goto exception;
@@ -18495,6 +18486,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
goto exception;
sp--;
BREAK;
+ CASE(OP_private_in):
+ if (js_operator_private_in(ctx, sp))
+ goto exception;
+ sp--;
+ BREAK;
CASE(OP_instanceof):
if (js_operator_instanceof(ctx, sp))
goto exception;
@@ -18625,7 +18621,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
break;
case OP_with_put_var:
/* XXX: check if strict mode */
- ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2],
+ ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2], obj,
JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-1]);
sp -= 2;
@@ -18681,9 +18677,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD_STAR);
goto done_generator;
CASE(OP_return_async):
- CASE(OP_initial_yield):
ret_val = JS_UNDEFINED;
goto done_generator;
+ CASE(OP_initial_yield):
+ ret_val = JS_NewInt32(ctx, FUNC_RET_INITIAL_YIELD);
+ goto done_generator;
CASE(OP_nop):
BREAK;
@@ -18802,14 +18800,14 @@ JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
int argc, JSValueConst *argv)
{
return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
- argc, argv, JS_CALL_FLAG_COPY_ARGV);
+ argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
}
static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,
int argc, JSValueConst *argv)
{
JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
- argc, argv, JS_CALL_FLAG_COPY_ARGV);
+ argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
JS_FreeValue(ctx, func_obj);
return res;
}
@@ -18914,7 +18912,7 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx,
return JS_ThrowTypeError(ctx, "not a function");
}
return call_func(ctx, func_obj, new_target, argc,
- argv, flags);
+ (JSValueConst *)argv, flags);
}
b = p->u.func.function_bytecode;
@@ -18943,7 +18941,7 @@ JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
int argc, JSValueConst *argv)
{
return JS_CallConstructorInternal(ctx, func_obj, new_target,
- argc, argv,
+ argc, (JSValue *)argv,
JS_CALL_FLAG_COPY_ARGV);
}
@@ -18951,7 +18949,7 @@ JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
int argc, JSValueConst *argv)
{
return JS_CallConstructorInternal(ctx, func_obj, func_obj,
- argc, argv,
+ argc, (JSValue *)argv,
JS_CALL_FLAG_COPY_ARGV);
}
@@ -18974,26 +18972,35 @@ static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
}
/* JSAsyncFunctionState (used by generator and async functions) */
-static warn_unused int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
- JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
+static JSAsyncFunctionState *async_func_init(JSContext *ctx,
+ JSValueConst func_obj, JSValueConst this_obj,
+ int argc, JSValueConst *argv)
{
+ JSAsyncFunctionState *s;
JSObject *p;
JSFunctionBytecode *b;
JSStackFrame *sf;
int local_count, i, arg_buf_len, n;
+ s = js_mallocz(ctx, sizeof(*s));
+ if (!s)
+ return NULL;
+ s->header.ref_count = 1;
+ add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
+
sf = &s->frame;
init_list_head(&sf->var_ref_list);
p = JS_VALUE_GET_OBJ(func_obj);
b = p->u.func.function_bytecode;
- sf->js_mode = b->js_mode;
+ sf->js_mode = b->js_mode | JS_MODE_ASYNC;
sf->cur_pc = b->byte_code_buf;
arg_buf_len = max_int(b->arg_count, argc);
local_count = arg_buf_len + b->var_count + b->stack_size;
sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * max_int(local_count, 1));
- if (!sf->arg_buf)
- return -1;
+ if (!sf->arg_buf) {
+ js_free(ctx, s);
+ return NULL;
+ }
sf->cur_func = JS_DupValue(ctx, func_obj);
s->this_val = JS_DupValue(ctx, this_obj);
s->argc = argc;
@@ -19005,38 +19012,17 @@ static warn_unused int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
n = arg_buf_len + b->var_count;
for(i = argc; i < n; i++)
sf->arg_buf[i] = JS_UNDEFINED;
- return 0;
-}
-
-static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,
- JS_MarkFunc *mark_func)
-{
- JSStackFrame *sf;
- JSValue *sp;
-
- sf = &s->frame;
- JS_MarkValue(rt, sf->cur_func, mark_func);
- JS_MarkValue(rt, s->this_val, mark_func);
- if (sf->cur_sp) {
- /* if the function is running, cur_sp is not known so we
- cannot mark the stack. Marking the variables is not needed
- because a running function cannot be part of a removable
- cycle */
- for(sp = sf->arg_buf; sp < sf->cur_sp; sp++)
- JS_MarkValue(rt, *sp, mark_func);
- }
+ s->resolving_funcs[0] = JS_UNDEFINED;
+ s->resolving_funcs[1] = JS_UNDEFINED;
+ s->is_completed = FALSE;
+ return s;
}
-static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
+static void async_func_free_frame(JSRuntime *rt, JSAsyncFunctionState *s)
{
- JSStackFrame *sf;
+ JSStackFrame *sf = &s->frame;
JSValue *sp;
- sf = &s->frame;
-
- /* 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);
@@ -19044,6 +19030,7 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
JS_FreeValueRT(rt, *sp);
}
js_free_rt(rt, sf->arg_buf);
+ sf->arg_buf = NULL;
}
JS_FreeValueRT(rt, sf->cur_func);
JS_FreeValueRT(rt, s->this_val);
@@ -19051,17 +19038,66 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s)
{
- JSValue func_obj;
+ JSRuntime *rt = ctx->rt;
+ JSStackFrame *sf = &s->frame;
+ JSValue func_obj, ret;
- if (js_check_stack_overflow(ctx->rt, 0))
- return JS_ThrowStackOverflow(ctx);
+ assert(!s->is_completed);
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ ret = JS_ThrowStackOverflow(ctx);
+ } else {
+ /* the tag does not matter provided it is not an object */
+ func_obj = JS_MKPTR(JS_TAG_INT, s);
+ ret = JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,
+ s->argc, sf->arg_buf, JS_CALL_FLAG_GENERATOR);
+ }
+ if (JS_IsException(ret) || JS_IsUndefined(ret)) {
+ if (JS_IsUndefined(ret)) {
+ ret = sf->cur_sp[-1];
+ sf->cur_sp[-1] = JS_UNDEFINED;
+ }
+ /* end of execution */
+ s->is_completed = TRUE;
+
+ /* close the closure variables. */
+ close_var_refs(rt, sf);
- /* the tag does not matter provided it is not an object */
- func_obj = JS_MKPTR(JS_TAG_INT, s);
- return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,
- s->argc, s->frame.arg_buf, JS_CALL_FLAG_GENERATOR);
+ async_func_free_frame(rt, s);
+ }
+ return ret;
}
+static void __async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
+{
+ /* cannot close the closure variables here because it would
+ potentially modify the object graph */
+ if (!s->is_completed) {
+ async_func_free_frame(rt, s);
+ }
+
+ JS_FreeValueRT(rt, s->resolving_funcs[0]);
+ JS_FreeValueRT(rt, s->resolving_funcs[1]);
+
+ remove_gc_object(&s->header);
+ if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && s->header.ref_count != 0) {
+ list_add_tail(&s->header.link, &rt->gc_zero_ref_count_list);
+ } else {
+ js_free_rt(rt, s);
+ }
+}
+
+static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
+{
+ if (--s->header.ref_count == 0) {
+ if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {
+ list_del(&s->header.link);
+ list_add(&s->header.link, &rt->gc_zero_ref_count_list);
+ if (rt->gc_phase == JS_GC_PHASE_NONE) {
+ free_zero_refcount(rt);
+ }
+ }
+ }
+}
/* Generators */
@@ -19075,14 +19111,17 @@ typedef enum JSGeneratorStateEnum {
typedef struct JSGeneratorData {
JSGeneratorStateEnum state;
- JSAsyncFunctionState func_state;
+ JSAsyncFunctionState *func_state;
} JSGeneratorData;
static void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s)
{
if (s->state == JS_GENERATOR_STATE_COMPLETED)
return;
- async_func_free(rt, &s->func_state);
+ if (s->func_state) {
+ async_func_free(rt, s->func_state);
+ s->func_state = NULL;
+ }
s->state = JS_GENERATOR_STATE_COMPLETED;
}
@@ -19107,9 +19146,9 @@ static void js_generator_mark(JSRuntime *rt, JSValueConst val,
JSObject *p = JS_VALUE_GET_OBJ(val);
JSGeneratorData *s = p->u.generator_data;
- if (!s || s->state == JS_GENERATOR_STATE_COMPLETED)
+ if (!s || !s->func_state)
return;
- async_func_mark(rt, &s->func_state, mark_func);
+ mark_func(rt, &s->func_state->header);
}
/* XXX: use enum */
@@ -19128,10 +19167,10 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
*pdone = TRUE;
if (!s)
return JS_ThrowTypeError(ctx, "not a generator");
- sf = &s->func_state.frame;
switch(s->state) {
default:
case JS_GENERATOR_STATE_SUSPENDED_START:
+ sf = &s->func_state->frame;
if (magic == GEN_MAGIC_NEXT) {
goto exec_no_arg;
} else {
@@ -19141,28 +19180,29 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
break;
case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR:
case JS_GENERATOR_STATE_SUSPENDED_YIELD:
+ sf = &s->func_state->frame;
/* cur_sp[-1] was set to JS_UNDEFINED in the previous call */
ret = JS_DupValue(ctx, argv[0]);
if (magic == GEN_MAGIC_THROW &&
s->state == JS_GENERATOR_STATE_SUSPENDED_YIELD) {
JS_Throw(ctx, ret);
- s->func_state.throw_flag = TRUE;
+ s->func_state->throw_flag = TRUE;
} else {
sf->cur_sp[-1] = ret;
sf->cur_sp[0] = JS_NewInt32(ctx, magic);
sf->cur_sp++;
exec_no_arg:
- s->func_state.throw_flag = FALSE;
+ s->func_state->throw_flag = FALSE;
}
s->state = JS_GENERATOR_STATE_EXECUTING;
- func_ret = async_func_resume(ctx, &s->func_state);
+ func_ret = async_func_resume(ctx, s->func_state);
s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD;
- if (JS_IsException(func_ret)) {
- /* finalize the execution in case of exception */
+ if (s->func_state->is_completed) {
+ /* finalize the execution in case of exception or normal return */
free_generator_stack(ctx, s);
return func_ret;
- }
- if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
+ } else {
+ assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT);
/* get the returned yield value at the top of the stack */
ret = sf->cur_sp[-1];
sf->cur_sp[-1] = JS_UNDEFINED;
@@ -19173,12 +19213,6 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
} else {
*pdone = FALSE;
}
- } else {
- /* end of iterator */
- ret = sf->cur_sp[-1];
- sf->cur_sp[-1] = JS_UNDEFINED;
- JS_FreeValue(ctx, func_ret);
- free_generator_stack(ctx, s);
}
break;
case JS_GENERATOR_STATE_COMPLETED:
@@ -19216,13 +19250,14 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
if (!s)
return JS_EXCEPTION;
s->state = JS_GENERATOR_STATE_SUSPENDED_START;
- if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
+ s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv);
+ if (!s->func_state) {
s->state = JS_GENERATOR_STATE_COMPLETED;
goto fail;
}
/* execute the function up to 'OP_initial_yield' */
- func_ret = async_func_resume(ctx, &s->func_state);
+ func_ret = async_func_resume(ctx, s->func_state);
if (JS_IsException(func_ret))
goto fail;
JS_FreeValue(ctx, func_ret);
@@ -19240,36 +19275,12 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
/* AsyncFunction */
-static void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s)
-{
- if (s->is_active) {
- async_func_free(rt, &s->func_state);
- s->is_active = FALSE;
- }
-}
-
-static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s)
-{
- js_async_function_terminate(rt, s);
- JS_FreeValueRT(rt, s->resolving_funcs[0]);
- JS_FreeValueRT(rt, s->resolving_funcs[1]);
- remove_gc_object(&s->header);
- js_free_rt(rt, s);
-}
-
-static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s)
-{
- if (--s->header.ref_count == 0) {
- js_async_function_free0(rt, s);
- }
-}
-
static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
- JSAsyncFunctionData *s = p->u.async_function_data;
+ JSAsyncFunctionState *s = p->u.async_function_data;
if (s) {
- js_async_function_free(rt, s);
+ async_func_free(rt, s);
}
}
@@ -19277,14 +19288,14 @@ static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
- JSAsyncFunctionData *s = p->u.async_function_data;
+ JSAsyncFunctionState *s = p->u.async_function_data;
if (s) {
mark_func(rt, &s->header);
}
}
static int js_async_function_resolve_create(JSContext *ctx,
- JSAsyncFunctionData *s,
+ JSAsyncFunctionState *s,
JSValue *resolving_funcs)
{
int i;
@@ -19306,60 +19317,58 @@ static int js_async_function_resolve_create(JSContext *ctx,
return 0;
}
-static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
+static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionState *s)
{
JSValue func_ret, ret2;
- func_ret = async_func_resume(ctx, &s->func_state);
- if (JS_IsException(func_ret)) {
- JSValue error;
- fail:
- error = JS_GetException(ctx);
- ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
- 1, &error);
- JS_FreeValue(ctx, error);
- js_async_function_terminate(ctx->rt, s);
- JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
- } else {
- JSValue value;
- value = s->func_state.frame.cur_sp[-1];
- s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
- if (JS_IsUndefined(func_ret)) {
- /* function returned */
- ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
- 1, &value);
+ func_ret = async_func_resume(ctx, s);
+ if (s->is_completed) {
+ if (JS_IsException(func_ret)) {
+ JSValue error;
+ fail:
+ error = JS_GetException(ctx);
+ ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
+ 1, (JSValueConst *)&error);
+ JS_FreeValue(ctx, error);
JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, value);
- js_async_function_terminate(ctx->rt, s);
} else {
- JSValue promise, resolving_funcs[2], resolving_funcs1[2];
- int i, res;
+ /* normal return */
+ ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
+ 1, (JSValueConst *)&func_ret);
+ JS_FreeValue(ctx, func_ret);
+ JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
+ }
+ } else {
+ JSValue value, promise, resolving_funcs[2], resolving_funcs1[2];
+ int i, res;
- /* await */
- JS_FreeValue(ctx, func_ret); /* not used */
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
- 1, &value, 0);
- JS_FreeValue(ctx, value);
- if (JS_IsException(promise))
- goto fail;
- if (js_async_function_resolve_create(ctx, s, resolving_funcs)) {
- JS_FreeValue(ctx, promise);
- goto fail;
- }
+ value = s->frame.cur_sp[-1];
+ s->frame.cur_sp[-1] = JS_UNDEFINED;
- /* Note: no need to create 'thrownawayCapability' as in
- the spec */
- for(i = 0; i < 2; i++)
- resolving_funcs1[i] = JS_UNDEFINED;
- res = perform_promise_then(ctx, promise,
- (JSValueConst *)resolving_funcs,
- (JSValueConst *)resolving_funcs1);
+ /* await */
+ JS_FreeValue(ctx, func_ret); /* not used */
+ promise = js_promise_resolve(ctx, ctx->promise_ctor,
+ 1, (JSValueConst *)&value, 0);
+ JS_FreeValue(ctx, value);
+ if (JS_IsException(promise))
+ goto fail;
+ if (js_async_function_resolve_create(ctx, s, resolving_funcs)) {
JS_FreeValue(ctx, promise);
- for(i = 0; i < 2; i++)
- JS_FreeValue(ctx, resolving_funcs[i]);
- if (res)
- goto fail;
+ goto fail;
}
+
+ /* Note: no need to create 'thrownawayCapability' as in
+ the spec */
+ for(i = 0; i < 2; i++)
+ resolving_funcs1[i] = JS_UNDEFINED;
+ res = perform_promise_then(ctx, promise,
+ (JSValueConst *)resolving_funcs,
+ (JSValueConst *)resolving_funcs1);
+ JS_FreeValue(ctx, promise);
+ for(i = 0; i < 2; i++)
+ JS_FreeValue(ctx, resolving_funcs[i]);
+ if (res)
+ goto fail;
}
}
@@ -19370,7 +19379,7 @@ static JSValue js_async_function_resolve_call(JSContext *ctx,
int flags)
{
JSObject *p = JS_VALUE_GET_OBJ(func_obj);
- JSAsyncFunctionData *s = p->u.async_function_data;
+ JSAsyncFunctionState *s = p->u.async_function_data;
BOOL is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE;
JSValueConst arg;
@@ -19378,12 +19387,12 @@ static JSValue js_async_function_resolve_call(JSContext *ctx,
arg = argv[0];
else
arg = JS_UNDEFINED;
- s->func_state.throw_flag = is_reject;
+ s->throw_flag = is_reject;
if (is_reject) {
JS_Throw(ctx, JS_DupValue(ctx, arg));
} else {
/* return value of await */
- s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);
+ s->frame.cur_sp[-1] = JS_DupValue(ctx, arg);
}
js_async_function_resume(ctx, s);
return JS_UNDEFINED;
@@ -19394,32 +19403,21 @@ static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj,
int argc, JSValueConst *argv, int flags)
{
JSValue promise;
- JSAsyncFunctionData *s;
+ JSAsyncFunctionState *s;
- s = js_mallocz(ctx, sizeof(*s));
+ s = async_func_init(ctx, func_obj, this_obj, argc, argv);
if (!s)
return JS_EXCEPTION;
- s->header.ref_count = 1;
- add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
- s->is_active = FALSE;
- s->resolving_funcs[0] = JS_UNDEFINED;
- s->resolving_funcs[1] = JS_UNDEFINED;
promise = JS_NewPromiseCapability(ctx, s->resolving_funcs);
- if (JS_IsException(promise))
- goto fail;
-
- if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
- fail:
- JS_FreeValue(ctx, promise);
- js_async_function_free(ctx->rt, s);
+ if (JS_IsException(promise)) {
+ async_func_free(ctx->rt, s);
return JS_EXCEPTION;
}
- s->is_active = TRUE;
js_async_function_resume(ctx, s);
- js_async_function_free(ctx->rt, s);
+ async_func_free(ctx->rt, s);
return promise;
}
@@ -19448,7 +19446,8 @@ typedef struct JSAsyncGeneratorRequest {
typedef struct JSAsyncGeneratorData {
JSObject *generator; /* back pointer to the object (const) */
JSAsyncGeneratorStateEnum state;
- JSAsyncFunctionState func_state;
+ /* func_state is NULL is state AWAITING_RETURN and COMPLETED */
+ JSAsyncFunctionState *func_state;
struct list_head queue; /* list of JSAsyncGeneratorRequest.link */
} JSAsyncGeneratorData;
@@ -19466,10 +19465,8 @@ static void js_async_generator_free(JSRuntime *rt,
JS_FreeValueRT(rt, req->resolving_funcs[1]);
js_free_rt(rt, req);
}
- if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&
- s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {
- async_func_free(rt, &s->func_state);
- }
+ if (s->func_state)
+ async_func_free(rt, s->func_state);
js_free_rt(rt, s);
}
@@ -19496,9 +19493,8 @@ static void js_async_generator_mark(JSRuntime *rt, JSValueConst val,
JS_MarkValue(rt, req->resolving_funcs[0], mark_func);
JS_MarkValue(rt, req->resolving_funcs[1], mark_func);
}
- if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&
- s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {
- async_func_mark(rt, &s->func_state, mark_func);
+ if (s->func_state) {
+ mark_func(rt, &s->func_state->header);
}
}
}
@@ -19608,7 +19604,8 @@ static void js_async_generator_complete(JSContext *ctx,
{
if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED) {
s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;
- async_func_free(ctx->rt, &s->func_state);
+ async_func_free(ctx->rt, s->func_state);
+ s->func_state = NULL;
}
}
@@ -19619,10 +19616,19 @@ static int js_async_generator_completed_return(JSContext *ctx,
JSValue promise, resolving_funcs[2], resolving_funcs1[2];
int res;
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
- 1, &value, 0);
- if (JS_IsException(promise))
- return -1;
+ // Can fail looking up JS_ATOM_constructor when is_reject==0.
+ promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, &value,
+ /*is_reject*/0);
+ // A poisoned .constructor property is observable and the resulting
+ // exception should be delivered to the catch handler.
+ if (JS_IsException(promise)) {
+ JSValue err = JS_GetException(ctx);
+ promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, (JSValueConst *)&err,
+ /*is_reject*/1);
+ JS_FreeValue(ctx, err);
+ if (JS_IsException(promise))
+ return -1;
+ }
if (js_async_generator_resolve_function_create(ctx,
JS_MKPTR(JS_TAG_OBJECT, s->generator),
resolving_funcs1,
@@ -19670,7 +19676,6 @@ static void js_async_generator_resume_next(JSContext *ctx,
} else if (next->completion_type == GEN_MAGIC_RETURN) {
s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN;
js_async_generator_completed_return(ctx, s, next->result);
- goto done;
} else {
js_async_generator_reject(ctx, s, next->result);
}
@@ -19681,30 +19686,38 @@ static void js_async_generator_resume_next(JSContext *ctx,
if (next->completion_type == GEN_MAGIC_THROW &&
s->state == JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD) {
JS_Throw(ctx, value);
- s->func_state.throw_flag = TRUE;
+ s->func_state->throw_flag = TRUE;
} else {
/* 'yield' returns a value. 'yield *' also returns a value
in case the 'throw' method is called */
- s->func_state.frame.cur_sp[-1] = value;
- s->func_state.frame.cur_sp[0] =
+ s->func_state->frame.cur_sp[-1] = value;
+ s->func_state->frame.cur_sp[0] =
JS_NewInt32(ctx, next->completion_type);
- s->func_state.frame.cur_sp++;
+ s->func_state->frame.cur_sp++;
exec_no_arg:
- s->func_state.throw_flag = FALSE;
+ s->func_state->throw_flag = FALSE;
}
s->state = JS_ASYNC_GENERATOR_STATE_EXECUTING;
resume_exec:
- func_ret = async_func_resume(ctx, &s->func_state);
- if (JS_IsException(func_ret)) {
- value = JS_GetException(ctx);
- js_async_generator_complete(ctx, s);
- js_async_generator_reject(ctx, s, value);
- JS_FreeValue(ctx, value);
- } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
- int func_ret_code;
- value = s->func_state.frame.cur_sp[-1];
- s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
+ func_ret = async_func_resume(ctx, s->func_state);
+ if (s->func_state->is_completed) {
+ if (JS_IsException(func_ret)) {
+ value = JS_GetException(ctx);
+ js_async_generator_complete(ctx, s);
+ js_async_generator_reject(ctx, s, value);
+ JS_FreeValue(ctx, value);
+ } else {
+ /* end of function */
+ js_async_generator_complete(ctx, s);
+ js_async_generator_resolve(ctx, s, func_ret, TRUE);
+ JS_FreeValue(ctx, func_ret);
+ }
+ } else {
+ int func_ret_code, ret;
+ assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT);
func_ret_code = JS_VALUE_GET_INT(func_ret);
+ value = s->func_state->frame.cur_sp[-1];
+ s->func_state->frame.cur_sp[-1] = JS_UNDEFINED;
switch(func_ret_code) {
case FUNC_RET_YIELD:
case FUNC_RET_YIELD_STAR:
@@ -19716,20 +19729,17 @@ static void js_async_generator_resume_next(JSContext *ctx,
JS_FreeValue(ctx, value);
break;
case FUNC_RET_AWAIT:
- js_async_generator_await(ctx, s, value);
+ ret = js_async_generator_await(ctx, s, value);
JS_FreeValue(ctx, value);
+ if (ret < 0) {
+ /* exception: throw it */
+ s->func_state->throw_flag = TRUE;
+ goto resume_exec;
+ }
goto done;
default:
abort();
}
- } else {
- assert(JS_IsUndefined(func_ret));
- /* end of function */
- value = s->func_state.frame.cur_sp[-1];
- s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
- js_async_generator_complete(ctx, s);
- js_async_generator_resolve(ctx, s, value, TRUE);
- JS_FreeValue(ctx, value);
}
break;
default:
@@ -19763,12 +19773,12 @@ static JSValue js_async_generator_resolve_function(JSContext *ctx,
} else {
/* restart function execution after await() */
assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING);
- s->func_state.throw_flag = is_reject;
+ s->func_state->throw_flag = is_reject;
if (is_reject) {
JS_Throw(ctx, JS_DupValue(ctx, arg));
} else {
/* return value of await */
- s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);
+ s->func_state->frame.cur_sp[-1] = JS_DupValue(ctx, arg);
}
js_async_generator_resume_next(ctx, s);
}
@@ -19792,7 +19802,7 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,
JS_ThrowTypeError(ctx, "not an AsyncGenerator object");
err = JS_GetException(ctx);
res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
- 1, &err);
+ 1, (JSValueConst *)&err);
JS_FreeValue(ctx, err);
JS_FreeValue(ctx, res2);
JS_FreeValue(ctx, resolving_funcs[0]);
@@ -19832,14 +19842,12 @@ static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst fun
return JS_EXCEPTION;
s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_START;
init_list_head(&s->queue);
- if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
- s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;
+ s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv);
+ if (!s->func_state)
goto fail;
- }
-
/* execute the function up to 'OP_initial_yield' (no yield nor
await are possible) */
- func_ret = async_func_resume(ctx, &s->func_state);
+ func_ret = async_func_resume(ctx, s->func_state);
if (JS_IsException(func_ret))
goto fail;
JS_FreeValue(ctx, func_ret);
@@ -20025,6 +20033,7 @@ typedef enum JSParseFunctionEnum {
JS_PARSE_FUNC_GETTER,
JS_PARSE_FUNC_SETTER,
JS_PARSE_FUNC_METHOD,
+ JS_PARSE_FUNC_CLASS_STATIC_INIT,
JS_PARSE_FUNC_CLASS_CONSTRUCTOR,
JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR,
} JSParseFunctionEnum;
@@ -20144,6 +20153,7 @@ typedef struct JSFunctionDef {
int source_len;
JSModuleDef *module; /* != NULL when parsing a module */
+ BOOL has_await; /* TRUE if await is used (used in module eval) */
} JSFunctionDef;
typedef struct JSToken {
@@ -20227,16 +20237,14 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {
#define short_opcode_info(op) opcode_info[op]
#endif
-static warn_unused int next_token(JSParseState *s);
+static __exception int next_token(JSParseState *s);
static void free_token(JSParseState *s, JSToken *token)
{
switch(token->val) {
-#ifdef CONFIG_BIGNUM
case TOK_NUMBER:
JS_FreeValue(s->ctx, token->u.num.val);
break;
-#endif
case TOK_STRING:
case TOK_TEMPLATE:
JS_FreeValue(s->ctx, token->u.str.str);
@@ -20258,7 +20266,7 @@ static void free_token(JSParseState *s, JSToken *token)
}
}
-static void maybe_unused dump_token(JSParseState *s,
+static void __maybe_unused dump_token(JSParseState *s,
const JSToken *token)
{
switch(token->val) {
@@ -20365,7 +20373,7 @@ static int js_parse_error_reserved_identifier(JSParseState *s)
s->token.u.ident.atom));
}
-static warn_unused int js_parse_template_part(JSParseState *s, const uint8_t *p)
+static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
{
uint32_t c;
StringBuffer b_s, *b = &b_s;
@@ -20426,7 +20434,7 @@ static warn_unused int js_parse_template_part(JSParseState *s, const uint8_t *p)
return -1;
}
-static warn_unused int js_parse_string(JSParseState *s, int sep,
+static __exception int js_parse_string(JSParseState *s, int sep,
BOOL do_throw, const uint8_t *p,
JSToken *token, const uint8_t **pp)
{
@@ -20571,7 +20579,7 @@ static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) {
!s->token.u.ident.has_escape;
}
-static warn_unused int js_parse_regexp(JSParseState *s)
+static __exception int js_parse_regexp(JSParseState *s)
{
const uint8_t *p;
BOOL in_class;
@@ -20669,7 +20677,7 @@ static warn_unused int js_parse_regexp(JSParseState *s)
return -1;
}
-static warn_unused int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
+static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
const char *static_buf)
{
char *buf, *new_buf;
@@ -20696,6 +20704,48 @@ static warn_unused int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
return 0;
}
+/* convert a TOK_IDENT to a keyword when needed */
+static void update_token_ident(JSParseState *s)
+{
+ if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
+ (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
+ (s->cur_func->js_mode & JS_MODE_STRICT)) ||
+ (s->token.u.ident.atom == JS_ATOM_yield &&
+ ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
+ (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
+ !s->cur_func->in_function_body && s->cur_func->parent &&
+ (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
+ (s->token.u.ident.atom == JS_ATOM_await &&
+ (s->is_module ||
+ (s->cur_func->func_kind & JS_FUNC_ASYNC) ||
+ s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT ||
+ (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
+ !s->cur_func->in_function_body && s->cur_func->parent &&
+ ((s->cur_func->parent->func_kind & JS_FUNC_ASYNC) ||
+ s->cur_func->parent->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))))) {
+ if (s->token.u.ident.has_escape) {
+ s->token.u.ident.is_reserved = TRUE;
+ s->token.val = TOK_IDENT;
+ } else {
+ /* The keywords atoms are pre allocated */
+ s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
+ }
+ }
+}
+
+/* if the current token is an identifier or keyword, reparse it
+ according to the current function type */
+static void reparse_ident_token(JSParseState *s)
+{
+ if (s->token.val == TOK_IDENT ||
+ (s->token.val >= TOK_FIRST_KEYWORD &&
+ s->token.val <= TOK_LAST_KEYWORD)) {
+ s->token.val = TOK_IDENT;
+ s->token.u.ident.is_reserved = FALSE;
+ update_token_ident(s);
+ }
+}
+
/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
BOOL *pident_has_escape, int c, BOOL is_private)
@@ -20745,7 +20795,7 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
}
-static warn_unused int next_token(JSParseState *s)
+static __exception int next_token(JSParseState *s)
{
const uint8_t *p;
int c;
@@ -20902,30 +20952,8 @@ static warn_unused int next_token(JSParseState *s)
s->token.u.ident.atom = atom;
s->token.u.ident.has_escape = ident_has_escape;
s->token.u.ident.is_reserved = FALSE;
- if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
- (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
- (s->cur_func->js_mode & JS_MODE_STRICT)) ||
- (s->token.u.ident.atom == JS_ATOM_yield &&
- ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
- (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
- !s->cur_func->in_function_body && s->cur_func->parent &&
- (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
- (s->token.u.ident.atom == JS_ATOM_await &&
- (s->is_module ||
- (((s->cur_func->func_kind & JS_FUNC_ASYNC) ||
- (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
- !s->cur_func->in_function_body && s->cur_func->parent &&
- (s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) {
- if (ident_has_escape) {
- s->token.u.ident.is_reserved = TRUE;
- s->token.val = TOK_IDENT;
- } else {
- /* The keywords atoms are pre allocated */
- s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
- }
- } else {
- s->token.val = TOK_IDENT;
- }
+ s->token.val = TOK_IDENT;
+ update_token_ident(s);
break;
case '#':
/* private name */
@@ -20982,8 +21010,8 @@ static warn_unused int next_token(JSParseState *s)
int flags, radix;
flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL |
ATOD_ACCEPT_UNDERSCORES;
-#ifdef CONFIG_BIGNUM
flags |= ATOD_ACCEPT_SUFFIX;
+#ifdef CONFIG_BIGNUM
if (s->cur_func->js_mode & JS_MODE_MATH) {
flags |= ATOD_MODE_BIGINT;
if (s->cur_func->js_mode & JS_MODE_MATH)
@@ -21274,8 +21302,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
for(;;) {
buf[ident_pos++] = c;
c = *p;
- if (c >= 128 ||
- !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1))
+ if (c >= 128 || !lre_is_id_continue_byte(c))
break;
p++;
if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {
@@ -21293,7 +21320,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
return atom;
}
-static warn_unused int json_next_token(JSParseState *s)
+static __exception int json_next_token(JSParseState *s)
{
const uint8_t *p;
int c;
@@ -21487,9 +21514,29 @@ static warn_unused int json_next_token(JSParseState *s)
return -1;
}
-/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is
- only set if TOK_IMPORT is returned */
-/* XXX: handle all unicode cases */
+static int match_identifier(const uint8_t *p, const char *s) {
+ uint32_t c;
+ while (*s) {
+ if ((uint8_t)*s++ != *p++)
+ return 0;
+ }
+ c = *p;
+ if (c >= 128)
+ c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ return !lre_js_is_ident_next(c);
+}
+
+/* simple_next_token() is used to check for the next token in simple cases.
+ It is only used for ':' and '=>', 'let' or 'function' look-ahead.
+ (*pp) is only set if TOK_IMPORT is returned for JS_DetectModule()
+ Whitespace and comments are skipped correctly.
+ Then the next token is analyzed, only for specific words.
+ Return values:
+ - '\n' if !no_line_terminator
+ - TOK_ARROW, TOK_IN, TOK_IMPORT, TOK_OF, TOK_EXPORT, TOK_FUNCTION
+ - TOK_IDENT is returned for other identifiers and keywords
+ - otherwise the next character or unicode codepoint is returned.
+ */
static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator)
{
const uint8_t *p;
@@ -21533,33 +21580,42 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator)
if (*p == '>')
return TOK_ARROW;
break;
+ case 'i':
+ if (match_identifier(p, "n"))
+ return TOK_IN;
+ if (match_identifier(p, "mport")) {
+ *pp = p + 5;
+ return TOK_IMPORT;
+ }
+ return TOK_IDENT;
+ case 'o':
+ if (match_identifier(p, "f"))
+ return TOK_OF;
+ return TOK_IDENT;
+ case 'e':
+ if (match_identifier(p, "xport"))
+ return TOK_EXPORT;
+ return TOK_IDENT;
+ case 'f':
+ if (match_identifier(p, "unction"))
+ return TOK_FUNCTION;
+ return TOK_IDENT;
+ case '\\':
+ if (*p == 'u') {
+ if (lre_js_is_ident_first(lre_parse_escape(&p, TRUE)))
+ return TOK_IDENT;
+ }
+ break;
default:
- if (lre_js_is_ident_first(c)) {
- if (c == 'i') {
- if (p[0] == 'n' && !lre_js_is_ident_next(p[1])) {
- return TOK_IN;
- }
- if (p[0] == 'm' && p[1] == 'p' && p[2] == 'o' &&
- p[3] == 'r' && p[4] == 't' &&
- !lre_js_is_ident_next(p[5])) {
- *pp = p + 5;
- return TOK_IMPORT;
- }
- } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) {
- return TOK_OF;
- } else if (c == 'e' &&
- p[0] == 'x' && p[1] == 'p' && p[2] == 'o' &&
- p[3] == 'r' && p[4] == 't' &&
- !lre_js_is_ident_next(p[5])) {
- *pp = p + 5;
- return TOK_EXPORT;
- } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' &&
- p[2] == 'c' && p[3] == 't' && p[4] == 'i' &&
- p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) {
- return TOK_FUNCTION;
- }
- return TOK_IDENT;
+ if (c >= 128) {
+ c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p);
+ if (no_line_terminator && (c == CP_PS || c == CP_LS))
+ return '\n';
}
+ if (lre_is_space(c))
+ continue;
+ if (lre_js_is_ident_first(c))
+ return TOK_IDENT;
break;
}
return c;
@@ -21572,6 +21628,31 @@ static int peek_token(JSParseState *s, BOOL no_line_terminator)
return simple_next_token(&p, no_line_terminator);
}
+static void skip_shebang(const uint8_t **pp, const uint8_t *buf_end)
+{
+ const uint8_t *p = *pp;
+ int c;
+
+ if (p[0] == '#' && p[1] == '!') {
+ p += 2;
+ while (p < buf_end) {
+ if (*p == '\n' || *p == '\r') {
+ break;
+ } else if (*p >= 0x80) {
+ c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ if (c == CP_LS || c == CP_PS) {
+ break;
+ } else if (c == -1) {
+ p++; /* skip invalid UTF-8 */
+ }
+ } else {
+ p++;
+ }
+ }
+ *pp = p;
+ }
+}
+
/* return true if 'input' contains the source of a module
(heuristic). 'input' must be a zero terminated.
@@ -21582,6 +21663,8 @@ BOOL JS_DetectModule(const char *input, size_t input_len)
{
const uint8_t *p = (const uint8_t *)input;
int tok;
+
+ skip_shebang(&p, p + input_len);
switch(simple_next_token(&p, FALSE)) {
case TOK_IMPORT:
tok = simple_next_token(&p, FALSE);
@@ -21694,6 +21777,14 @@ static int new_label(JSParseState *s)
return new_label_fd(s->cur_func, -1);
}
+/* don't update the last opcode and don't emit line number info */
+static void emit_label_raw(JSParseState *s, int label)
+{
+ emit_u8(s, OP_label);
+ emit_u32(s, label);
+ s->cur_func->label_slots[label].pos = s->cur_func->byte_code.size;
+}
+
/* return the label ID offset */
static int emit_label(JSParseState *s, int label)
{
@@ -21733,7 +21824,7 @@ static int cpool_add(JSParseState *s, JSValue val)
return fd->cpool_count - 1;
}
-static warn_unused int emit_push_const(JSParseState *s, JSValueConst val,
+static __exception int emit_push_const(JSParseState *s, JSValueConst val,
BOOL as_atom)
{
int idx;
@@ -21743,7 +21834,7 @@ static warn_unused int emit_push_const(JSParseState *s, JSValueConst val,
/* warning: JS_NewAtomStr frees the string value */
JS_DupValue(s->ctx, val);
atom = JS_NewAtomStr(s->ctx, JS_VALUE_GET_STRING(val));
- if (atom != JS_ATOM_NULL && !JS_AtomIsTaggedInt(atom)) {
+ if (atom != JS_ATOM_NULL && !__JS_AtomIsTaggedInt(atom)) {
emit_op(s, OP_push_atom_value);
emit_u32(s, atom);
return 0;
@@ -22192,7 +22283,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
/* add a private field variable in the current scope */
static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,
- JSAtom name, JSVarKindEnum var_kind)
+ JSAtom name, JSVarKindEnum var_kind, BOOL is_static)
{
JSContext *ctx = s->ctx;
JSVarDef *vd;
@@ -22204,17 +22295,18 @@ static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,
vd = &fd->vars[idx];
vd->is_lexical = 1;
vd->is_const = 1;
+ vd->is_static_private = is_static;
return idx;
}
-static warn_unused int js_parse_expr(JSParseState *s);
-static warn_unused int js_parse_function_decl(JSParseState *s,
+static __exception int js_parse_expr(JSParseState *s);
+static __exception int js_parse_function_decl(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name, const uint8_t *ptr,
int start_line);
static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s);
-static warn_unused int js_parse_function_decl2(JSParseState *s,
+static __exception int js_parse_function_decl2(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name,
@@ -22222,9 +22314,9 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
int function_line_num,
JSParseExportEnum export_flag,
JSFunctionDef **pfd);
-static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags);
-static warn_unused int js_parse_assign_expr(JSParseState *s);
-static warn_unused int js_parse_unary(JSParseState *s, int parse_flags);
+static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags);
+static __exception int js_parse_assign_expr(JSParseState *s);
+static __exception int js_parse_unary(JSParseState *s, int parse_flags);
static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
JSAtom label_name,
int label_break, int label_cont,
@@ -22251,7 +22343,7 @@ static int seal_template_obj(JSContext *ctx, JSValueConst obj)
return 0;
}
-static warn_unused int js_parse_template(JSParseState *s, int call, int *argc)
+static __exception int js_parse_template(JSParseState *s, int call, int *argc)
{
JSContext *ctx = s->ctx;
JSValue raw_array, template_object;
@@ -22382,7 +22474,7 @@ static BOOL token_is_ident(int tok)
}
/* if the property is an expression, name = JS_ATOM_NULL */
-static int warn_unused js_parse_property_name(JSParseState *s,
+static int __exception js_parse_property_name(JSParseState *s,
JSAtom *pname,
BOOL allow_method, BOOL allow_var,
BOOL allow_private)
@@ -22401,7 +22493,8 @@ static int warn_unused js_parse_property_name(JSParseState *s,
if (next_token(s))
goto fail1;
if (s->token.val == ':' || s->token.val == ',' ||
- s->token.val == '}' || s->token.val == '(') {
+ s->token.val == '}' || s->token.val == '(' ||
+ s->token.val == '=') {
is_non_reserved_ident = TRUE;
goto ident_found;
}
@@ -22417,7 +22510,8 @@ static int warn_unused js_parse_property_name(JSParseState *s,
if (next_token(s))
goto fail1;
if (s->token.val == ':' || s->token.val == ',' ||
- s->token.val == '}' || s->token.val == '(') {
+ s->token.val == '}' || s->token.val == '(' ||
+ s->token.val == '=') {
is_non_reserved_ident = TRUE;
goto ident_found;
}
@@ -22524,7 +22618,7 @@ static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)
return 0;
}
-static warn_unused int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
+static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
{
s->token.line_num = sp->last_line_num;
s->line_num = sp->line_num;
@@ -22730,7 +22824,7 @@ static void set_object_name_computed(JSParseState *s)
}
}
-static warn_unused int js_parse_object_literal(JSParseState *s)
+static __exception int js_parse_object_literal(JSParseState *s)
{
JSAtom name = JS_ATOM_NULL;
const uint8_t *start_ptr;
@@ -22848,22 +22942,20 @@ static warn_unused int js_parse_object_literal(JSParseState *s)
#define PF_IN_ACCEPTED (1 << 0)
/* allow function calls parsing in js_parse_postfix_expr() */
#define PF_POSTFIX_CALL (1 << 1)
-/* allow arrow functions parsing in js_parse_postfix_expr() */
-#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 << 2)
/* forbid the exponentiation operator in js_parse_unary() */
-#define PF_POW_FORBIDDEN (1 << 4)
+#define PF_POW_FORBIDDEN (1 << 3)
-static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags);
+static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);
-static warn_unused int js_parse_left_hand_side_expr(JSParseState *s)
+static __exception int js_parse_left_hand_side_expr(JSParseState *s)
{
return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
}
/* XXX: could generate specific bytecode */
-static warn_unused int js_parse_class_default_ctor(JSParseState *s,
+static __exception int js_parse_class_default_ctor(JSParseState *s,
BOOL has_super,
JSFunctionDef **pfd)
{
@@ -22950,11 +23042,12 @@ static JSAtom get_private_setter_name(JSContext *ctx, JSAtom name)
typedef struct {
JSFunctionDef *fields_init_fd;
int computed_fields_count;
- BOOL has_brand;
+ BOOL need_brand;
int brand_push_pos;
+ BOOL is_static;
} ClassFieldsDef;
-static warn_unused int emit_class_init_start(JSParseState *s,
+static __exception int emit_class_init_start(JSParseState *s,
ClassFieldsDef *cf)
{
int label_add_brand;
@@ -22965,41 +23058,27 @@ static warn_unused int emit_class_init_start(JSParseState *s,
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);
+ if (!cf->is_static) {
+ /* add the brand to the newly created instance */
+ /* 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_home_object);
- emit_u16(s, 0);
-
- emit_op(s, OP_add_brand);
-
- emit_label(s, label_add_brand);
+ emit_op(s, OP_scope_get_var);
+ emit_atom(s, JS_ATOM_this);
+ emit_u16(s, 0);
- s->cur_func = s->cur_func->parent;
- return 0;
-}
+ emit_op(s, OP_scope_get_var);
+ emit_atom(s, JS_ATOM_home_object);
+ emit_u16(s, 0);
-static warn_unused int add_brand(JSParseState *s, ClassFieldsDef *cf)
-{
- if (!cf->has_brand) {
- /* define the brand field in 'this' of the initializer */
- if (!cf->fields_init_fd) {
- if (emit_class_init_start(s, cf))
- return -1;
- }
- /* 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;
+ emit_op(s, OP_add_brand);
- cf->has_brand = TRUE;
+ emit_label(s, label_add_brand);
}
+ s->cur_func = s->cur_func->parent;
return 0;
}
@@ -23019,7 +23098,7 @@ static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)
}
-static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
+static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
JSParseExportEnum export_flag)
{
JSContext *ctx = s->ctx;
@@ -23106,7 +23185,8 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
ClassFieldsDef *cf = &class_fields[i];
cf->fields_init_fd = NULL;
cf->computed_fields_count = 0;
- cf->has_brand = FALSE;
+ cf->need_brand = FALSE;
+ cf->is_static = i;
}
ctor_fd = NULL;
@@ -23116,11 +23196,51 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
continue;
}
- is_static = (s->token.val == TOK_STATIC);
+ is_static = FALSE;
+ if (s->token.val == TOK_STATIC) {
+ int next = peek_token(s, TRUE);
+ if (!(next == ';' || next == '}' || next == '(' || next == '='))
+ is_static = TRUE;
+ }
prop_type = -1;
if (is_static) {
if (next_token(s))
goto fail;
+ if (s->token.val == '{') {
+ ClassFieldsDef *cf = &class_fields[is_static];
+ JSFunctionDef *init;
+ if (!cf->fields_init_fd) {
+ if (emit_class_init_start(s, cf))
+ goto fail;
+ }
+ s->cur_func = cf->fields_init_fd;
+ /* XXX: could try to avoid creating a new function and
+ reuse 'fields_init_fd' with a specific 'var'
+ scope */
+ // stack is now: <empty>
+ if (js_parse_function_decl2(s, JS_PARSE_FUNC_CLASS_STATIC_INIT,
+ JS_FUNC_NORMAL, JS_ATOM_NULL,
+ s->token.ptr, s->token.line_num,
+ JS_PARSE_EXPORT_NONE, &init) < 0) {
+ goto fail;
+ }
+ // stack is now: fclosure
+ push_scope(s);
+ emit_op(s, OP_scope_get_var);
+ emit_atom(s, JS_ATOM_this);
+ emit_u16(s, 0);
+ // stack is now: fclosure this
+ emit_op(s, OP_swap);
+ // stack is now: this fclosure
+ emit_op(s, OP_call_method);
+ emit_u16(s, 0);
+ // stack is now: returnvalue
+ emit_op(s, OP_drop);
+ // stack is now: <empty>
+ pop_scope(s);
+ s->cur_func = s->cur_func->parent;
+ continue;
+ }
/* allow "static" field name */
if (s->token.val == ';' || s->token.val == '=') {
is_static = FALSE;
@@ -23151,24 +23271,26 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
JSFunctionDef *method_fd;
if (is_private) {
- int idx, var_kind;
+ int idx, var_kind, is_static1;
idx = find_private_class_field(ctx, fd, name, fd->scope_level);
if (idx >= 0) {
var_kind = fd->vars[idx].var_kind;
+ is_static1 = fd->vars[idx].is_static_private;
if (var_kind == JS_VAR_PRIVATE_FIELD ||
var_kind == JS_VAR_PRIVATE_METHOD ||
var_kind == JS_VAR_PRIVATE_GETTER_SETTER ||
- var_kind == (JS_VAR_PRIVATE_GETTER + is_set)) {
+ var_kind == (JS_VAR_PRIVATE_GETTER + is_set) ||
+ (var_kind == (JS_VAR_PRIVATE_GETTER + 1 - is_set) &&
+ is_static != is_static1)) {
goto private_field_already_defined;
}
fd->vars[idx].var_kind = JS_VAR_PRIVATE_GETTER_SETTER;
} else {
if (add_private_class_field(s, fd, name,
- JS_VAR_PRIVATE_GETTER + is_set) < 0)
+ JS_VAR_PRIVATE_GETTER + is_set, is_static) < 0)
goto fail;
}
- if (add_brand(s, &class_fields[is_static]) < 0)
- goto fail;
+ class_fields[is_static].need_brand = TRUE;
}
if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set,
@@ -23190,7 +23312,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
emit_atom(s, setter_name);
ret = add_private_class_field(s, fd, setter_name,
- JS_VAR_PRIVATE_SETTER);
+ JS_VAR_PRIVATE_SETTER, is_static);
JS_FreeAtom(ctx, setter_name);
if (ret < 0)
goto fail;
@@ -23225,7 +23347,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto private_field_already_defined;
}
if (add_private_class_field(s, fd, name,
- JS_VAR_PRIVATE_FIELD) < 0)
+ JS_VAR_PRIVATE_FIELD, is_static) < 0)
goto fail;
emit_op(s, OP_private_symbol);
emit_atom(s, name);
@@ -23315,8 +23437,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
}
if (is_private) {
- if (add_brand(s, &class_fields[is_static]) < 0)
- goto fail;
+ class_fields[is_static].need_brand = TRUE;
}
if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, start_ptr, s->token.line_num, JS_PARSE_EXPORT_NONE, &method_fd))
goto fail;
@@ -23332,7 +23453,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
}
if (add_private_class_field(s, fd, name,
- JS_VAR_PRIVATE_METHOD) < 0)
+ JS_VAR_PRIVATE_METHOD, is_static) < 0)
goto fail;
emit_op(s, OP_set_home_object);
emit_op(s, OP_set_name);
@@ -23382,12 +23503,29 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
if (next_token(s))
goto fail;
- /* store the function to initialize the fields to that it can be
- referenced by the constructor */
{
ClassFieldsDef *cf = &class_fields[0];
int var_idx;
+ if (cf->need_brand) {
+ /* add a private brand to the prototype */
+ emit_op(s, OP_dup);
+ emit_op(s, OP_null);
+ emit_op(s, OP_swap);
+ emit_op(s, OP_add_brand);
+
+ /* define the brand field in 'this' of the initializer */
+ if (!cf->fields_init_fd) {
+ if (emit_class_init_start(s, cf))
+ goto fail;
+ }
+ /* patch the start of the function to enable the
+ OP_add_brand_instance code */
+ cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true;
+ }
+
+ /* store the function to initialize the fields to that it can be
+ referenced by the constructor */
var_idx = define_var(s, fd, JS_ATOM_class_fields_init,
JS_VAR_DEF_CONST);
if (var_idx < 0)
@@ -23405,14 +23543,11 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
/* drop the prototype */
emit_op(s, OP_drop);
- /* initialize the static fields */
- if (class_fields[1].fields_init_fd != NULL) {
- ClassFieldsDef *cf = &class_fields[1];
+ if (class_fields[1].need_brand) {
+ /* add a private brand to the class */
emit_op(s, OP_dup);
- emit_class_init_end(s, cf);
- emit_op(s, OP_call_method);
- emit_u16(s, 0);
- emit_op(s, OP_drop);
+ emit_op(s, OP_dup);
+ emit_op(s, OP_add_brand);
}
if (class_name != JS_ATOM_NULL) {
@@ -23424,6 +23559,17 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
emit_atom(s, class_name);
emit_u16(s, fd->scope_level);
}
+
+ /* initialize the static fields */
+ if (class_fields[1].fields_init_fd != NULL) {
+ ClassFieldsDef *cf = &class_fields[1];
+ emit_op(s, OP_dup);
+ emit_class_init_end(s, cf);
+ emit_op(s, OP_call_method);
+ emit_u16(s, 0);
+ emit_op(s, OP_drop);
+ }
+
pop_scope(s);
pop_scope(s);
@@ -23464,7 +23610,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
return -1;
}
-static warn_unused int js_parse_array_literal(JSParseState *s)
+static __exception int js_parse_array_literal(JSParseState *s)
{
uint32_t idx;
BOOL need_length;
@@ -23500,7 +23646,7 @@ static warn_unused int js_parse_array_literal(JSParseState *s)
if (js_parse_assign_expr(s))
return -1;
emit_op(s, OP_define_field);
- emit_u32(s, JS_AtomFromUInt32(idx));
+ emit_u32(s, __JS_AtomFromUInt32(idx));
need_length = FALSE;
}
idx++;
@@ -23610,7 +23756,7 @@ static BOOL has_with_scope(JSFunctionDef *s, int scope_level)
return FALSE;
}
-static warn_unused int get_lvalue(JSParseState *s, int *popcode, int *pscope,
+static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
JSAtom *pname, int *plabel, int *pdepth, BOOL keep,
int tok)
{
@@ -23850,7 +23996,7 @@ static void put_lvalue(JSParseState *s, int opcode, int scope,
}
}
-static warn_unused int js_parse_expr_paren(JSParseState *s)
+static __exception int js_parse_expr_paren(JSParseState *s)
{
if (js_parse_expect(s, '('))
return -1;
@@ -23868,7 +24014,7 @@ static int js_unsupported_keyword(JSParseState *s, JSAtom atom)
JS_AtomGetStr(s->ctx, buf, sizeof(buf), atom));
}
-static warn_unused int js_define_var(JSParseState *s, JSAtom name, int tok)
+static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
{
JSFunctionDef *fd = s->cur_func;
JSVarDefEnum var_def_type;
@@ -24416,8 +24562,8 @@ static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,
emit_label(s, label_next);
}
-/* allowed parse_flags: PF_POSTFIX_CALL, PF_ARROW_FUNC */
-static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
+/* allowed parse_flags: PF_POSTFIX_CALL */
+static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
{
FuncCallType call_type;
int optional_chaining_label;
@@ -24519,16 +24665,8 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
}
break;
case '(':
- if ((parse_flags & PF_ARROW_FUNC) &&
- js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
- if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
- JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num))
- return -1;
- } else {
- if (js_parse_expr_paren(s))
- return -1;
- }
+ if (js_parse_expr_paren(s))
+ return -1;
break;
case TOK_FUNCTION:
if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,
@@ -24568,14 +24706,8 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
if (s->token.u.ident.is_reserved) {
return js_parse_error_reserved_identifier(s);
}
- if ((parse_flags & PF_ARROW_FUNC) &&
- peek_token(s, TRUE) == TOK_ARROW) {
- if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
- JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num))
- return -1;
- } else if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) != '\n') {
+ if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
+ peek_token(s, TRUE) != '\n') {
const uint8_t *source_ptr;
int source_line_num;
@@ -24588,15 +24720,6 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
JS_FUNC_ASYNC, JS_ATOM_NULL,
source_ptr, source_line_num))
return -1;
- } else if ((parse_flags & PF_ARROW_FUNC) &&
- ((s->token.val == '(' &&
- js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
- (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
- peek_token(s, TRUE) == TOK_ARROW))) {
- if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
- JS_FUNC_ASYNC, JS_ATOM_NULL,
- source_ptr, source_line_num))
- return -1;
} else {
name = JS_DupAtom(s->ctx, JS_ATOM_async);
goto do_get_var;
@@ -24608,8 +24731,10 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
return -1;
}
name = JS_DupAtom(s->ctx, s->token.u.ident.atom);
- if (next_token(s)) /* update line number before emitting code */
+ if (next_token(s)) { /* update line number before emitting code */
+ JS_FreeAtom(s->ctx, name);
return -1;
+ }
do_get_var:
emit_op(s, OP_scope_get_var);
emit_u32(s, name);
@@ -24756,6 +24881,25 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
fd->byte_code.buf[fd->last_opcode_pos] = OP_get_field2;
drop_count = 2;
break;
+ case OP_get_field_opt_chain:
+ {
+ int opt_chain_label, next_label;
+ opt_chain_label = get_u32(fd->byte_code.buf +
+ fd->last_opcode_pos + 1 + 4 + 1);
+ /* keep the object on the stack */
+ fd->byte_code.buf[fd->last_opcode_pos] = OP_get_field2;
+ fd->byte_code.size = fd->last_opcode_pos + 1 + 4;
+ next_label = emit_goto(s, OP_goto, -1);
+ emit_label(s, opt_chain_label);
+ /* need an additional undefined value for the
+ case where the optional field does not
+ exists */
+ emit_op(s, OP_undefined);
+ emit_label(s, next_label);
+ drop_count = 2;
+ opcode = OP_get_field;
+ }
+ break;
case OP_scope_get_private_field:
/* keep the object on the stack */
fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_get_private_field2;
@@ -24766,6 +24910,25 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el2;
drop_count = 2;
break;
+ case OP_get_array_el_opt_chain:
+ {
+ int opt_chain_label, next_label;
+ opt_chain_label = get_u32(fd->byte_code.buf +
+ fd->last_opcode_pos + 1 + 1);
+ /* keep the object on the stack */
+ fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el2;
+ fd->byte_code.size = fd->last_opcode_pos + 1;
+ next_label = emit_goto(s, OP_goto, -1);
+ emit_label(s, opt_chain_label);
+ /* need an additional undefined value for the
+ case where the optional field does not
+ exists */
+ emit_op(s, OP_undefined);
+ emit_label(s, next_label);
+ drop_count = 2;
+ opcode = OP_get_array_el;
+ }
+ break;
case OP_scope_get_var:
{
JSAtom name;
@@ -25048,43 +25211,89 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
break;
}
}
- if (optional_chaining_label >= 0)
- emit_label(s, optional_chaining_label);
+ if (optional_chaining_label >= 0) {
+ JSFunctionDef *fd = s->cur_func;
+ int opcode;
+ emit_label_raw(s, optional_chaining_label);
+ /* modify the last opcode so that it is an indicator of an
+ optional chain */
+ opcode = get_prev_opcode(fd);
+ if (opcode == OP_get_field || opcode == OP_get_array_el) {
+ if (opcode == OP_get_field)
+ opcode = OP_get_field_opt_chain;
+ else
+ opcode = OP_get_array_el_opt_chain;
+ fd->byte_code.buf[fd->last_opcode_pos] = opcode;
+ } else {
+ fd->last_opcode_pos = -1;
+ }
+ }
return 0;
}
-static warn_unused int js_parse_delete(JSParseState *s)
+static __exception int js_parse_delete(JSParseState *s)
{
JSFunctionDef *fd = s->cur_func;
JSAtom name;
+ int opcode;
if (next_token(s))
return -1;
if (js_parse_unary(s, PF_POW_FORBIDDEN))
return -1;
- switch (get_prev_opcode(fd)) {
+ switch(opcode = get_prev_opcode(fd)) {
case OP_get_field:
+ case OP_get_field_opt_chain:
{
JSValue val;
- int ret;
-
+ int ret, opt_chain_label, next_label;
+ if (opcode == OP_get_field_opt_chain) {
+ opt_chain_label = get_u32(fd->byte_code.buf +
+ fd->last_opcode_pos + 1 + 4 + 1);
+ } else {
+ opt_chain_label = -1;
+ }
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
fd->byte_code.size = fd->last_opcode_pos;
- fd->last_opcode_pos = -1;
val = JS_AtomToValue(s->ctx, name);
ret = emit_push_const(s, val, 1);
JS_FreeValue(s->ctx, val);
JS_FreeAtom(s->ctx, name);
if (ret)
return ret;
+ emit_op(s, OP_delete);
+ if (opt_chain_label >= 0) {
+ next_label = emit_goto(s, OP_goto, -1);
+ emit_label(s, opt_chain_label);
+ /* if the optional chain is not taken, return 'true' */
+ emit_op(s, OP_drop);
+ emit_op(s, OP_push_true);
+ emit_label(s, next_label);
+ }
+ fd->last_opcode_pos = -1;
}
- goto do_delete;
+ break;
case OP_get_array_el:
fd->byte_code.size = fd->last_opcode_pos;
fd->last_opcode_pos = -1;
- do_delete:
emit_op(s, OP_delete);
break;
+ case OP_get_array_el_opt_chain:
+ {
+ int opt_chain_label, next_label;
+ opt_chain_label = get_u32(fd->byte_code.buf +
+ fd->last_opcode_pos + 1 + 1);
+ fd->byte_code.size = fd->last_opcode_pos;
+ emit_op(s, OP_delete);
+ next_label = emit_goto(s, OP_goto, -1);
+ emit_label(s, opt_chain_label);
+ /* if the optional chain is not taken, return 'true' */
+ emit_op(s, OP_drop);
+ emit_op(s, OP_push_true);
+ emit_label(s, next_label);
+ fd->last_opcode_pos = -1;
+ }
+ break;
case OP_scope_get_var:
/* 'delete this': this is not a reference */
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
@@ -25099,6 +25308,8 @@ static warn_unused int js_parse_delete(JSParseState *s)
case OP_scope_get_private_field:
return js_parse_error(s, "cannot delete a private class field");
case OP_get_super_value:
+ fd->byte_code.size = fd->last_opcode_pos;
+ fd->last_opcode_pos = -1;
emit_op(s, OP_throw_error);
emit_atom(s, JS_ATOM_NULL);
emit_u8(s, JS_THROW_ERROR_DELETE_SUPER);
@@ -25112,8 +25323,8 @@ static warn_unused int js_parse_delete(JSParseState *s)
return 0;
}
-/* allowed parse_flags: PF_ARROW_FUNC, PF_POW_ALLOWED, PF_POW_FORBIDDEN */
-static warn_unused int js_parse_unary(JSParseState *s, int parse_flags)
+/* allowed parse_flags: PF_POW_ALLOWED, PF_POW_FORBIDDEN */
+static __exception int js_parse_unary(JSParseState *s, int parse_flags)
{
int op;
@@ -25198,12 +25409,12 @@ static warn_unused int js_parse_unary(JSParseState *s, int parse_flags)
return -1;
if (js_parse_unary(s, PF_POW_FORBIDDEN))
return -1;
+ s->cur_func->has_await = TRUE;
emit_op(s, OP_await);
parse_flags = 0;
break;
default:
- if (js_parse_postfix_expr(s, (parse_flags & PF_ARROW_FUNC) |
- PF_POSTFIX_CALL))
+ if (js_parse_postfix_expr(s, PF_POSTFIX_CALL))
return -1;
if (!s->got_lf &&
(s->token.val == TOK_DEC || s->token.val == TOK_INC)) {
@@ -25260,18 +25471,40 @@ static warn_unused int js_parse_unary(JSParseState *s, int parse_flags)
return 0;
}
-/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
-static warn_unused int js_parse_expr_binary(JSParseState *s, int level,
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_expr_binary(JSParseState *s, int level,
int parse_flags)
{
int op, opcode;
if (level == 0) {
- return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) |
- PF_POW_ALLOWED);
+ return js_parse_unary(s, PF_POW_ALLOWED);
+ } else if (s->token.val == TOK_PRIVATE_NAME &&
+ (parse_flags & PF_IN_ACCEPTED) && level == 4 &&
+ peek_token(s, FALSE) == TOK_IN) {
+ JSAtom atom;
+
+ atom = JS_DupAtom(s->ctx, s->token.u.ident.atom);
+ if (next_token(s))
+ goto fail_private_in;
+ if (s->token.val != TOK_IN)
+ goto fail_private_in;
+ if (next_token(s))
+ goto fail_private_in;
+ if (js_parse_expr_binary(s, level - 1, parse_flags)) {
+ fail_private_in:
+ JS_FreeAtom(s->ctx, atom);
+ return -1;
+ }
+ emit_op(s, OP_scope_in_private_field);
+ emit_atom(s, atom);
+ emit_u16(s, s->cur_func->scope_level);
+ JS_FreeAtom(s->ctx, atom);
+ return 0;
+ } else {
+ if (js_parse_expr_binary(s, level - 1, parse_flags))
+ return -1;
}
- if (js_parse_expr_binary(s, level - 1, parse_flags))
- return -1;
for(;;) {
op = s->token.val;
switch(level) {
@@ -25400,15 +25633,15 @@ static warn_unused int js_parse_expr_binary(JSParseState *s, int level,
}
if (next_token(s))
return -1;
- if (js_parse_expr_binary(s, level - 1, parse_flags & ~PF_ARROW_FUNC))
+ if (js_parse_expr_binary(s, level - 1, parse_flags))
return -1;
emit_op(s, opcode);
}
return 0;
}
-/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
-static warn_unused int js_parse_logical_and_or(JSParseState *s, int op,
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_logical_and_or(JSParseState *s, int op,
int parse_flags)
{
int label1;
@@ -25431,11 +25664,11 @@ static warn_unused int js_parse_logical_and_or(JSParseState *s, int op,
emit_op(s, OP_drop);
if (op == TOK_LAND) {
- if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))
+ if (js_parse_expr_binary(s, 8, parse_flags))
return -1;
} else {
if (js_parse_logical_and_or(s, TOK_LAND,
- parse_flags & ~PF_ARROW_FUNC))
+ parse_flags))
return -1;
}
if (s->token.val != op) {
@@ -25450,7 +25683,7 @@ static warn_unused int js_parse_logical_and_or(JSParseState *s, int op,
return 0;
}
-static warn_unused int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
+static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
{
int label1;
@@ -25467,7 +25700,7 @@ static warn_unused int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
emit_goto(s, OP_if_false, label1);
emit_op(s, OP_drop);
- if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))
+ if (js_parse_expr_binary(s, 8, parse_flags))
return -1;
if (s->token.val != TOK_DOUBLE_QUESTION_MARK)
break;
@@ -25477,8 +25710,8 @@ static warn_unused int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
return 0;
}
-/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
-static warn_unused int js_parse_cond_expr(JSParseState *s, int parse_flags)
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
{
int label1, label2;
@@ -25509,7 +25742,7 @@ static warn_unused int js_parse_cond_expr(JSParseState *s, int parse_flags)
static void emit_return(JSParseState *s, BOOL hasval);
/* allowed parse_flags: PF_IN_ACCEPTED */
-static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
+static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
{
int opcode, op, scope;
JSAtom name0 = JS_ATOM_NULL;
@@ -25571,7 +25804,6 @@ static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
/* OP_async_yield_star takes the value as parameter */
emit_op(s, OP_get_field);
emit_atom(s, JS_ATOM_value);
- emit_op(s, OP_await);
emit_op(s, OP_async_yield_star);
} else {
/* OP_yield_star takes (value, done) as parameter */
@@ -25653,12 +25885,50 @@ static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
emit_label(s, label_next);
}
return 0;
+ } else if (s->token.val == '(' &&
+ js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
+ return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
+ JS_FUNC_NORMAL, JS_ATOM_NULL,
+ s->token.ptr, s->token.line_num);
+ } else if (token_is_pseudo_keyword(s, JS_ATOM_async)) {
+ const uint8_t *source_ptr;
+ int source_line_num, tok;
+ JSParsePos pos;
+
+ /* fast test */
+ tok = peek_token(s, TRUE);
+ if (tok == TOK_FUNCTION || tok == '\n')
+ goto next;
+
+ source_ptr = s->token.ptr;
+ source_line_num = s->token.line_num;
+ js_parse_get_pos(s, &pos);
+ if (next_token(s))
+ return -1;
+ if ((s->token.val == '(' &&
+ js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
+ (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
+ peek_token(s, TRUE) == TOK_ARROW)) {
+ return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
+ JS_FUNC_ASYNC, JS_ATOM_NULL,
+ source_ptr, source_line_num);
+ } else {
+ /* undo the token parsing */
+ if (js_parse_seek_token(s, &pos))
+ return -1;
+ }
+ } else if (s->token.val == TOK_IDENT &&
+ peek_token(s, TRUE) == TOK_ARROW) {
+ return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
+ JS_FUNC_NORMAL, JS_ATOM_NULL,
+ s->token.ptr, s->token.line_num);
}
+ next:
if (s->token.val == TOK_IDENT) {
/* name0 is used to check for OP_set_name pattern, not duplicated */
name0 = s->token.u.ident.atom;
}
- if (js_parse_cond_expr(s, parse_flags | PF_ARROW_FUNC))
+ if (js_parse_cond_expr(s, parse_flags))
return -1;
op = s->token.val;
@@ -25755,13 +26025,13 @@ static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
return 0;
}
-static warn_unused int js_parse_assign_expr(JSParseState *s)
+static __exception int js_parse_assign_expr(JSParseState *s)
{
return js_parse_assign_expr2(s, PF_IN_ACCEPTED);
}
/* allowed parse_flags: PF_IN_ACCEPTED */
-static warn_unused int js_parse_expr2(JSParseState *s, int parse_flags)
+static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
{
BOOL comma = FALSE;
for(;;) {
@@ -25785,7 +26055,7 @@ static warn_unused int js_parse_expr2(JSParseState *s, int parse_flags)
return 0;
}
-static warn_unused int js_parse_expr(JSParseState *s)
+static __exception int js_parse_expr(JSParseState *s)
{
return js_parse_expr2(s, PF_IN_ACCEPTED);
}
@@ -25813,7 +26083,7 @@ static void pop_break_entry(JSFunctionDef *fd)
fd->top_break = be->prev;
}
-static warn_unused int emit_break(JSParseState *s, JSAtom name, int is_cont)
+static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)
{
BlockEnv *top;
int i, scope_level;
@@ -25865,61 +26135,61 @@ static warn_unused int emit_break(JSParseState *s, JSAtom name, int is_cont)
static void emit_return(JSParseState *s, BOOL hasval)
{
BlockEnv *top;
- int drop_count;
- drop_count = 0;
+ if (s->cur_func->func_kind != JS_FUNC_NORMAL) {
+ if (!hasval) {
+ /* no value: direct return in case of async generator */
+ emit_op(s, OP_undefined);
+ hasval = TRUE;
+ } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
+ /* the await must be done before handling the "finally" in
+ case it raises an exception */
+ emit_op(s, OP_await);
+ }
+ }
+
top = s->cur_func->top_break;
while (top != NULL) {
- /* XXX: emit the appropriate OP_leave_scope opcodes? Probably not
- required as all local variables will be closed upon returning
- from JS_CallInternal, but not in the same order. */
- if (top->has_iterator) {
- /* with 'yield', the exact number of OP_drop to emit is
- unknown, so we use a specific operation to look for
- the catch offset */
+ if (top->has_iterator || top->label_finally != -1) {
if (!hasval) {
emit_op(s, OP_undefined);
hasval = TRUE;
}
- emit_op(s, OP_iterator_close_return);
- if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
- int label_next, label_next2;
-
- emit_op(s, OP_drop); /* catch offset */
- emit_op(s, OP_drop); /* next */
- emit_op(s, OP_get_field2);
- emit_atom(s, JS_ATOM_return);
- /* stack: iter_obj return_func */
- emit_op(s, OP_dup);
- emit_op(s, OP_is_undefined_or_null);
- label_next = emit_goto(s, OP_if_true, -1);
- emit_op(s, OP_call_method);
- emit_u16(s, 0);
- emit_op(s, OP_iterator_check_object);
- emit_op(s, OP_await);
- label_next2 = emit_goto(s, OP_goto, -1);
- emit_label(s, label_next);
- emit_op(s, OP_drop);
- emit_label(s, label_next2);
- emit_op(s, OP_drop);
+ /* Remove the stack elements up to and including the catch
+ offset. When 'yield' is used in an expression we have
+ no easy way to count them, so we use this specific
+ instruction instead. */
+ emit_op(s, OP_nip_catch);
+ /* stack: iter_obj next ret_val */
+ if (top->has_iterator) {
+ if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
+ int label_next, label_next2;
+ emit_op(s, OP_nip); /* next */
+ emit_op(s, OP_swap);
+ emit_op(s, OP_get_field2);
+ emit_atom(s, JS_ATOM_return);
+ /* stack: iter_obj return_func */
+ emit_op(s, OP_dup);
+ emit_op(s, OP_is_undefined_or_null);
+ label_next = emit_goto(s, OP_if_true, -1);
+ emit_op(s, OP_call_method);
+ emit_u16(s, 0);
+ emit_op(s, OP_iterator_check_object);
+ emit_op(s, OP_await);
+ label_next2 = emit_goto(s, OP_goto, -1);
+ emit_label(s, label_next);
+ emit_op(s, OP_drop);
+ emit_label(s, label_next2);
+ emit_op(s, OP_drop);
+ } else {
+ emit_op(s, OP_rot3r);
+ emit_op(s, OP_undefined); /* dummy catch offset */
+ emit_op(s, OP_iterator_close);
+ }
} else {
- emit_op(s, OP_iterator_close);
- }
- drop_count = -3;
- }
- drop_count += top->drop_count;
- if (top->label_finally != -1) {
- while(drop_count) {
- /* must keep the stack top if hasval */
- emit_op(s, hasval ? OP_nip : OP_drop);
- drop_count--;
+ /* execute the "finally" block */
+ emit_goto(s, OP_gosub, top->label_finally);
}
- if (!hasval) {
- /* must push return value to keep same stack size */
- emit_op(s, OP_undefined);
- hasval = TRUE;
- }
- emit_goto(s, OP_gosub, top->label_finally);
}
top = top->prev;
}
@@ -25936,20 +26206,15 @@ static void emit_return(JSParseState *s, BOOL hasval)
label_return = -1;
}
- /* XXX: if this is not initialized, should throw the
- ReferenceError in the caller realm */
- emit_op(s, OP_scope_get_var);
+ /* The error should be raised in the caller context, so we use
+ a specific opcode */
+ emit_op(s, OP_scope_get_var_checkthis);
emit_atom(s, JS_ATOM_this);
emit_u16(s, 0);
emit_label(s, label_return);
emit_op(s, OP_return);
} else if (s->cur_func->func_kind != JS_FUNC_NORMAL) {
- if (!hasval) {
- emit_op(s, OP_undefined);
- } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
- emit_op(s, OP_await);
- }
emit_op(s, OP_return_async);
} else {
emit_op(s, hasval ? OP_return : OP_return_undef);
@@ -25962,15 +26227,15 @@ static void emit_return(JSParseState *s, BOOL hasval)
#define DECL_MASK_OTHER (1 << 2) /* all other declarations */
#define DECL_MASK_ALL (DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL | DECL_MASK_OTHER)
-static warn_unused int js_parse_statement_or_decl(JSParseState *s,
+static __exception int js_parse_statement_or_decl(JSParseState *s,
int decl_mask);
-static warn_unused int js_parse_statement(JSParseState *s)
+static __exception int js_parse_statement(JSParseState *s)
{
return js_parse_statement_or_decl(s, 0);
}
-static warn_unused int js_parse_block(JSParseState *s)
+static __exception int js_parse_block(JSParseState *s)
{
if (js_parse_expect(s, '{'))
return -1;
@@ -25990,7 +26255,7 @@ static warn_unused int js_parse_block(JSParseState *s)
}
/* allowed parse_flags: PF_IN_ACCEPTED */
-static warn_unused int js_parse_var(JSParseState *s, int parse_flags, int tok,
+static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
BOOL export_flag)
{
JSContext *ctx = s->ctx;
@@ -26096,7 +26361,6 @@ static int is_let(JSParseState *s, int decl_mask)
int res = FALSE;
if (token_is_pseudo_keyword(s, JS_ATOM_let)) {
-#if 1
JSParsePos pos;
js_parse_get_pos(s, &pos);
for (;;) {
@@ -26129,19 +26393,13 @@ static int is_let(JSParseState *s, int decl_mask)
if (js_parse_seek_token(s, &pos)) {
res = -1;
}
-#else
- int tok = peek_token(s, TRUE);
- if (tok == '{' || tok == TOK_IDENT || peek_token(s, FALSE) == '[') {
- res = TRUE;
- }
-#endif
}
return res;
}
/* XXX: handle IteratorClose when exiting the loop before the
enumeration is done */
-static warn_unused int js_parse_for_in_of(JSParseState *s, int label_name,
+static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
BOOL is_async)
{
JSContext *ctx = s->ctx;
@@ -26216,6 +26474,9 @@ static warn_unused int js_parse_for_in_of(JSParseState *s, int label_name,
emit_atom(s, var_name);
emit_u16(s, fd->scope_level);
}
+ } else if (!is_async && token_is_pseudo_keyword(s, JS_ATOM_async) &&
+ peek_token(s, FALSE) == TOK_OF) {
+ return js_parse_error(s, "'for of' expression cannot start with 'async'");
} else {
int skip_bits;
if ((s->token.val == '[' || s->token.val == '{')
@@ -26372,7 +26633,7 @@ static void set_eval_ret_undefined(JSParseState *s)
}
}
-static warn_unused int js_parse_statement_or_decl(JSParseState *s,
+static __exception int js_parse_statement_or_decl(JSParseState *s,
int decl_mask)
{
JSContext *ctx = s->ctx;
@@ -26432,6 +26693,10 @@ static warn_unused int js_parse_statement_or_decl(JSParseState *s,
js_parse_error(s, "return not in a function");
goto fail;
}
+ if (s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
+ js_parse_error(s, "return in a static initializer block");
+ goto fail;
+ }
if (next_token(s))
goto fail;
if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) {
@@ -26600,6 +26865,7 @@ static warn_unused int js_parse_statement_or_decl(JSParseState *s,
is_async = TRUE;
if (next_token(s))
goto fail;
+ s->cur_func->has_await = TRUE;
}
if (js_parse_expect(s, '('))
goto fail;
@@ -27130,6 +27396,9 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
m->func_obj = JS_UNDEFINED;
m->eval_exception = JS_UNDEFINED;
m->meta_obj = JS_UNDEFINED;
+ m->promise = JS_UNDEFINED;
+ m->resolving_funcs[0] = JS_UNDEFINED;
+ m->resolving_funcs[1] = JS_UNDEFINED;
list_add_tail(&m->link, &ctx->loaded_modules);
return m;
}
@@ -27151,6 +27420,9 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
JS_MarkValue(rt, m->func_obj, mark_func);
JS_MarkValue(rt, m->eval_exception, mark_func);
JS_MarkValue(rt, m->meta_obj, mark_func);
+ JS_MarkValue(rt, m->promise, mark_func);
+ JS_MarkValue(rt, m->resolving_funcs[0], mark_func);
+ JS_MarkValue(rt, m->resolving_funcs[1], mark_func);
}
static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
@@ -27181,11 +27453,15 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
JS_FreeAtom(ctx, mi->import_name);
}
js_free(ctx, m->import_entries);
+ js_free(ctx, m->async_parent_modules);
JS_FreeValue(ctx, m->module_ns);
JS_FreeValue(ctx, m->func_obj);
JS_FreeValue(ctx, m->eval_exception);
JS_FreeValue(ctx, m->meta_obj);
+ JS_FreeValue(ctx, m->promise);
+ JS_FreeValue(ctx, m->resolving_funcs[0]);
+ JS_FreeValue(ctx, m->resolving_funcs[1]);
list_del(&m->link);
js_free(ctx, m);
}
@@ -27346,6 +27622,7 @@ static char *js_default_module_normalize_name(JSContext *ctx,
{
char *filename, *p;
const char *r;
+ int cap;
int len;
if (name[0] != '.') {
@@ -27359,7 +27636,8 @@ static char *js_default_module_normalize_name(JSContext *ctx,
else
len = 0;
- filename = js_malloc(ctx, len + strlen(name) + 1 + 1);
+ cap = len + strlen(name) + 1 + 1;
+ filename = js_malloc(ctx, cap);
if (!filename)
return NULL;
memcpy(filename, base_name, len);
@@ -27391,8 +27669,8 @@ static char *js_default_module_normalize_name(JSContext *ctx,
}
}
if (filename[0] != '\0')
- strcat(filename, "/");
- strcat(filename, r);
+ pstrcat(filename, cap, "/");
+ pstrcat(filename, cap, r);
// printf("normalize: %s %s -> %s\n", base_name, name, filename);
return filename;
}
@@ -27692,7 +27970,7 @@ static int find_exported_name(GetExportNamesState *s, JSAtom name)
return -1;
}
-static warn_unused int get_exported_names(JSContext *ctx,
+static __exception int get_exported_names(JSContext *ctx,
GetExportNamesState *s,
JSModuleDef *m, BOOL from_star)
{
@@ -27774,13 +28052,11 @@ static int exported_names_cmp(const void *p1, const void *p2, void *opaque)
return ret;
}
-static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m);
-
static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
void *opaque)
{
JSModuleDef *m = opaque;
- return js_get_module_ns(ctx, m);
+ return JS_GetModuleNamespace(ctx, m);
}
static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
@@ -27885,7 +28161,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
return JS_EXCEPTION;
}
-static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m)
+JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m)
{
if (JS_IsUndefined(m->module_ns)) {
JSValue val;
@@ -28040,7 +28316,8 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m)
/* Prepare a module to be executed by resolving all the imported
variables. */
-static int js_link_module(JSContext *ctx, JSModuleDef *m)
+static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
+ JSModuleDef **pstack_top, int index)
{
int i;
JSImportEntry *mi;
@@ -28050,21 +28327,47 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
BOOL is_c_module;
JSValue ret_val;
- if (m->instantiated)
- return 0;
- m->instantiated = TRUE;
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ JS_ThrowStackOverflow(ctx);
+ return -1;
+ }
#ifdef DUMP_MODULE_RESOLVE
{
char buf1[ATOM_GET_STR_BUF_SIZE];
- printf("start instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
+ printf("js_inner_module_linking '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
}
#endif
+ if (m->status == JS_MODULE_STATUS_LINKING ||
+ m->status == JS_MODULE_STATUS_LINKED ||
+ m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED)
+ return index;
+
+ assert(m->status == JS_MODULE_STATUS_UNLINKED);
+ m->status = JS_MODULE_STATUS_LINKING;
+ m->dfs_index = index;
+ m->dfs_ancestor_index = index;
+ index++;
+ /* push 'm' on stack */
+ m->stack_prev = *pstack_top;
+ *pstack_top = m;
+
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
- if (js_link_module(ctx, rme->module) < 0)
+ m1 = rme->module;
+ index = js_inner_module_linking(ctx, m1, pstack_top, index);
+ if (index < 0)
goto fail;
+ assert(m1->status == JS_MODULE_STATUS_LINKING ||
+ m1->status == JS_MODULE_STATUS_LINKED ||
+ m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m1->status == JS_MODULE_STATUS_EVALUATED);
+ if (m1->status == JS_MODULE_STATUS_LINKING) {
+ m->dfs_ancestor_index = min_int(m->dfs_ancestor_index,
+ m1->dfs_ancestor_index);
+ }
}
#ifdef DUMP_MODULE_RESOLVE
@@ -28119,7 +28422,7 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
if (mi->import_name == JS_ATOM__star_) {
JSValue val;
/* name space import */
- val = js_get_module_ns(ctx, m1);
+ val = JS_GetModuleNamespace(ctx, m1);
if (JS_IsException(val))
goto fail;
set_value(ctx, &var_refs[mi->var_idx]->value, val);
@@ -28143,7 +28446,7 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
JSModuleDef *m2;
/* name space import from */
m2 = res_m->req_module_entries[res_me->u.req_module_idx].module;
- val = js_get_module_ns(ctx, m2);
+ val = JS_GetModuleNamespace(ctx, m2);
if (JS_IsException(val))
goto fail;
var_ref = js_create_module_var(ctx, TRUE);
@@ -28190,14 +28493,59 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
JS_FreeValue(ctx, ret_val);
}
+ assert(m->dfs_ancestor_index <= m->dfs_index);
+ if (m->dfs_index == m->dfs_ancestor_index) {
+ for(;;) {
+ /* pop m1 from stack */
+ m1 = *pstack_top;
+ *pstack_top = m1->stack_prev;
+ m1->status = JS_MODULE_STATUS_LINKED;
+ if (m1 == m)
+ break;
+ }
+ }
+
#ifdef DUMP_MODULE_RESOLVE
- printf("done instantiate\n");
+ printf("js_inner_module_linking done\n");
#endif
- return 0;
+ return index;
fail:
return -1;
}
+/* Prepare a module to be executed by resolving all the imported
+ variables. */
+static int js_link_module(JSContext *ctx, JSModuleDef *m)
+{
+ JSModuleDef *stack_top, *m1;
+
+#ifdef DUMP_MODULE_RESOLVE
+ {
+ char buf1[ATOM_GET_STR_BUF_SIZE];
+ printf("js_link_module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
+ }
+#endif
+ assert(m->status == JS_MODULE_STATUS_UNLINKED ||
+ m->status == JS_MODULE_STATUS_LINKED ||
+ m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED);
+ stack_top = NULL;
+ if (js_inner_module_linking(ctx, m, &stack_top, 0) < 0) {
+ while (stack_top != NULL) {
+ m1 = stack_top;
+ assert(m1->status == JS_MODULE_STATUS_LINKING);
+ m1->status = JS_MODULE_STATUS_UNLINKED;
+ stack_top = m1->stack_prev;
+ }
+ return -1;
+ }
+ assert(stack_top == NULL);
+ assert(m->status == JS_MODULE_STATUS_LINKED ||
+ m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED);
+ return 0;
+}
+
/* return JS_ATOM_NULL if the name cannot be found. Only works with
not striped bytecode functions. */
JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
@@ -28206,8 +28554,8 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
JSFunctionBytecode *b;
JSObject *p;
/* XXX: currently we just use the filename of the englobing
- function. It does not work for eval(). Need to add a
- ScriptOrModule info in JSFunctionBytecode */
+ function from the debug info. May need to add a ScriptOrModule
+ info in JSFunctionBytecode. */
sf = ctx->rt->current_stack_frame;
if (!sf)
return JS_ATOM_NULL;
@@ -28216,15 +28564,23 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
if (!sf)
return JS_ATOM_NULL;
}
- if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)
- return JS_ATOM_NULL;
- p = JS_VALUE_GET_OBJ(sf->cur_func);
- if (!js_class_has_bytecode(p->class_id))
- return JS_ATOM_NULL;
- b = p->u.func.function_bytecode;
- if (!b->has_debug)
- return JS_ATOM_NULL;
- return JS_DupAtom(ctx, b->debug.filename);
+ for(;;) {
+ if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)
+ return JS_ATOM_NULL;
+ p = JS_VALUE_GET_OBJ(sf->cur_func);
+ if (!js_class_has_bytecode(p->class_id))
+ return JS_ATOM_NULL;
+ b = p->u.func.function_bytecode;
+ if (!b->is_direct_or_indirect_eval) {
+ if (!b->has_debug)
+ return JS_ATOM_NULL;
+ return JS_DupAtom(ctx, b->debug.filename);
+ } else {
+ sf = sf->prev_frame;
+ if (!sf)
+ return JS_ATOM_NULL;
+ }
+ }
}
JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m)
@@ -28267,29 +28623,110 @@ static JSValue js_import_meta(JSContext *ctx)
return JS_GetImportMeta(ctx, m);
}
-/* used by os.Worker() and import() */
-JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
- const char *filename)
+static JSValue JS_NewModuleValue(JSContext *ctx, JSModuleDef *m)
+{
+ return JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
+}
+
+static JSValue js_load_module_rejected(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic, JSValue *func_data)
{
+ JSValueConst *resolving_funcs = (JSValueConst *)func_data;
+ JSValueConst error;
+ JSValue ret;
+
+ /* XXX: check if the test is necessary */
+ if (argc >= 1)
+ error = argv[0];
+ else
+ error = JS_UNDEFINED;
+ ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
+ 1, &error);
+ JS_FreeValue(ctx, ret);
+ return JS_UNDEFINED;
+}
+
+static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic, JSValue *func_data)
+{
+ JSValueConst *resolving_funcs = (JSValueConst *)func_data;
+ JSModuleDef *m = JS_VALUE_GET_PTR(func_data[2]);
+ JSValue ret, ns;
+
+ /* return the module namespace */
+ ns = JS_GetModuleNamespace(ctx, m);
+ if (JS_IsException(ns)) {
+ JSValue err = JS_GetException(ctx);
+ js_load_module_rejected(ctx, JS_UNDEFINED, 1, (JSValueConst *)&err, 0, func_data);
+ return JS_UNDEFINED;
+ }
+ ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
+ 1, (JSValueConst *)&ns);
+ JS_FreeValue(ctx, ret);
+ JS_FreeValue(ctx, ns);
+ return JS_UNDEFINED;
+}
+
+static void JS_LoadModuleInternal(JSContext *ctx, const char *basename,
+ const char *filename,
+ JSValueConst *resolving_funcs)
+{
+ JSValue evaluate_promise;
JSModuleDef *m;
- JSValue ret, func_obj;
+ JSValue ret, err, func_obj, evaluate_resolving_funcs[2];
+ JSValueConst func_data[3];
m = js_host_resolve_imported_module(ctx, basename, filename);
if (!m)
- return NULL;
+ goto fail;
if (js_resolve_module(ctx, m) < 0) {
js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);
- return NULL;
+ goto fail;
}
/* Evaluate the module code */
- func_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
- ret = JS_EvalFunction(ctx, func_obj);
- if (JS_IsException(ret))
- return NULL;
+ func_obj = JS_NewModuleValue(ctx, m);
+ evaluate_promise = JS_EvalFunction(ctx, func_obj);
+ if (JS_IsException(evaluate_promise)) {
+ fail:
+ err = JS_GetException(ctx);
+ ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
+ 1, (JSValueConst *)&err);
+ JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
+ JS_FreeValue(ctx, err);
+ return;
+ }
+
+ func_obj = JS_NewModuleValue(ctx, m);
+ func_data[0] = resolving_funcs[0];
+ func_data[1] = resolving_funcs[1];
+ func_data[2] = func_obj;
+ evaluate_resolving_funcs[0] = JS_NewCFunctionData(ctx, js_load_module_fulfilled, 0, 0, 3, func_data);
+ evaluate_resolving_funcs[1] = JS_NewCFunctionData(ctx, js_load_module_rejected, 0, 0, 3, func_data);
+ JS_FreeValue(ctx, func_obj);
+ ret = js_promise_then(ctx, evaluate_promise, 2, (JSValueConst *)evaluate_resolving_funcs);
JS_FreeValue(ctx, ret);
- return m;
+ JS_FreeValue(ctx, evaluate_resolving_funcs[0]);
+ JS_FreeValue(ctx, evaluate_resolving_funcs[1]);
+ JS_FreeValue(ctx, evaluate_promise);
+}
+
+/* Return a promise or an exception in case of memory error. Used by
+ os.Worker() */
+JSValue JS_LoadModule(JSContext *ctx, const char *basename,
+ const char *filename)
+{
+ JSValue promise, resolving_funcs[2];
+
+ promise = JS_NewPromiseCapability(ctx, resolving_funcs);
+ if (JS_IsException(promise))
+ return JS_EXCEPTION;
+ JS_LoadModuleInternal(ctx, basename, filename,
+ (JSValueConst *)resolving_funcs);
+ JS_FreeValue(ctx, resolving_funcs[0]);
+ JS_FreeValue(ctx, resolving_funcs[1]);
+ return promise;
}
static JSValue js_dynamic_import_job(JSContext *ctx,
@@ -28298,9 +28735,8 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
JSValueConst *resolving_funcs = argv;
JSValueConst basename_val = argv[2];
JSValueConst specifier = argv[3];
- JSModuleDef *m;
const char *basename = NULL, *filename;
- JSValue ret, err, ns;
+ JSValue ret, err;
if (!JS_IsString(basename_val)) {
JS_ThrowTypeError(ctx, "no function filename for import()");
@@ -28314,27 +28750,15 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
if (!filename)
goto exception;
- m = JS_RunModule(ctx, basename, filename);
+ JS_LoadModuleInternal(ctx, basename, filename,
+ resolving_funcs);
JS_FreeCString(ctx, filename);
- if (!m)
- goto exception;
-
- /* return the module namespace */
- ns = js_get_module_ns(ctx, m);
- if (JS_IsException(ns))
- goto exception;
-
- ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
- 1, &ns);
- JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, ns);
JS_FreeCString(ctx, basename);
return JS_UNDEFINED;
exception:
-
err = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
- 1, &err);
+ 1, (JSValueConst *)&err);
JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
JS_FreeValue(ctx, err);
JS_FreeCString(ctx, basename);
@@ -28367,6 +28791,8 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
args[2] = basename_val;
args[3] = specifier;
+ /* cannot run JS_LoadModuleInternal synchronously because it would
+ cause an unexpected recursion in js_evaluate_module() */
JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args);
JS_FreeValue(ctx, basename_val);
@@ -28375,63 +28801,400 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
return promise;
}
-/* Run the <eval> function of the module and of all its requested
- modules. */
-static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
+static void js_set_module_evaluated(JSContext *ctx, JSModuleDef *m)
+{
+ m->status = JS_MODULE_STATUS_EVALUATED;
+ if (!JS_IsUndefined(m->promise)) {
+ JSValue value, ret_val;
+ assert(m->cycle_root == m);
+ value = JS_UNDEFINED;
+ ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED,
+ 1, (JSValueConst *)&value);
+ JS_FreeValue(ctx, ret_val);
+ }
+}
+
+typedef struct {
+ JSModuleDef **tab;
+ int count;
+ int size;
+} ExecModuleList;
+
+/* XXX: slow. Could use a linked list instead of ExecModuleList */
+static BOOL find_in_exec_module_list(ExecModuleList *exec_list, JSModuleDef *m)
+{
+ int i;
+ for(i = 0; i < exec_list->count; i++) {
+ if (exec_list->tab[i] == m)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int gather_available_ancestors(JSContext *ctx, JSModuleDef *module,
+ ExecModuleList *exec_list)
+{
+ int i;
+
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ JS_ThrowStackOverflow(ctx);
+ return -1;
+ }
+ for(i = 0; i < module->async_parent_modules_count; i++) {
+ JSModuleDef *m = module->async_parent_modules[i];
+ if (!find_in_exec_module_list(exec_list, m) &&
+ !m->cycle_root->eval_has_exception) {
+ assert(m->status == JS_MODULE_STATUS_EVALUATING_ASYNC);
+ assert(!m->eval_has_exception);
+ assert(m->async_evaluation);
+ assert(m->pending_async_dependencies > 0);
+ m->pending_async_dependencies--;
+ if (m->pending_async_dependencies == 0) {
+ if (js_resize_array(ctx, (void **)&exec_list->tab, sizeof(exec_list->tab[0]), &exec_list->size, exec_list->count + 1)) {
+ return -1;
+ }
+ exec_list->tab[exec_list->count++] = m;
+ if (!m->has_tla) {
+ if (gather_available_ancestors(ctx, m, exec_list))
+ return -1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int exec_module_list_cmp(const void *p1, const void *p2, void *opaque)
+{
+ JSModuleDef *m1 = *(JSModuleDef **)p1;
+ JSModuleDef *m2 = *(JSModuleDef **)p2;
+ return (m1->async_evaluation_timestamp > m2->async_evaluation_timestamp) -
+ (m1->async_evaluation_timestamp < m2->async_evaluation_timestamp);
+}
+
+static int js_execute_async_module(JSContext *ctx, JSModuleDef *m);
+static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
+ JSValue *pvalue);
+
+static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic, JSValue *func_data)
+{
+ JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]);
+ JSValueConst error = argv[0];
+ int i;
+
+ if (js_check_stack_overflow(ctx->rt, 0))
+ return JS_ThrowStackOverflow(ctx);
+
+ if (module->status == JS_MODULE_STATUS_EVALUATED) {
+ assert(module->eval_has_exception);
+ return JS_UNDEFINED;
+ }
+
+ assert(module->status == JS_MODULE_STATUS_EVALUATING_ASYNC);
+ assert(!module->eval_has_exception);
+ assert(module->async_evaluation);
+
+ module->eval_has_exception = TRUE;
+ module->eval_exception = JS_DupValue(ctx, error);
+ module->status = JS_MODULE_STATUS_EVALUATED;
+
+ for(i = 0; i < module->async_parent_modules_count; i++) {
+ JSModuleDef *m = module->async_parent_modules[i];
+ JSValue m_obj = JS_NewModuleValue(ctx, m);
+ js_async_module_execution_rejected(ctx, JS_UNDEFINED, 1, &error, 0,
+ &m_obj);
+ JS_FreeValue(ctx, m_obj);
+ }
+
+ if (!JS_IsUndefined(module->promise)) {
+ JSValue ret_val;
+ assert(module->cycle_root == module);
+ ret_val = JS_Call(ctx, module->resolving_funcs[1], JS_UNDEFINED,
+ 1, &error);
+ JS_FreeValue(ctx, ret_val);
+ }
+ return JS_UNDEFINED;
+}
+
+static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic, JSValue *func_data)
+{
+ JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]);
+ ExecModuleList exec_list_s, *exec_list = &exec_list_s;
+ int i;
+
+ if (module->status == JS_MODULE_STATUS_EVALUATED) {
+ assert(module->eval_has_exception);
+ return JS_UNDEFINED;
+ }
+ assert(module->status == JS_MODULE_STATUS_EVALUATING_ASYNC);
+ assert(!module->eval_has_exception);
+ assert(module->async_evaluation);
+ module->async_evaluation = FALSE;
+ js_set_module_evaluated(ctx, module);
+
+ exec_list->tab = NULL;
+ exec_list->count = 0;
+ exec_list->size = 0;
+
+ if (gather_available_ancestors(ctx, module, exec_list) < 0) {
+ js_free(ctx, exec_list->tab);
+ return JS_EXCEPTION;
+ }
+
+ /* sort by increasing async_evaluation timestamp */
+ rqsort(exec_list->tab, exec_list->count, sizeof(exec_list->tab[0]),
+ exec_module_list_cmp, NULL);
+
+ for(i = 0; i < exec_list->count; i++) {
+ JSModuleDef *m = exec_list->tab[i];
+ if (m->status == JS_MODULE_STATUS_EVALUATED) {
+ assert(m->eval_has_exception);
+ } else if (m->has_tla) {
+ js_execute_async_module(ctx, m);
+ } else {
+ JSValue error;
+ if (js_execute_sync_module(ctx, m, &error) < 0) {
+ JSValue m_obj = JS_NewModuleValue(ctx, m);
+ js_async_module_execution_rejected(ctx, JS_UNDEFINED,
+ 1, (JSValueConst *)&error, 0,
+ &m_obj);
+ JS_FreeValue(ctx, m_obj);
+ JS_FreeValue(ctx, error);
+ } else {
+ js_set_module_evaluated(ctx, m);
+ }
+ }
+ }
+ js_free(ctx, exec_list->tab);
+ return JS_UNDEFINED;
+}
+
+static int js_execute_async_module(JSContext *ctx, JSModuleDef *m)
+{
+ JSValue promise, m_obj;
+ JSValue resolve_funcs[2], ret_val;
+ promise = js_async_function_call(ctx, m->func_obj, JS_UNDEFINED, 0, NULL, 0);
+ if (JS_IsException(promise))
+ return -1;
+ m_obj = JS_NewModuleValue(ctx, m);
+ resolve_funcs[0] = JS_NewCFunctionData(ctx, js_async_module_execution_fulfilled, 0, 0, 1, (JSValueConst *)&m_obj);
+ resolve_funcs[1] = JS_NewCFunctionData(ctx, js_async_module_execution_rejected, 0, 0, 1, (JSValueConst *)&m_obj);
+ ret_val = js_promise_then(ctx, promise, 2, (JSValueConst *)resolve_funcs);
+ JS_FreeValue(ctx, ret_val);
+ JS_FreeValue(ctx, m_obj);
+ JS_FreeValue(ctx, resolve_funcs[0]);
+ JS_FreeValue(ctx, resolve_funcs[1]);
+ JS_FreeValue(ctx, promise);
+ return 0;
+}
+
+/* return < 0 in case of exception. *pvalue contains the exception. */
+static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
+ JSValue *pvalue)
+{
+ if (m->init_func) {
+ /* C module init : no asynchronous execution */
+ if (m->init_func(ctx, m) < 0)
+ goto fail;
+ } else {
+ JSValue promise;
+ JSPromiseStateEnum state;
+
+ promise = js_async_function_call(ctx, m->func_obj, JS_UNDEFINED, 0, NULL, 0);
+ if (JS_IsException(promise))
+ goto fail;
+ state = JS_PromiseState(ctx, promise);
+ if (state == JS_PROMISE_FULFILLED) {
+ JS_FreeValue(ctx, promise);
+ } else if (state == JS_PROMISE_REJECTED) {
+ *pvalue = JS_PromiseResult(ctx, promise);
+ JS_FreeValue(ctx, promise);
+ return -1;
+ } else {
+ JS_FreeValue(ctx, promise);
+ JS_ThrowTypeError(ctx, "promise is pending");
+ fail:
+ *pvalue = JS_GetException(ctx);
+ return -1;
+ }
+ }
+ *pvalue = JS_UNDEFINED;
+ return 0;
+}
+
+/* spec: InnerModuleEvaluation. Return (index, JS_UNDEFINED) or (-1,
+ exception) */
+static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m,
+ int index, JSModuleDef **pstack_top,
+ JSValue *pvalue)
{
JSModuleDef *m1;
int i;
- JSValue ret_val;
- if (m->eval_mark)
- return JS_UNDEFINED; /* avoid cycles */
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ JS_ThrowStackOverflow(ctx);
+ *pvalue = JS_GetException(ctx);
+ return -1;
+ }
+
+#ifdef DUMP_MODULE_RESOLVE
+ {
+ char buf1[ATOM_GET_STR_BUF_SIZE];
+ printf("js_inner_module_evaluation '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
+ }
+#endif
- if (m->evaluated) {
- /* if the module was already evaluated, rethrow the exception
- it raised */
+ if (m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED) {
if (m->eval_has_exception) {
- return JS_Throw(ctx, JS_DupValue(ctx, m->eval_exception));
+ *pvalue = JS_DupValue(ctx, m->eval_exception);
+ return -1;
} else {
- return JS_UNDEFINED;
+ *pvalue = JS_UNDEFINED;
+ return index;
}
}
+ if (m->status == JS_MODULE_STATUS_EVALUATING) {
+ *pvalue = JS_UNDEFINED;
+ return index;
+ }
+ assert(m->status == JS_MODULE_STATUS_LINKED);
- m->eval_mark = TRUE;
+ m->status = JS_MODULE_STATUS_EVALUATING;
+ m->dfs_index = index;
+ m->dfs_ancestor_index = index;
+ m->pending_async_dependencies = 0;
+ index++;
+ /* push 'm' on stack */
+ m->stack_prev = *pstack_top;
+ *pstack_top = m;
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
m1 = rme->module;
- if (!m1->eval_mark) {
- ret_val = js_evaluate_module(ctx, m1);
- if (JS_IsException(ret_val)) {
- m->eval_mark = FALSE;
- return ret_val;
+ index = js_inner_module_evaluation(ctx, m1, index, pstack_top, pvalue);
+ if (index < 0)
+ return -1;
+ assert(m1->status == JS_MODULE_STATUS_EVALUATING ||
+ m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m1->status == JS_MODULE_STATUS_EVALUATED);
+ if (m1->status == JS_MODULE_STATUS_EVALUATING) {
+ m->dfs_ancestor_index = min_int(m->dfs_ancestor_index,
+ m1->dfs_ancestor_index);
+ } else {
+ m1 = m1->cycle_root;
+ assert(m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m1->status == JS_MODULE_STATUS_EVALUATED);
+ if (m1->eval_has_exception) {
+ *pvalue = JS_DupValue(ctx, m1->eval_exception);
+ return -1;
}
- JS_FreeValue(ctx, ret_val);
+ }
+ if (m1->async_evaluation) {
+ m->pending_async_dependencies++;
+ if (js_resize_array(ctx, (void **)&m1->async_parent_modules, sizeof(m1->async_parent_modules[0]), &m1->async_parent_modules_size, m1->async_parent_modules_count + 1)) {
+ *pvalue = JS_GetException(ctx);
+ return -1;
+ }
+ m1->async_parent_modules[m1->async_parent_modules_count++] = m;
}
}
- if (m->init_func) {
- /* C module init */
- if (m->init_func(ctx, m) < 0)
- ret_val = JS_EXCEPTION;
- else
- ret_val = JS_UNDEFINED;
+ if (m->pending_async_dependencies > 0) {
+ assert(!m->async_evaluation);
+ m->async_evaluation = TRUE;
+ m->async_evaluation_timestamp =
+ ctx->rt->module_async_evaluation_next_timestamp++;
+ } else if (m->has_tla) {
+ assert(!m->async_evaluation);
+ m->async_evaluation = TRUE;
+ m->async_evaluation_timestamp =
+ ctx->rt->module_async_evaluation_next_timestamp++;
+ js_execute_async_module(ctx, m);
} else {
- ret_val = JS_CallFree(ctx, m->func_obj, JS_UNDEFINED, 0, NULL);
- m->func_obj = JS_UNDEFINED;
+ if (js_execute_sync_module(ctx, m, pvalue) < 0)
+ return -1;
}
- if (JS_IsException(ret_val)) {
- /* save the thrown exception value */
- m->eval_has_exception = TRUE;
- m->eval_exception = JS_DupValue(ctx, ctx->rt->current_exception);
+
+ assert(m->dfs_ancestor_index <= m->dfs_index);
+ if (m->dfs_index == m->dfs_ancestor_index) {
+ for(;;) {
+ /* pop m1 from stack */
+ m1 = *pstack_top;
+ *pstack_top = m1->stack_prev;
+ if (!m1->async_evaluation) {
+ m1->status = JS_MODULE_STATUS_EVALUATED;
+ } else {
+ m1->status = JS_MODULE_STATUS_EVALUATING_ASYNC;
+ }
+ /* spec bug: cycle_root must be assigned before the test */
+ m1->cycle_root = m;
+ if (m1 == m)
+ break;
+ }
}
- m->eval_mark = FALSE;
- m->evaluated = TRUE;
- return ret_val;
+ *pvalue = JS_UNDEFINED;
+ return index;
}
-static warn_unused JSAtom js_parse_from_clause(JSParseState *s)
+/* Run the <eval> function of the module and of all its requested
+ modules. Return a promise or an exception. */
+static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
+{
+ JSModuleDef *m1, *stack_top;
+ JSValue ret_val, result;
+
+ assert(m->status == JS_MODULE_STATUS_LINKED ||
+ m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED);
+ if (m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED) {
+ m = m->cycle_root;
+ }
+ /* a promise may be created only on the cycle_root of a cycle */
+ if (!JS_IsUndefined(m->promise))
+ return JS_DupValue(ctx, m->promise);
+ m->promise = JS_NewPromiseCapability(ctx, m->resolving_funcs);
+ if (JS_IsException(m->promise))
+ return JS_EXCEPTION;
+
+ stack_top = NULL;
+ if (js_inner_module_evaluation(ctx, m, 0, &stack_top, &result) < 0) {
+ while (stack_top != NULL) {
+ m1 = stack_top;
+ assert(m1->status == JS_MODULE_STATUS_EVALUATING);
+ m1->status = JS_MODULE_STATUS_EVALUATED;
+ m1->eval_has_exception = TRUE;
+ m1->eval_exception = JS_DupValue(ctx, result);
+ m1->cycle_root = m; /* spec bug: should be present */
+ stack_top = m1->stack_prev;
+ }
+ JS_FreeValue(ctx, result);
+ assert(m->status == JS_MODULE_STATUS_EVALUATED);
+ assert(m->eval_has_exception);
+ ret_val = JS_Call(ctx, m->resolving_funcs[1], JS_UNDEFINED,
+ 1, (JSValueConst *)&m->eval_exception);
+ JS_FreeValue(ctx, ret_val);
+ } else {
+ assert(m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED);
+ assert(!m->eval_has_exception);
+ if (!m->async_evaluation) {
+ JSValue value;
+ assert(m->status == JS_MODULE_STATUS_EVALUATED);
+ value = JS_UNDEFINED;
+ ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED,
+ 1, (JSValueConst *)&value);
+ JS_FreeValue(ctx, ret_val);
+ }
+ assert(stack_top == NULL);
+ }
+ return JS_DupValue(ctx, m->promise);
+}
+
+static __exception JSAtom js_parse_from_clause(JSParseState *s)
{
JSAtom module_name;
if (!token_is_pseudo_keyword(s, JS_ATOM_from)) {
@@ -28454,7 +29217,7 @@ static warn_unused JSAtom js_parse_from_clause(JSParseState *s)
return module_name;
}
-static warn_unused int js_parse_export(JSParseState *s)
+static __exception int js_parse_export(JSParseState *s)
{
JSContext *ctx = s->ctx;
JSModuleDef *m = s->cur_func->module;
@@ -28657,7 +29420,7 @@ static int add_import(JSParseState *s, JSModuleDef *m,
return 0;
}
-static warn_unused int js_parse_import(JSParseState *s)
+static __exception int js_parse_import(JSParseState *s)
{
JSContext *ctx = s->ctx;
JSModuleDef *m = s->cur_func->module;
@@ -28772,7 +29535,7 @@ static warn_unused int js_parse_import(JSParseState *s)
return js_parse_expect_semi(s);
}
-static warn_unused int js_parse_source_element(JSParseState *s)
+static __exception int js_parse_source_element(JSParseState *s)
{
JSFunctionDef *fd = s->cur_func;
int tok;
@@ -29696,7 +30459,8 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
}
var_idx = idx;
break;
- } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
+ } else
+ if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
dbuf_putc(bc, OP_get_loc);
dbuf_put_u16(bc, idx);
var_object_test(ctx, s, var_name, op, bc, &label_done, 1);
@@ -29781,6 +30545,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
case OP_scope_get_ref:
dbuf_putc(bc, OP_undefined);
/* fall thru */
+ case OP_scope_get_var_checkthis:
case OP_scope_get_var_undef:
case OP_scope_get_var:
case OP_scope_put_var:
@@ -29806,7 +30571,12 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
}
} else {
if (s->vars[var_idx].is_lexical) {
- dbuf_putc(bc, OP_get_loc_check);
+ if (op == OP_scope_get_var_checkthis) {
+ /* only used for 'this' return in derived class constructors */
+ dbuf_putc(bc, OP_get_loc_checkthis);
+ } else {
+ dbuf_putc(bc, OP_get_loc_check);
+ }
} else {
dbuf_putc(bc, OP_get_loc);
}
@@ -30263,12 +31033,17 @@ static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s,
/* obj func value */
dbuf_putc(bc, OP_call_method);
dbuf_put_u16(bc, 1);
+ dbuf_putc(bc, OP_drop);
}
break;
default:
abort();
}
break;
+ case OP_scope_in_private_field:
+ get_loc_or_ref(bc, is_ref, idx);
+ dbuf_putc(bc, OP_private_in);
+ break;
default:
abort();
}
@@ -30387,12 +31162,13 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
is_arg_scope = (scope_idx == ARG_SCOPE_END);
if (!is_arg_scope) {
/* add unscoped variables */
+ /* XXX: propagate is_const and var_kind too ? */
for(i = 0; i < fd->arg_count; i++) {
vd = &fd->args[i];
if (vd->var_name != JS_ATOM_NULL) {
get_closure_var(ctx, s, fd,
- TRUE, i, vd->var_name, FALSE, FALSE,
- JS_VAR_NORMAL);
+ TRUE, i, vd->var_name, FALSE,
+ vd->is_lexical, JS_VAR_NORMAL);
}
}
for(i = 0; i < fd->var_count; i++) {
@@ -30402,8 +31178,8 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
vd->var_name != JS_ATOM__ret_ &&
vd->var_name != JS_ATOM_NULL) {
get_closure_var(ctx, s, fd,
- FALSE, i, vd->var_name, FALSE, FALSE,
- JS_VAR_NORMAL);
+ FALSE, i, vd->var_name, FALSE,
+ vd->is_lexical, JS_VAR_NORMAL);
}
}
} else {
@@ -30412,8 +31188,8 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
/* do not close top level last result */
if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) {
get_closure_var(ctx, s, fd,
- FALSE, i, vd->var_name, FALSE, FALSE,
- JS_VAR_NORMAL);
+ FALSE, i, vd->var_name, FALSE,
+ vd->is_lexical, JS_VAR_NORMAL);
}
}
}
@@ -30446,7 +31222,7 @@ static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv,
/* for direct eval compilation: add references to the variables of the
calling function */
-static warn_unused int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
+static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
JSFunctionBytecode *b, int scope_idx)
{
int i, count;
@@ -30866,7 +31642,7 @@ static int get_label_pos(JSFunctionDef *s, int label)
/* convert global variable accesses to local variables or closure
variables when necessary */
-static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
+static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
{
int pos, pos_next, bc_len, op, len, i, idx, line_num;
uint8_t *bc_buf;
@@ -30945,6 +31721,7 @@ static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
dbuf_putc(&bc_out, op);
dbuf_put_u16(&bc_out, s->scopes[scope].first + 1);
break;
+ case OP_scope_get_var_checkthis:
case OP_scope_get_var_undef:
case OP_scope_get_var:
case OP_scope_put_var:
@@ -30974,6 +31751,7 @@ static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
case OP_scope_get_private_field:
case OP_scope_get_private_field2:
case OP_scope_put_private_field:
+ case OP_scope_in_private_field:
{
int ret;
var_name = get_u32(bc_buf + pos + 1);
@@ -31186,6 +31964,17 @@ static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
/* only used during parsing */
break;
+ case OP_get_field_opt_chain: /* equivalent to OP_get_field */
+ {
+ JSAtom name = get_u32(bc_buf + pos + 1);
+ dbuf_putc(&bc_out, OP_get_field);
+ dbuf_put_u32(&bc_out, name);
+ }
+ break;
+ case OP_get_array_el_opt_chain: /* equivalent to OP_get_array_el */
+ dbuf_putc(&bc_out, OP_get_array_el);
+ break;
+
default:
no_change:
dbuf_put(&bc_out, bc_buf + pos, len);
@@ -31430,7 +32219,7 @@ static void put_short_code(DynBuf *bc_out, int op, int idx)
}
/* peephole optimizations and resolve goto/labels */
-static warn_unused int resolve_labels(JSContext *ctx, JSFunctionDef *s)
+static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
{
int pos, pos_next, bc_len, op, op1, len, i, line_num;
const uint8_t *bc_buf;
@@ -32239,7 +33028,8 @@ static warn_unused int resolve_labels(JSContext *ctx, JSFunctionDef *s)
bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false);
}
goto shrink;
- } else if (diff == (int16_t)diff && op == OP_goto) {
+ } else
+ if (diff == (int16_t)diff && op == OP_goto) {
//put_u16(bc_out.buf + pos, diff);
jp->size = 2;
delta = 2;
@@ -32316,14 +33106,15 @@ typedef struct StackSizeState {
int bc_len;
int stack_len_max;
uint16_t *stack_level_tab;
+ int32_t *catch_pos_tab;
int *pc_stack;
int pc_stack_len;
int pc_stack_size;
} StackSizeState;
/* 'op' is only used for error indication */
-static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
- int pos, int op, int stack_len)
+static __exception int ss_check(JSContext *ctx, StackSizeState *s,
+ int pos, int op, int stack_len, int catch_pos)
{
if ((unsigned)pos >= s->bc_len) {
JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);
@@ -32339,9 +33130,13 @@ static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
if (s->stack_level_tab[pos] != 0xffff) {
/* already explored: check that the stack size is consistent */
if (s->stack_level_tab[pos] != stack_len) {
- JS_ThrowInternalError(ctx, "unconsistent stack size: %d %d (pc=%d)",
+ JS_ThrowInternalError(ctx, "inconsistent stack size: %d %d (pc=%d)",
s->stack_level_tab[pos], stack_len, pos);
return -1;
+ } else if (s->catch_pos_tab[pos] != catch_pos) {
+ JS_ThrowInternalError(ctx, "inconsistent catch position: %d %d (pc=%d)",
+ s->catch_pos_tab[pos], catch_pos, pos);
+ return -1;
} else {
return 0;
}
@@ -32349,6 +33144,7 @@ static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
/* mark as explored and store the stack size */
s->stack_level_tab[pos] = stack_len;
+ s->catch_pos_tab[pos] = catch_pos;
/* queue the new PC to explore */
if (js_resize_array(ctx, (void **)&s->pc_stack, sizeof(s->pc_stack[0]),
@@ -32358,12 +33154,12 @@ static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
return 0;
}
-static warn_unused int compute_stack_size(JSContext *ctx,
+static __exception int compute_stack_size(JSContext *ctx,
JSFunctionDef *fd,
int *pstack_size)
{
StackSizeState s_s, *s = &s_s;
- int i, diff, n_pop, pos_next, stack_len, pos, op;
+ int i, diff, n_pop, pos_next, stack_len, pos, op, catch_pos, catch_level;
const JSOpCode *oi;
const uint8_t *bc_buf;
@@ -32376,24 +33172,33 @@ static warn_unused int compute_stack_size(JSContext *ctx,
return -1;
for(i = 0; i < s->bc_len; i++)
s->stack_level_tab[i] = 0xffff;
- s->stack_len_max = 0;
s->pc_stack = NULL;
+ s->catch_pos_tab = js_malloc(ctx, sizeof(s->catch_pos_tab[0]) *
+ s->bc_len);
+ if (!s->catch_pos_tab)
+ goto fail;
+
+ s->stack_len_max = 0;
s->pc_stack_len = 0;
s->pc_stack_size = 0;
/* breadth-first graph exploration */
- if (ss_check(ctx, s, 0, OP_invalid, 0))
+ if (ss_check(ctx, s, 0, OP_invalid, 0, -1))
goto fail;
while (s->pc_stack_len > 0) {
pos = s->pc_stack[--s->pc_stack_len];
stack_len = s->stack_level_tab[pos];
+ catch_pos = s->catch_pos_tab[pos];
op = bc_buf[pos];
if (op == 0 || op >= OP_COUNT) {
JS_ThrowInternalError(ctx, "invalid opcode (op=%d, pc=%d)", op, pos);
goto fail;
}
oi = &short_opcode_info(op);
+#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 64)
+ printf("%5d: %10s %5d %5d\n", pos, oi->name, stack_len, catch_pos);
+#endif
pos_next = pos + oi->size;
if (pos_next > s->bc_len) {
JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);
@@ -32449,55 +33254,104 @@ static warn_unused int compute_stack_size(JSContext *ctx,
case OP_if_true8:
case OP_if_false8:
diff = (int8_t)bc_buf[pos + 1];
- if (ss_check(ctx, s, pos + 1 + diff, op, stack_len))
+ if (ss_check(ctx, s, pos + 1 + diff, op, stack_len, catch_pos))
goto fail;
break;
#endif
case OP_if_true:
case OP_if_false:
- case OP_catch:
diff = get_u32(bc_buf + pos + 1);
- if (ss_check(ctx, s, pos + 1 + diff, op, stack_len))
+ if (ss_check(ctx, s, pos + 1 + diff, op, stack_len, catch_pos))
goto fail;
break;
case OP_gosub:
diff = get_u32(bc_buf + pos + 1);
- if (ss_check(ctx, s, pos + 1 + diff, op, stack_len + 1))
+ if (ss_check(ctx, s, pos + 1 + diff, op, stack_len + 1, catch_pos))
goto fail;
break;
case OP_with_get_var:
case OP_with_delete_var:
diff = get_u32(bc_buf + pos + 5);
- if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 1))
+ if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 1, catch_pos))
goto fail;
break;
case OP_with_make_ref:
case OP_with_get_ref:
case OP_with_get_ref_undef:
diff = get_u32(bc_buf + pos + 5);
- if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 2))
+ if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 2, catch_pos))
goto fail;
break;
case OP_with_put_var:
diff = get_u32(bc_buf + pos + 5);
- if (ss_check(ctx, s, pos + 5 + diff, op, stack_len - 1))
+ if (ss_check(ctx, s, pos + 5 + diff, op, stack_len - 1, catch_pos))
goto fail;
break;
-
+ case OP_catch:
+ diff = get_u32(bc_buf + pos + 1);
+ if (ss_check(ctx, s, pos + 1 + diff, op, stack_len, catch_pos))
+ goto fail;
+ catch_pos = pos;
+ break;
+ case OP_for_of_start:
+ case OP_for_await_of_start:
+ catch_pos = pos;
+ break;
+ /* we assume the catch offset entry is only removed with
+ some op codes */
+ case OP_drop:
+ catch_level = stack_len;
+ goto check_catch;
+ case OP_nip:
+ catch_level = stack_len - 1;
+ goto check_catch;
+ case OP_nip1:
+ catch_level = stack_len - 1;
+ goto check_catch;
+ case OP_iterator_close:
+ catch_level = stack_len + 2;
+ check_catch:
+ /* Note: for for_of_start/for_await_of_start we consider
+ the catch offset is on the first stack entry instead of
+ the thirst */
+ if (catch_pos >= 0) {
+ int level;
+ level = s->stack_level_tab[catch_pos];
+ if (bc_buf[catch_pos] != OP_catch)
+ level++; /* for_of_start, for_wait_of_start */
+ /* catch_level = stack_level before op_catch is executed ? */
+ if (catch_level == level) {
+ catch_pos = s->catch_pos_tab[catch_pos];
+ }
+ }
+ break;
+ case OP_nip_catch:
+ if (catch_pos < 0) {
+ JS_ThrowInternalError(ctx, "nip_catch: no catch op (pc=%d)", pos);
+ goto fail;
+ }
+ stack_len = s->stack_level_tab[catch_pos];
+ if (bc_buf[catch_pos] != OP_catch)
+ stack_len++; /* for_of_start, for_wait_of_start */
+ stack_len++; /* no stack overflow is possible by construction */
+ catch_pos = s->catch_pos_tab[catch_pos];
+ break;
default:
break;
}
- if (ss_check(ctx, s, pos_next, op, stack_len))
+ if (ss_check(ctx, s, pos_next, op, stack_len, catch_pos))
goto fail;
done_insn: ;
}
- js_free(ctx, s->stack_level_tab);
js_free(ctx, s->pc_stack);
+ js_free(ctx, s->catch_pos_tab);
+ js_free(ctx, s->stack_level_tab);
*pstack_size = s->stack_len_max;
return 0;
fail:
- js_free(ctx, s->stack_level_tab);
js_free(ctx, s->pc_stack);
+ js_free(ctx, s->catch_pos_tab);
+ js_free(ctx, s->stack_level_tab);
*pstack_size = 0;
return -1;
}
@@ -32679,10 +33533,8 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
}
} else {
b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
- if (fd->arg_count)
- memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
- if (fd->var_count)
- memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
+ memcpy_no_ub(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
+ memcpy_no_ub(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
}
b->var_count = fd->var_count;
b->arg_count = fd->arg_count;
@@ -32744,6 +33596,8 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->super_allowed = fd->super_allowed;
b->arguments_allowed = fd->arguments_allowed;
b->backtrace_barrier = fd->backtrace_barrier;
+ b->is_direct_or_indirect_eval = (fd->eval_type == JS_EVAL_TYPE_DIRECT ||
+ fd->eval_type == JS_EVAL_TYPE_INDIRECT);
b->realm = JS_DupContext(ctx);
add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
@@ -32809,7 +33663,7 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)
}
}
-static warn_unused int js_parse_directives(JSParseState *s)
+static __exception int js_parse_directives(JSParseState *s)
{
char str[20];
JSParsePos pos;
@@ -32983,7 +33837,7 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s)
/* func_name must be JS_ATOM_NULL for JS_PARSE_FUNC_STATEMENT and
JS_PARSE_FUNC_EXPR, JS_PARSE_FUNC_ARROW and JS_PARSE_FUNC_VAR */
-static warn_unused int js_parse_function_decl2(JSParseState *s,
+static __exception int js_parse_function_decl2(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name,
@@ -33026,8 +33880,9 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
func_type == JS_PARSE_FUNC_EXPR &&
(func_kind & JS_FUNC_GENERATOR)) ||
(s->token.u.ident.atom == JS_ATOM_await &&
- func_type == JS_PARSE_FUNC_EXPR &&
- (func_kind & JS_FUNC_ASYNC))) {
+ ((func_type == JS_PARSE_FUNC_EXPR &&
+ (func_kind & JS_FUNC_ASYNC)) ||
+ func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))) {
return js_parse_error_reserved_identifier(s);
}
}
@@ -33121,7 +33976,8 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
func_type == JS_PARSE_FUNC_SETTER ||
func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR ||
func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
- fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW);
+ fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW &&
+ func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT);
fd->has_this_binding = fd->has_arguments_binding;
fd->is_derived_class_constructor = (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
if (func_type == JS_PARSE_FUNC_ARROW) {
@@ -33129,6 +33985,11 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
fd->super_call_allowed = fd->parent->super_call_allowed;
fd->super_allowed = fd->parent->super_allowed;
fd->arguments_allowed = fd->parent->arguments_allowed;
+ } else if (func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
+ fd->new_target_allowed = TRUE; // although new.target === undefined
+ fd->super_call_allowed = FALSE;
+ fd->super_allowed = TRUE;
+ fd->arguments_allowed = FALSE;
} else {
fd->new_target_allowed = TRUE;
fd->super_call_allowed = fd->is_derived_class_constructor;
@@ -33166,7 +34027,7 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
if (add_arg(ctx, fd, name) < 0)
goto fail;
fd->defined_arg_count = 1;
- } else {
+ } else if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) {
if (s->token.val == '(') {
int skip_bits;
/* if there is an '=' inside the parameter list, we
@@ -33227,6 +34088,8 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
goto fail;
}
if (fd->has_parameter_expressions) {
+ if (js_parse_check_duplicate_parameter(s, name))
+ goto fail;
if (define_var(s, fd, name, JS_VAR_DEF_LET) < 0)
goto fail;
}
@@ -33387,8 +34250,10 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
}
}
- if (js_parse_expect(s, '{'))
- goto fail;
+ if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) {
+ if (js_parse_expect(s, '{'))
+ goto fail;
+ }
if (js_parse_directives(s))
goto fail;
@@ -33418,9 +34283,15 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
if (js_is_live_code(s)) {
emit_return(s, FALSE);
}
-done:
+ done:
s->cur_func = fd->parent;
+ /* Reparse identifiers after the function is terminated so that
+ the token is parsed in the englobing function. It could be done
+ by just using next_token() here for normal functions, but it is
+ necessary for arrow functions with an expression body. */
+ reparse_ident_token(s);
+
/* create the function object */
{
int idx;
@@ -33531,7 +34402,7 @@ done:
return -1;
}
-static warn_unused int js_parse_function_decl(JSParseState *s,
+static __exception int js_parse_function_decl(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name,
@@ -33543,7 +34414,7 @@ static warn_unused int js_parse_function_decl(JSParseState *s,
NULL);
}
-static warn_unused int js_parse_program(JSParseState *s)
+static __exception int js_parse_program(JSParseState *s)
{
JSFunctionDef *fd = s->cur_func;
int idx;
@@ -33572,12 +34443,24 @@ static warn_unused int js_parse_program(JSParseState *s)
if (!s->is_module) {
/* return the value of the hidden variable eval_ret_idx */
- emit_op(s, OP_get_loc);
- emit_u16(s, fd->eval_ret_idx);
+ if (fd->func_kind == JS_FUNC_ASYNC) {
+ /* wrap the return value in an object so that promises can
+ be safely returned */
+ emit_op(s, OP_object);
+ emit_op(s, OP_dup);
- emit_op(s, OP_return);
+ emit_op(s, OP_get_loc);
+ emit_u16(s, fd->eval_ret_idx);
+
+ emit_op(s, OP_put_field);
+ emit_atom(s, JS_ATOM_value);
+ } else {
+ emit_op(s, OP_get_loc);
+ emit_u16(s, fd->eval_ret_idx);
+ }
+ emit_return(s, TRUE);
} else {
- emit_op(s, OP_return_undef);
+ emit_return(s, FALSE);
}
return 0;
@@ -33620,7 +34503,6 @@ static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj,
ret_val = js_evaluate_module(ctx, m);
if (JS_IsException(ret_val)) {
fail:
- js_free_modules(ctx, JS_FREE_MODULE_NOT_EVALUATED);
return JS_EXCEPTION;
}
} else {
@@ -33635,33 +34517,8 @@ JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj)
return JS_EvalFunctionInternal(ctx, fun_obj, ctx->global_obj, NULL, NULL);
}
-static void skip_shebang(JSParseState *s)
-{
- const uint8_t *p = s->buf_ptr;
- int c;
-
- if (p[0] == '#' && p[1] == '!') {
- p += 2;
- while (p < s->buf_end) {
- if (*p == '\n' || *p == '\r') {
- break;
- } else if (*p >= 0x80) {
- c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
- if (c == CP_LS || c == CP_PS) {
- break;
- } else if (c == -1) {
- p++; /* skip invalid UTF-8 */
- }
- } else {
- p++;
- }
- }
- s->buf_ptr = p;
- }
-}
-
/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
-static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
+static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
const char *input, size_t input_len,
const char *filename, int line, int flags, int scope_idx)
{
@@ -33675,7 +34532,7 @@ static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
JSModuleDef *m;
js_parse_init(ctx, s, input, input_len, filename, line);
- skip_shebang(s);
+ skip_shebang(&s->buf_ptr, s->buf_end);
eval_type = flags & JS_EVAL_TYPE_MASK;
m = NULL;
@@ -33733,6 +34590,10 @@ static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
goto fail;
}
fd->module = m;
+ if (m != NULL || (flags & JS_EVAL_FLAG_ASYNC)) {
+ fd->in_function_body = TRUE;
+ fd->func_kind = JS_FUNC_ASYNC;
+ }
s->is_module = (m != NULL);
s->allow_html_comments = !s->is_module;
@@ -33747,6 +34608,9 @@ static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
goto fail1;
}
+ if (m != NULL)
+ m->has_tla = fd->has_await;
+
/* create the function object and all the enclosed functions */
fun_obj = js_create_function(ctx, fd);
if (JS_IsException(fun_obj))
@@ -33756,7 +34620,7 @@ static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
m->func_obj = fun_obj;
if (js_resolve_module(ctx, m) < 0)
goto fail1;
- fun_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
+ fun_obj = JS_NewModuleValue(ctx, m);
}
if (flags & JS_EVAL_FLAG_COMPILE_ONLY) {
ret_val = fun_obj;
@@ -33952,8 +34816,6 @@ typedef enum BCTagEnum {
BC_TAG_OBJECT,
BC_TAG_ARRAY,
BC_TAG_BIG_INT,
- BC_TAG_BIG_FLOAT,
- BC_TAG_BIG_DECIMAL,
BC_TAG_TEMPLATE_OBJECT,
BC_TAG_FUNCTION_BYTECODE,
BC_TAG_MODULE,
@@ -33963,24 +34825,21 @@ typedef enum BCTagEnum {
BC_TAG_DATE,
BC_TAG_OBJECT_VALUE,
BC_TAG_OBJECT_REFERENCE,
+#ifdef CONFIG_BIGNUM
+ BC_TAG_BIG_FLOAT,
+ BC_TAG_BIG_DECIMAL,
+#endif
} BCTagEnum;
#ifdef CONFIG_BIGNUM
-#define BC_BASE_VERSION 2
+#define BC_VERSION 0x43
#else
-#define BC_BASE_VERSION 1
-#endif
-#define BC_BE_VERSION 0x40
-#ifdef WORDS_BIGENDIAN
-#define BC_VERSION (BC_BASE_VERSION | BC_BE_VERSION)
-#else
-#define BC_VERSION BC_BASE_VERSION
+#define BC_VERSION 3
#endif
typedef struct BCWriterState {
JSContext *ctx;
DynBuf dbuf;
- BOOL byte_swap : 8;
BOOL allow_bytecode : 8;
BOOL allow_sab : 8;
BOOL allow_reference : 8;
@@ -34010,8 +34869,6 @@ static const char * const bc_tag_str[] = {
"object",
"array",
"bigint",
- "bigfloat",
- "bigdecimal",
"template",
"function",
"module",
@@ -34021,9 +34878,22 @@ static const char * const bc_tag_str[] = {
"Date",
"ObjectValue",
"ObjectReference",
+#ifdef CONFIG_BIGNUM
+ "bigfloat",
+ "bigdecimal",
+#endif
};
#endif
+static inline BOOL is_be(void)
+{
+ union {
+ uint16_t a;
+ uint8_t b;
+ } u = {0x100};
+ return u.b;
+}
+
static void bc_put_u8(BCWriterState *s, uint8_t v)
{
dbuf_putc(&s->dbuf, v);
@@ -34031,21 +34901,21 @@ static void bc_put_u8(BCWriterState *s, uint8_t v)
static void bc_put_u16(BCWriterState *s, uint16_t v)
{
- if (s->byte_swap)
+ if (is_be())
v = bswap16(v);
dbuf_put_u16(&s->dbuf, v);
}
-static maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v)
+static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v)
{
- if (s->byte_swap)
+ if (is_be())
v = bswap32(v);
dbuf_put_u32(&s->dbuf, v);
}
static void bc_put_u64(BCWriterState *s, uint64_t v)
{
- if (s->byte_swap)
+ if (is_be())
v = bswap64(v);
dbuf_put(&s->dbuf, (uint8_t *)&v, sizeof(v));
}
@@ -34070,7 +34940,7 @@ static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom)
{
uint32_t v;
- if (atom < s->first_atom || JS_AtomIsTaggedInt(atom)) {
+ if (atom < s->first_atom || __JS_AtomIsTaggedInt(atom)) {
*pres = atom;
return 0;
}
@@ -34110,8 +34980,8 @@ static int bc_put_atom(BCWriterState *s, JSAtom atom)
{
uint32_t v;
- if (JS_AtomIsTaggedInt(atom)) {
- v = (JS_AtomToUInt32(atom) << 1) | 1;
+ if (__JS_AtomIsTaggedInt(atom)) {
+ v = (__JS_AtomToUInt32(atom) << 1) | 1;
} else {
if (bc_atom_to_idx(s, &v, atom))
return -1;
@@ -34215,7 +35085,7 @@ static int JS_WriteFunctionBytecode(BCWriterState *s,
pos += len;
}
- if (s->byte_swap)
+ if (is_be())
bc_byte_swap(bc_buf, bc_len);
dbuf_put(&s->dbuf, bc_buf, bc_len);
@@ -34230,7 +35100,7 @@ static int JS_WriteFunctionBytecode(BCWriterState *s,
static void JS_WriteString(BCWriterState *s, JSString *p)
{
int i;
- bc_put_leb128(s, (p->len << 1) | p->is_wide_char);
+ bc_put_leb128(s, ((uint32_t)p->len << 1) | p->is_wide_char);
if (p->is_wide_char) {
for(i = 0; i < p->len; i++)
bc_put_u16(s, p->u.str16[i]);
@@ -34239,7 +35109,6 @@ static void JS_WriteString(BCWriterState *s, JSString *p)
}
}
-#ifdef CONFIG_BIGNUM
static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
{
uint32_t tag, tag1;
@@ -34254,12 +35123,14 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
case JS_TAG_BIG_INT:
tag1 = BC_TAG_BIG_INT;
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
tag1 = BC_TAG_BIG_FLOAT;
break;
case JS_TAG_BIG_DECIMAL:
tag1 = BC_TAG_BIG_DECIMAL;
break;
+#endif
default:
abort();
}
@@ -34276,7 +35147,7 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
e = a->expn + 3;
else
e = a->expn;
- e = (e << 1) | a->sign;
+ e = (e * 2) | a->sign;
if (e < INT32_MIN || e > INT32_MAX) {
JS_ThrowInternalError(s->ctx, "bignum exponent is too large");
return -1;
@@ -34305,20 +35176,14 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
bc_put_leb128(s, len);
/* always saved in byte based little endian representation */
for(j = 0; j < n1; j++) {
- dbuf_putc(&s->dbuf, v >> (j * 8));
+ bc_put_u8(s, v >> (j * 8));
}
for(; i < a->len; i++) {
limb_t v = a->tab[i];
#if LIMB_BITS == 32
-#ifdef WORDS_BIGENDIAN
- v = bswap32(v);
-#endif
- dbuf_put_u32(&s->dbuf, v);
+ bc_put_u32(s, v);
#else
-#ifdef WORDS_BIGENDIAN
- v = bswap64(v);
-#endif
- dbuf_put_u64(&s->dbuf, v);
+ bc_put_u64(s, v);
#endif
}
} else {
@@ -34361,20 +35226,19 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
v8 = d;
bpos = 1;
} else {
- dbuf_putc(&s->dbuf, v8 | (d << 4));
+ bc_put_u8(s, v8 | (d << 4));
bpos = 0;
}
}
}
/* flush the last digit */
if (bpos) {
- dbuf_putc(&s->dbuf, v8);
+ bc_put_u8(s, v8);
}
}
}
return 0;
}
-#endif /* CONFIG_BIGNUM */
static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj);
@@ -34397,6 +35261,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
bc_set_flags(&flags, &idx, b->arguments_allowed, 1);
bc_set_flags(&flags, &idx, b->has_debug, 1);
bc_set_flags(&flags, &idx, b->backtrace_barrier, 1);
+ bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1);
assert(idx <= 16);
bc_put_u16(s, flags);
bc_put_u8(s, b->js_mode);
@@ -34503,6 +35368,8 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
bc_put_leb128(s, mi->req_module_idx);
}
+ bc_put_u8(s, m->has_tla);
+
if (JS_WriteObjectRec(s, m->func_obj))
goto fail;
return 0;
@@ -34731,8 +35598,8 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
case JS_CLASS_NUMBER:
case JS_CLASS_STRING:
case JS_CLASS_BOOLEAN:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT:
case JS_CLASS_BIG_DECIMAL:
#endif
@@ -34754,14 +35621,14 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
goto fail;
}
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
case JS_TAG_BIG_DECIMAL:
+#endif
if (JS_WriteBigNum(s, obj))
goto fail;
break;
-#endif
default:
invalid_tag:
JS_ThrowInternalError(s->ctx, "unsupported tag (%d)", tag);
@@ -34779,15 +35646,10 @@ static int JS_WriteObjectAtoms(BCWriterState *s)
JSRuntime *rt = s->ctx->rt;
DynBuf dbuf1;
int i, atoms_size;
- uint8_t version;
dbuf1 = s->dbuf;
js_dbuf_init(s->ctx, &s->dbuf);
-
- version = BC_VERSION;
- if (s->byte_swap)
- version ^= BC_BE_VERSION;
- bc_put_u8(s, version);
+ bc_put_u8(s, BC_VERSION);
bc_put_leb128(s, s->idx_to_atom_count);
for(i = 0; i < s->idx_to_atom_count; i++) {
@@ -34820,8 +35682,6 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
memset(s, 0, sizeof(*s));
s->ctx = ctx;
- /* XXX: byte swapped output is untested */
- s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0);
s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);
s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0);
s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0);
@@ -34942,33 +35802,45 @@ static int bc_get_u8(BCReaderState *s, uint8_t *pval)
static int bc_get_u16(BCReaderState *s, uint16_t *pval)
{
+ uint16_t v;
if (unlikely(s->buf_end - s->ptr < 2)) {
*pval = 0; /* avoid warning */
return bc_read_error_end(s);
}
- *pval = get_u16(s->ptr);
+ v = get_u16(s->ptr);
+ if (is_be())
+ v = bswap16(v);
+ *pval = v;
s->ptr += 2;
return 0;
}
-static maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
+static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
{
+ uint32_t v;
if (unlikely(s->buf_end - s->ptr < 4)) {
*pval = 0; /* avoid warning */
return bc_read_error_end(s);
}
- *pval = get_u32(s->ptr);
+ v = get_u32(s->ptr);
+ if (is_be())
+ v = bswap32(v);
+ *pval = v;
s->ptr += 4;
return 0;
}
static int bc_get_u64(BCReaderState *s, uint64_t *pval)
{
+ uint64_t v;
if (unlikely(s->buf_end - s->ptr < 8)) {
*pval = 0; /* avoid warning */
return bc_read_error_end(s);
}
- *pval = get_u64(s->ptr);
+ v = get_u64(s->ptr);
+ if (is_be())
+ v = bswap64(v);
+ *pval = v;
s->ptr += 8;
return 0;
}
@@ -35025,7 +35897,7 @@ static int bc_idx_to_atom(BCReaderState *s, JSAtom *patom, uint32_t idx)
{
JSAtom atom;
- if (JS_AtomIsTaggedInt(idx)) {
+ if (__JS_AtomIsTaggedInt(idx)) {
atom = idx;
} else if (idx < s->first_atom) {
atom = JS_DupAtom(s->ctx, idx);
@@ -35049,7 +35921,7 @@ static int bc_get_atom(BCReaderState *s, JSAtom *patom)
if (bc_get_leb128(s, &v))
return -1;
if (v & 1) {
- *patom = JS_AtomFromUInt32(v >> 1);
+ *patom = __JS_AtomFromUInt32(v >> 1);
return 0;
} else {
return bc_idx_to_atom(s, patom, v >> 1);
@@ -35080,7 +35952,13 @@ static JSString *JS_ReadString(BCReaderState *s)
}
memcpy(p->u.str8, s->ptr, size);
s->ptr += size;
- if (!is_wide_char) {
+ if (is_wide_char) {
+ if (is_be()) {
+ uint32_t i;
+ for (i = 0; i < len; i++)
+ p->u.str16[i] = bswap16(p->u.str16[i]);
+ }
+ } else {
p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */
}
#ifdef DUMP_READ_OBJECT
@@ -35119,6 +35997,9 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
}
b->byte_code_buf = bc_buf;
+ if (is_be())
+ bc_byte_swap(bc_buf, bc_len);
+
pos = 0;
while (pos < bc_len) {
op = bc_buf[pos];
@@ -35153,18 +36034,16 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
return 0;
}
-#ifdef CONFIG_BIGNUM
static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
{
JSValue obj = JS_UNDEFINED;
uint8_t v8;
int32_t e;
uint32_t len;
- limb_t l, i, n, j;
+ limb_t l, i, n;
JSBigFloat *p;
limb_t v;
bf_t *a;
- int bpos, d;
p = js_new_bf(s->ctx);
if (!p)
@@ -35173,12 +36052,14 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
case BC_TAG_BIG_INT:
obj = JS_MKPTR(JS_TAG_BIG_INT, p);
break;
+#ifdef CONFIG_BIGNUM
case BC_TAG_BIG_FLOAT:
obj = JS_MKPTR(JS_TAG_BIG_FLOAT, p);
break;
case BC_TAG_BIG_DECIMAL:
obj = JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
break;
+#endif
default:
abort();
}
@@ -35212,45 +36093,23 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
JS_ThrowInternalError(s->ctx, "invalid bignum length");
goto fail;
}
- if (tag != BC_TAG_BIG_DECIMAL)
- l = (len + sizeof(limb_t) - 1) / sizeof(limb_t);
- else
+#ifdef CONFIG_BIGNUM
+ if (tag == BC_TAG_BIG_DECIMAL) {
l = (len + LIMB_DIGITS - 1) / LIMB_DIGITS;
+ } else
+#endif
+ {
+ l = (len + sizeof(limb_t) - 1) / sizeof(limb_t);
+ }
if (bf_resize(a, l)) {
JS_ThrowOutOfMemory(s->ctx);
goto fail;
}
- if (tag != BC_TAG_BIG_DECIMAL) {
- n = len & (sizeof(limb_t) - 1);
- if (n != 0) {
- v = 0;
- for(i = 0; i < n; i++) {
- if (bc_get_u8(s, &v8))
- goto fail;
- v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8);
- }
- a->tab[0] = v;
- i = 1;
- } else {
- i = 0;
- }
- for(; i < l; i++) {
-#if LIMB_BITS == 32
- if (bc_get_u32(s, &v))
- goto fail;
-#ifdef WORDS_BIGENDIAN
- v = bswap32(v);
-#endif
-#else
- if (bc_get_u64(s, &v))
- goto fail;
-#ifdef WORDS_BIGENDIAN
- v = bswap64(v);
-#endif
-#endif
- a->tab[i] = v;
- }
- } else {
+#ifdef CONFIG_BIGNUM
+ if (tag == BC_TAG_BIG_DECIMAL) {
+ limb_t j;
+ int bpos, d;
+
bpos = 0;
for(i = 0; i < l; i++) {
if (i == 0 && (n = len % LIMB_DIGITS) != 0) {
@@ -35277,6 +36136,32 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
}
a->tab[i] = v;
}
+ } else
+#endif /* CONFIG_BIGNUM */
+ {
+ n = len & (sizeof(limb_t) - 1);
+ if (n != 0) {
+ v = 0;
+ for(i = 0; i < n; i++) {
+ if (bc_get_u8(s, &v8))
+ goto fail;
+ v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8);
+ }
+ a->tab[0] = v;
+ i = 1;
+ } else {
+ i = 0;
+ }
+ for(; i < l; i++) {
+#if LIMB_BITS == 32
+ if (bc_get_u32(s, &v))
+ goto fail;
+#else
+ if (bc_get_u64(s, &v))
+ goto fail;
+#endif
+ a->tab[i] = v;
+ }
}
}
bc_read_trace(s, "}\n");
@@ -35285,7 +36170,6 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
JS_FreeValue(s->ctx, obj);
return JS_EXCEPTION;
}
-#endif /* CONFIG_BIGNUM */
static JSValue JS_ReadObjectRec(BCReaderState *s);
@@ -35335,6 +36219,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
bc.arguments_allowed = bc_get_flags(v16, &idx, 1);
bc.has_debug = bc_get_flags(v16, &idx, 1);
bc.backtrace_barrier = bc_get_flags(v16, &idx, 1);
+ bc.is_direct_or_indirect_eval = bc_get_flags(v16, &idx, 1);
bc.read_only_bytecode = s->is_rom_data;
if (bc_get_u8(s, &v8))
goto fail;
@@ -35513,7 +36398,7 @@ static JSValue JS_ReadModule(BCReaderState *s)
m = js_new_module_def(ctx, module_name);
if (!m)
goto fail;
- obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
+ obj = JS_NewModuleValue(ctx, m);
if (bc_get_leb128_int(s, &m->req_module_entries_count))
goto fail;
if (m->req_module_entries_count != 0) {
@@ -35586,6 +36471,10 @@ static JSValue JS_ReadModule(BCReaderState *s)
}
}
+ if (bc_get_u8(s, &v8))
+ goto fail;
+ m->has_tla = (v8 != 0);
+
m->func_obj = JS_ReadObjectRec(s);
if (JS_IsException(m->func_obj))
goto fail;
@@ -35864,7 +36753,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
if (bc_get_u64(s, &u.u64))
return JS_EXCEPTION;
bc_read_trace(s, "%g\n", u.d);
- obj = JS_NewFloat64Impl(ctx, u.d);
+ obj = __JS_NewFloat64(ctx, u.d);
}
break;
case BC_TAG_STRING:
@@ -35910,13 +36799,13 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
case BC_TAG_OBJECT_VALUE:
obj = JS_ReadObjectValue(s);
break;
-#ifdef CONFIG_BIGNUM
case BC_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case BC_TAG_BIG_FLOAT:
case BC_TAG_BIG_DECIMAL:
+#endif
obj = JS_ReadBigNum(s, tag);
break;
-#endif
case BC_TAG_OBJECT_REFERENCE:
{
uint32_t val;
@@ -35950,7 +36839,6 @@ static int JS_ReadObjectAtoms(BCReaderState *s)
if (bc_get_u8(s, &v8))
return -1;
- /* XXX: could support byte swapped input */
if (v8 != BC_VERSION) {
JS_ThrowSyntaxError(s->ctx, "invalid version (%d expected=%d)",
v8, BC_VERSION);
@@ -36172,7 +37060,7 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
val = JS_NewInt64(ctx, e->u.i64);
break;
case JS_DEF_PROP_DOUBLE:
- val = JS_NewFloat64Impl(ctx, e->u.f64);
+ val = __JS_NewFloat64(ctx, e->u.f64);
break;
case JS_DEF_PROP_UNDEFINED:
val = JS_UNDEFINED;
@@ -36236,7 +37124,7 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
val = JS_NewInt64(ctx, e->u.i64);
break;
case JS_DEF_PROP_DOUBLE:
- val = JS_NewFloat64Impl(ctx, e->u.f64);
+ val = __JS_NewFloat64(ctx, e->u.f64);
break;
case JS_DEF_OBJECT:
val = JS_NewObject(ctx);
@@ -36325,12 +37213,10 @@ static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val,
static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
- BOOL res;
double d;
if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))
return JS_EXCEPTION;
- res = isfinite(d);
- return JS_NewBool(ctx, res);
+ return JS_NewBool(ctx, isfinite(d));
}
/* Object class */
@@ -36348,10 +37234,10 @@ static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)
case JS_TAG_OBJECT:
case JS_TAG_EXCEPTION:
return JS_DupValue(ctx, val);
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_INT);
goto set_value;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_FLOAT);
goto set_value;
@@ -36469,7 +37355,7 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
return -1;
}
-static warn_unused int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
+static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
JSAtom prop, JSValueConst desc,
int flags)
{
@@ -36485,7 +37371,7 @@ static warn_unused int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
return ret;
}
-static warn_unused int JS_ObjectDefineProperties(JSContext *ctx,
+static __exception int JS_ObjectDefineProperties(JSContext *ctx,
JSValueConst obj,
JSValueConst properties)
{
@@ -36724,13 +37610,13 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t
} else {
if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, desc.value), flags) < 0
|| JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,
- JS_NewBool(ctx, (desc.flags & JS_PROP_WRITABLE) != 0), flags) < 0)
+ JS_NewBool(ctx, desc.flags & JS_PROP_WRITABLE), flags) < 0)
goto exception1;
}
if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,
- JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0), flags) < 0
+ JS_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE), flags) < 0
|| JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,
- JS_NewBool(ctx, (desc.flags & JS_PROP_CONFIGURABLE) != 0), flags) < 0)
+ JS_NewBool(ctx, desc.flags & JS_PROP_CONFIGURABLE), flags) < 0)
goto exception1;
js_free_desc(ctx, &desc);
}
@@ -36970,6 +37856,32 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val,
return JS_NewBool(ctx, ret);
}
+static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue obj;
+ JSAtom atom;
+ JSObject *p;
+ BOOL ret;
+
+ obj = JS_ToObject(ctx, argv[0]);
+ if (JS_IsException(obj))
+ return obj;
+ atom = JS_ValueToAtom(ctx, argv[1]);
+ if (unlikely(atom == JS_ATOM_NULL)) {
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+ }
+ p = JS_VALUE_GET_OBJ(obj);
+ ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);
+ JS_FreeAtom(ctx, atom);
+ JS_FreeValue(ctx, obj);
+ if (ret < 0)
+ return JS_EXCEPTION;
+ else
+ return JS_NewBool(ctx, ret);
+}
+
static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -37459,7 +38371,7 @@ static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_
if (has_prop < 0)
goto exception;
if (has_prop) {
- res = JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0);
+ res = JS_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE);
js_free_desc(ctx, &desc);
} else {
res = JS_FALSE;
@@ -37516,32 +38428,6 @@ exception:
return res;
}
-static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue obj;
- JSAtom atom;
- JSObject *p;
- BOOL ret;
-
- obj = JS_ToObject(ctx, argv[0]);
- if (JS_IsException(obj))
- return obj;
- atom = JS_ValueToAtom(ctx, argv[1]);
- if (unlikely(atom == JS_ATOM_NULL)) {
- JS_FreeValue(ctx, obj);
- return JS_EXCEPTION;
- }
- p = JS_VALUE_GET_OBJ(obj);
- ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);
- JS_FreeAtom(ctx, atom);
- JS_FreeValue(ctx, obj);
- if (ret < 0)
- return JS_EXCEPTION;
- else
- return JS_NewBool(ctx, ret);
-}
-
static const JSCFunctionListEntry js_object_funcs[] = {
JS_CFUNC_DEF("create", 2, js_object_create ),
JS_CFUNC_MAGIC_DEF("getPrototypeOf", 1, js_object_getPrototypeOf, 0 ),
@@ -37550,6 +38436,7 @@ static const JSCFunctionListEntry js_object_funcs[] = {
JS_CFUNC_DEF("defineProperties", 2, js_object_defineProperties ),
JS_CFUNC_DEF("getOwnPropertyNames", 1, js_object_getOwnPropertyNames ),
JS_CFUNC_DEF("getOwnPropertySymbols", 1, js_object_getOwnPropertySymbols ),
+ JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 0 ),
JS_CFUNC_MAGIC_DEF("keys", 1, js_object_keys, JS_ITERATOR_KIND_KEY ),
JS_CFUNC_MAGIC_DEF("values", 1, js_object_keys, JS_ITERATOR_KIND_VALUE ),
JS_CFUNC_MAGIC_DEF("entries", 1, js_object_keys, JS_ITERATOR_KIND_KEY_AND_VALUE ),
@@ -37671,7 +38558,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
return JS_EXCEPTION;
}
-static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
+static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
JSValueConst obj)
{
JSValue len_val;
@@ -37683,7 +38570,7 @@ static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
return JS_ToUint32Free(ctx, pres, len_val);
}
-static warn_unused int js_get_length64(JSContext *ctx, int64_t *pres,
+static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
JSValueConst obj)
{
JSValue len_val;
@@ -37719,7 +38606,9 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
if (js_get_length32(ctx, &len, array_arg))
return NULL;
if (len > JS_MAX_LOCAL_VARS) {
- JS_ThrowInternalError(ctx, "too many arguments");
+ // XXX: check for stack overflow?
+ JS_ThrowRangeError(ctx, "too many arguments in function call (only %d allowed)",
+ JS_MAX_LOCAL_VARS);
return NULL;
}
/* avoid allocating 0 bytes */
@@ -37768,9 +38657,9 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
if (!tab)
return JS_EXCEPTION;
if (magic & 1) {
- ret = JS_CallConstructor2(ctx, this_val, this_arg, len, tab);
+ ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab);
} else {
- ret = JS_Call(ctx, this_val, this_arg, len, tab);
+ ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab);
}
free_arg_list(ctx, tab, len);
return ret;
@@ -37980,7 +38869,8 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
int argc, JSValueConst *argv, int magic)
{
JSValue obj, msg, proto;
- JSValueConst message;
+ JSValueConst message, options;
+ int arg_index;
if (JS_IsUndefined(new_target))
new_target = JS_GetActiveFunction(ctx);
@@ -38006,12 +38896,9 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
JS_FreeValue(ctx, proto);
if (JS_IsException(obj))
return obj;
- if (magic == JS_AGGREGATE_ERROR) {
- message = argv[1];
- } else {
- message = argv[0];
- }
+ arg_index = (magic == JS_AGGREGATE_ERROR);
+ message = argv[arg_index++];
if (!JS_IsUndefined(message)) {
msg = JS_ToString(ctx, message);
if (unlikely(JS_IsException(msg)))
@@ -38020,6 +38907,22 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
}
+ if (arg_index < argc) {
+ options = argv[arg_index];
+ if (JS_IsObject(options)) {
+ int present = JS_HasProperty(ctx, options, JS_ATOM_cause);
+ if (present < 0)
+ goto exception;
+ if (present) {
+ JSValue cause = JS_GetProperty(ctx, options, JS_ATOM_cause);
+ if (JS_IsException(cause))
+ goto exception;
+ JS_DefinePropertyValue(ctx, obj, JS_ATOM_cause, cause,
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
+ }
+ }
+ }
+
if (magic == JS_AGGREGATE_ERROR) {
JSValue error_list = iterator_to_array(ctx, argv[0]);
if (JS_IsException(error_list))
@@ -38413,6 +39316,106 @@ static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj)
return JS_IsArray(ctx, obj);
}
+static JSValue js_array_at(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue obj, ret;
+ int64_t len, idx;
+ JSValue *arrp;
+ uint32_t count;
+
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ if (JS_ToInt64Sat(ctx, &idx, argv[0]))
+ goto exception;
+
+ if (idx < 0)
+ idx = len + idx;
+ if (idx < 0 || idx >= len) {
+ ret = JS_UNDEFINED;
+ } else if (js_get_fast_array(ctx, obj, &arrp, &count) && idx < count) {
+ ret = JS_DupValue(ctx, arrp[idx]);
+ } else {
+ int present = JS_TryGetPropertyInt64(ctx, obj, idx, &ret);
+ if (present < 0)
+ goto exception;
+ if (!present)
+ ret = JS_UNDEFINED;
+ }
+ JS_FreeValue(ctx, obj);
+ return ret;
+ exception:
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+}
+
+static JSValue js_array_with(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, obj, ret, *arrp, *pval;
+ JSObject *p;
+ int64_t i, len, idx;
+ uint32_t count32;
+
+ ret = JS_EXCEPTION;
+ arr = JS_UNDEFINED;
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ if (JS_ToInt64Sat(ctx, &idx, argv[0]))
+ goto exception;
+
+ if (idx < 0)
+ idx = len + idx;
+
+ if (idx < 0 || idx >= len) {
+ JS_ThrowRangeError(ctx, "invalid array index: %" PRId64, idx);
+ goto exception;
+ }
+
+ arr = js_allocate_fast_array(ctx, len);
+ if (JS_IsException(arr))
+ goto exception;
+
+ p = JS_VALUE_GET_OBJ(arr);
+ i = 0;
+ pval = p->u.array.u.values;
+ if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
+ for (; i < idx; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ *pval = JS_DupValue(ctx, argv[1]);
+ for (i++, pval++; i < len; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ } else {
+ for (; i < idx; i++, pval++)
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
+ goto fill_and_fail;
+ *pval = JS_DupValue(ctx, argv[1]);
+ for (i++, pval++; i < len; i++, pval++) {
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
+ fill_and_fail:
+ for (; i < len; i++, pval++)
+ *pval = JS_UNDEFINED;
+ goto exception;
+ }
+ }
+ }
+
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ goto exception;
+
+ ret = arr;
+ arr = JS_UNDEFINED;
+
+exception:
+ JS_FreeValue(ctx, arr);
+ JS_FreeValue(ctx, obj);
+ return ret;
+}
+
static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -38778,9 +39781,10 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
JSValue obj, val;
- int64_t len, n, res;
+ int64_t len, n;
JSValue *arrp;
uint32_t count;
+ int res;
obj = JS_ToObject(ctx, this_val);
if (js_get_length64(ctx, &len, obj))
@@ -38911,13 +39915,21 @@ static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
+enum {
+ ArrayFind,
+ ArrayFindIndex,
+ ArrayFindLast,
+ ArrayFindLastIndex,
+};
+
static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int findIndex)
+ int argc, JSValueConst *argv, int mode)
{
JSValueConst func, this_arg;
JSValueConst args[3];
JSValue obj, val, index_val, res;
- int64_t len, k;
+ int64_t len, k, end;
+ int dir;
index_val = JS_UNDEFINED;
val = JS_UNDEFINED;
@@ -38933,7 +39945,17 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
if (argc > 1)
this_arg = argv[1];
- for(k = 0; k < len; k++) {
+ k = 0;
+ dir = 1;
+ end = len;
+ if (mode == ArrayFindLast || mode == ArrayFindLastIndex) {
+ k = len - 1;
+ dir = -1;
+ end = -1;
+ }
+
+ // TODO(bnoordhuis) add fast path for fast arrays
+ for(; k != end; k += dir) {
index_val = JS_NewInt64(ctx, k);
if (JS_IsException(index_val))
goto exception;
@@ -38947,7 +39969,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(res))
goto exception;
if (JS_ToBoolFree(ctx, res)) {
- if (findIndex) {
+ if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) {
JS_FreeValue(ctx, val);
JS_FreeValue(ctx, obj);
return index_val;
@@ -38961,7 +39983,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, index_val);
}
JS_FreeValue(ctx, obj);
- if (findIndex)
+ if (mode == ArrayFindIndex || mode == ArrayFindLastIndex)
return JS_NewInt32(ctx, -1);
else
return JS_UNDEFINED;
@@ -38984,7 +40006,8 @@ static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val,
method = JS_GetProperty(ctx, obj, JS_ATOM_join);
if (JS_IsException(method)) {
ret = JS_EXCEPTION;
- } else if (!JS_IsFunction(ctx, method)) {
+ } else
+ if (!JS_IsFunction(ctx, method)) {
/* Use intrinsic Object.prototype.toString */
JS_FreeValue(ctx, method);
ret = js_object_toString(ctx, obj, 0, NULL);
@@ -39211,6 +40234,61 @@ static JSValue js_array_reverse(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
+// Note: a.toReversed() is a.slice().reverse() with the twist that a.slice()
+// leaves holes in sparse arrays intact whereas a.toReversed() replaces them
+// with undefined, thus in effect creating a dense array.
+// Does not use Array[@@species], always returns a base Array.
+static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, obj, ret, *arrp, *pval;
+ JSObject *p;
+ int64_t i, len;
+ uint32_t count32;
+
+ ret = JS_EXCEPTION;
+ arr = JS_UNDEFINED;
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ arr = js_allocate_fast_array(ctx, len);
+ if (JS_IsException(arr))
+ goto exception;
+
+ if (len > 0) {
+ p = JS_VALUE_GET_OBJ(arr);
+
+ i = len - 1;
+ pval = p->u.array.u.values;
+ if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
+ for (; i >= 0; i--, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ } else {
+ // Query order is observable; test262 expects descending order.
+ for (; i >= 0; i--, pval++) {
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
+ // Exception; initialize remaining elements.
+ for (; i >= 0; i--, pval++)
+ *pval = JS_UNDEFINED;
+ goto exception;
+ }
+ }
+ }
+
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ goto exception;
+ }
+
+ ret = arr;
+ arr = JS_UNDEFINED;
+
+exception:
+ JS_FreeValue(ctx, arr);
+ JS_FreeValue(ctx, obj);
+ return ret;
+}
+
static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int splice)
{
@@ -39232,7 +40310,8 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
if (argc == 0) {
item_count = 0;
del_count = 0;
- } else if (argc == 1) {
+ } else
+ if (argc == 1) {
item_count = 0;
del_count = len - start;
} else {
@@ -39317,6 +40396,92 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
+static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, obj, ret, *arrp, *pval, *last;
+ JSObject *p;
+ int64_t i, j, len, newlen, start, add, del;
+ uint32_t count32;
+
+ pval = NULL;
+ last = NULL;
+ ret = JS_EXCEPTION;
+ arr = JS_UNDEFINED;
+
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ start = 0;
+ if (argc > 0)
+ if (JS_ToInt64Clamp(ctx, &start, argv[0], 0, len, len))
+ goto exception;
+
+ del = 0;
+ if (argc > 0)
+ del = len - start;
+ if (argc > 1)
+ if (JS_ToInt64Clamp(ctx, &del, argv[1], 0, del, 0))
+ goto exception;
+
+ add = 0;
+ if (argc > 2)
+ add = argc - 2;
+
+ newlen = len + add - del;
+ if (newlen > MAX_SAFE_INTEGER) {
+ JS_ThrowTypeError(ctx, "invalid array length");
+ goto exception;
+ }
+
+ arr = js_allocate_fast_array(ctx, newlen);
+ if (JS_IsException(arr))
+ goto exception;
+
+ if (newlen <= 0)
+ goto done;
+
+ p = JS_VALUE_GET_OBJ(arr);
+ pval = &p->u.array.u.values[0];
+ last = &p->u.array.u.values[newlen];
+
+ if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
+ for (i = 0; i < start; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ for (j = 0; j < add; j++, pval++)
+ *pval = JS_DupValue(ctx, argv[2 + j]);
+ for (i += del; i < len; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ } else {
+ for (i = 0; i < start; i++, pval++)
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
+ goto exception;
+ for (j = 0; j < add; j++, pval++)
+ *pval = JS_DupValue(ctx, argv[2 + j]);
+ for (i += del; i < len; i++, pval++)
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
+ goto exception;
+ }
+
+ assert(pval == last);
+
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, newlen)) < 0)
+ goto exception;
+
+done:
+ ret = arr;
+ arr = JS_UNDEFINED;
+
+exception:
+ while (pval != last)
+ *pval++ = JS_UNDEFINED;
+
+ JS_FreeValue(ctx, arr);
+ JS_FreeValue(ctx, obj);
+ return ret;
+}
+
static JSValue js_array_copyWithin(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -39620,6 +40785,68 @@ fail:
return JS_EXCEPTION;
}
+// Note: a.toSorted() is a.slice().sort() with the twist that a.slice()
+// leaves holes in sparse arrays intact whereas a.toSorted() replaces them
+// with undefined, thus in effect creating a dense array.
+// Does not use Array[@@species], always returns a base Array.
+static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, obj, ret, *arrp, *pval;
+ JSObject *p;
+ int64_t i, len;
+ uint32_t count32;
+ int ok;
+
+ ok = JS_IsUndefined(argv[0]) || JS_IsFunction(ctx, argv[0]);
+ if (!ok)
+ return JS_ThrowTypeError(ctx, "not a function");
+
+ ret = JS_EXCEPTION;
+ arr = JS_UNDEFINED;
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ arr = js_allocate_fast_array(ctx, len);
+ if (JS_IsException(arr))
+ goto exception;
+
+ if (len > 0) {
+ p = JS_VALUE_GET_OBJ(arr);
+ i = 0;
+ pval = p->u.array.u.values;
+ if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
+ for (; i < len; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ } else {
+ for (; i < len; i++, pval++) {
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
+ for (; i < len; i++, pval++)
+ *pval = JS_UNDEFINED;
+ goto exception;
+ }
+ }
+ }
+
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ goto exception;
+ }
+
+ ret = js_array_sort(ctx, arr, argc, argv);
+ if (JS_IsException(ret))
+ goto exception;
+ JS_FreeValue(ctx, ret);
+
+ ret = arr;
+ arr = JS_UNDEFINED;
+
+exception:
+ JS_FreeValue(ctx, arr);
+ JS_FreeValue(ctx, obj);
+ return ret;
+}
+
typedef struct JSArrayIteratorData {
JSValue obj;
JSIteratorKindEnum kind;
@@ -39772,6 +40999,8 @@ static const JSCFunctionListEntry js_iterator_proto_funcs[] = {
};
static const JSCFunctionListEntry js_array_proto_funcs[] = {
+ JS_CFUNC_DEF("at", 1, js_array_at ),
+ JS_CFUNC_DEF("with", 2, js_array_with ),
JS_CFUNC_DEF("concat", 1, js_array_concat ),
JS_CFUNC_MAGIC_DEF("every", 1, js_array_every, special_every ),
JS_CFUNC_MAGIC_DEF("some", 1, js_array_every, special_some ),
@@ -39781,8 +41010,10 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce ),
JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight ),
JS_CFUNC_DEF("fill", 1, js_array_fill ),
- JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, 0 ),
- JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, 1 ),
+ JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, ArrayFind ),
+ JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, ArrayFindIndex ),
+ JS_CFUNC_MAGIC_DEF("findLast", 1, js_array_find, ArrayFindLast ),
+ JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_array_find, ArrayFindLastIndex ),
JS_CFUNC_DEF("indexOf", 1, js_array_indexOf ),
JS_CFUNC_DEF("lastIndexOf", 1, js_array_lastIndexOf ),
JS_CFUNC_DEF("includes", 1, js_array_includes ),
@@ -39794,9 +41025,12 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("shift", 0, js_array_pop, 1 ),
JS_CFUNC_MAGIC_DEF("unshift", 1, js_array_push, 1 ),
JS_CFUNC_DEF("reverse", 0, js_array_reverse ),
+ JS_CFUNC_DEF("toReversed", 0, js_array_toReversed ),
JS_CFUNC_DEF("sort", 1, js_array_sort ),
+ JS_CFUNC_DEF("toSorted", 1, js_array_toSorted ),
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_slice, 0 ),
JS_CFUNC_MAGIC_DEF("splice", 2, js_array_slice, 1 ),
+ JS_CFUNC_DEF("toSpliced", 2, js_array_toSpliced ),
JS_CFUNC_DEF("copyWithin", 2, js_array_copyWithin ),
JS_CFUNC_MAGIC_DEF("flatMap", 1, js_array_flatten, 1 ),
JS_CFUNC_MAGIC_DEF("flat", 0, js_array_flatten, 0 ),
@@ -39824,17 +41058,19 @@ static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target,
if (JS_IsException(val))
return val;
switch(JS_VALUE_GET_TAG(val)) {
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
double d;
bf_get_float64(&p->num, &d, BF_RNDN);
JS_FreeValue(ctx, val);
- val = __JS_NewFloat64(ctx, d);
+ val = JS_NewFloat64(ctx, d);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL:
val = JS_ToStringFree(ctx, val);
if (JS_IsException(val))
@@ -39983,8 +41219,16 @@ static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val,
if (base < 0)
goto fail;
}
+ if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) {
+ char buf1[70], *ptr;
+ ptr = i64toa(buf1 + sizeof(buf1), JS_VALUE_GET_INT(val), base);
+ return JS_NewString(ctx, ptr);
+ }
if (JS_ToFloat64Free(ctx, &d, val))
return JS_EXCEPTION;
+ if (base != 10 && isfinite(d)) {
+ return js_dtoa_radix(ctx, d, base);
+ }
return js_dtoa(ctx, d, base, 0, JS_DTOA_VAR_FORMAT);
fail:
JS_FreeValue(ctx, val);
@@ -40008,7 +41252,7 @@ static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val,
if (f < 0 || f > 100)
return JS_ThrowRangeError(ctx, "invalid number of digits");
if (fabs(d) >= 1e21) {
- return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
+ return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
} else {
return js_dtoa(ctx, d, 10, f, JS_DTOA_FRAC_FORMAT);
}
@@ -40029,7 +41273,7 @@ static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val,
if (JS_ToInt32Sat(ctx, &f, argv[0]))
return JS_EXCEPTION;
if (!isfinite(d)) {
- return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
+ return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
}
if (JS_IsUndefined(argv[0])) {
flags = 0;
@@ -40061,7 +41305,7 @@ static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
if (!isfinite(d)) {
to_string:
- return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
+ return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
}
if (p < 1 || p > 100)
return JS_ThrowRangeError(ctx, "invalid number of digits");
@@ -40182,17 +41426,14 @@ static int js_string_get_own_property(JSContext *ctx,
uint32_t idx, ch;
/* This is a class exotic method: obj class_id is JS_CLASS_STRING */
- if (JS_AtomIsTaggedInt(prop)) {
+ if (__JS_AtomIsTaggedInt(prop)) {
p = JS_VALUE_GET_OBJ(obj);
if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {
p1 = JS_VALUE_GET_STRING(p->u.object_data);
- idx = JS_AtomToUInt32(prop);
+ idx = __JS_AtomToUInt32(prop);
if (idx < p1->len) {
if (desc) {
- if (p1->is_wide_char)
- ch = p1->u.str16[idx];
- else
- ch = p1->u.str8[idx];
+ ch = string_get(p1, idx);
desc->flags = JS_PROP_ENUMERABLE;
desc->value = js_new_string_char(ctx, ch);
desc->getter = JS_UNDEFINED;
@@ -40215,8 +41456,8 @@ static int js_string_define_own_property(JSContext *ctx,
JSObject *p;
JSString *p1, *p2;
- if (JS_AtomIsTaggedInt(prop)) {
- idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ idx = __JS_AtomToUInt32(prop);
p = JS_VALUE_GET_OBJ(this_obj);
if (JS_VALUE_GET_TAG(p->u.object_data) != JS_TAG_STRING)
goto def;
@@ -40250,8 +41491,8 @@ static int js_string_delete_property(JSContext *ctx,
{
uint32_t idx;
- if (JS_AtomIsTaggedInt(prop)) {
- idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ idx = __JS_AtomToUInt32(prop);
if (idx < js_string_obj_get_length(ctx, obj)) {
return FALSE;
}
@@ -40347,7 +41588,7 @@ static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val,
} else {
if (JS_ToFloat64(ctx, &d, argv[i]))
goto fail;
- if (d < 0 || d > 0x10ffff || (c = (int)d) != d)
+ if (isnan(d) || d < 0 || d > 0x10ffff || (c = (int)d) != d)
goto range_error;
}
if (string_buffer_putc(b, c))
@@ -40458,10 +41699,7 @@ static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val,
if (idx < 0 || idx >= p->len) {
ret = JS_NAN;
} else {
- if (p->is_wide_char)
- c = p->u.str16[idx];
- else
- c = p->u.str8[idx];
+ c = string_get(p, idx);
ret = JS_NewInt32(ctx, c);
}
JS_FreeValue(ctx, val);
@@ -40469,7 +41707,7 @@ static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val,
}
static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+ int argc, JSValueConst *argv, int is_at)
{
JSValue val, ret;
JSString *p;
@@ -40483,13 +41721,15 @@ static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
+ if (idx < 0 && is_at)
+ idx += p->len;
if (idx < 0 || idx >= p->len) {
- ret = js_new_string8(ctx, NULL, 0);
- } else {
- if (p->is_wide_char)
- c = p->u.str16[idx];
+ if (is_at)
+ ret = JS_UNDEFINED;
else
- c = p->u.str8[idx];
+ ret = js_new_string8(ctx, NULL, 0);
+ } else {
+ c = string_get(p, idx);
ret = js_new_string_char(ctx, c);
}
JS_FreeValue(ctx, val);
@@ -40597,6 +41837,80 @@ static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)
return index;
}
+/* return the position of the first invalid character in the string or
+ -1 if none */
+static int js_string_find_invalid_codepoint(JSString *p)
+{
+ int i;
+ if (!p->is_wide_char)
+ return -1;
+ for(i = 0; i < p->len; i++) {
+ uint32_t c = p->u.str16[i];
+ if (is_surrogate(c)) {
+ if (is_hi_surrogate(c) && (i + 1) < p->len
+ && is_lo_surrogate(p->u.str16[i + 1])) {
+ i++;
+ } else {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue str;
+ JSString *p;
+ BOOL ret;
+
+ str = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(str))
+ return JS_EXCEPTION;
+ p = JS_VALUE_GET_STRING(str);
+ ret = (js_string_find_invalid_codepoint(p) < 0);
+ JS_FreeValue(ctx, str);
+ return JS_NewBool(ctx, ret);
+}
+
+static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue str, ret;
+ JSString *p;
+ int i;
+
+ str = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(str))
+ return JS_EXCEPTION;
+
+ p = JS_VALUE_GET_STRING(str);
+ /* avoid reallocating the string if it is well-formed */
+ i = js_string_find_invalid_codepoint(p);
+ if (i < 0)
+ return str;
+
+ ret = js_new_string16(ctx, p->u.str16, p->len);
+ JS_FreeValue(ctx, str);
+ if (JS_IsException(ret))
+ return JS_EXCEPTION;
+
+ p = JS_VALUE_GET_STRING(ret);
+ for (; i < p->len; i++) {
+ uint32_t c = p->u.str16[i];
+ if (is_surrogate(c)) {
+ if (is_hi_surrogate(c) && (i + 1) < p->len
+ && is_lo_surrogate(p->u.str16[i + 1])) {
+ i++;
+ } else {
+ p->u.str16[i] = 0xFFFD;
+ }
+ }
+ }
+ return ret;
+}
+
static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int lastIndexOf)
{
@@ -40679,7 +41993,7 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val,
ret = js_is_regexp(ctx, argv[0]);
if (ret) {
if (ret > 0)
- JS_ThrowTypeError(ctx, "regex not supported");
+ JS_ThrowTypeError(ctx, "regexp not supported");
goto fail;
}
v = JS_ToString(ctx, argv[0]);
@@ -40803,7 +42117,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, S);
return JS_EXCEPTION;
}
- result = JS_InvokeFree(ctx, rx, atom, 1, &S);
+ result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S);
JS_FreeValue(ctx, S);
return result;
}
@@ -41241,7 +42555,7 @@ static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val,
}
}
if (n > JS_STRING_LEN_MAX) {
- JS_ThrowInternalError(ctx, "string too long");
+ JS_ThrowRangeError(ctx, "invalid string length");
goto fail2;
}
if (string_buffer_init(ctx, b, n))
@@ -41303,8 +42617,9 @@ static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val,
len = p->len;
if (len == 0 || n == 1)
return str;
+ // XXX: potential arithmetic overflow
if (val * len > JS_STRING_LEN_MAX) {
- JS_ThrowInternalError(ctx, "string too long");
+ JS_ThrowRangeError(ctx, "invalid string length");
goto fail;
}
if (string_buffer_init2(ctx, b, n * len, p->is_wide_char))
@@ -41367,10 +42682,10 @@ static int string_prevc(JSString *p, int *pidx)
idx--;
if (p->is_wide_char) {
c = p->u.str16[idx];
- if (c >= 0xdc00 && c < 0xe000 && idx > 0) {
+ if (is_lo_surrogate(c) && idx > 0) {
c1 = p->u.str16[idx - 1];
- if (c1 >= 0xd800 && c1 <= 0xdc00) {
- c = (((c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000;
+ if (is_hi_surrogate(c1)) {
+ c = from_surrogate(c1, c);
idx--;
}
}
@@ -41409,26 +42724,6 @@ static BOOL test_final_sigma(JSString *p, int sigma_pos)
return !lre_is_cased(c1);
}
-static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue a, b;
- int cmp;
-
- a = JS_ToStringCheckObject(ctx, this_val);
- if (JS_IsException(a))
- return JS_EXCEPTION;
- b = JS_ToString(ctx, argv[0]);
- if (JS_IsException(b)) {
- JS_FreeValue(ctx, a);
- return JS_EXCEPTION;
- }
- cmp = js_string_compare(ctx, JS_VALUE_GET_STRING(a), JS_VALUE_GET_STRING(b));
- JS_FreeValue(ctx, a);
- JS_FreeValue(ctx, b);
- return JS_NewInt32(ctx, cmp);
-}
-
static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int to_lower)
{
@@ -41514,23 +42809,38 @@ static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len)
return JS_EXCEPTION;
}
+static int js_string_normalize1(JSContext *ctx, uint32_t **pout_buf,
+ JSValueConst val,
+ UnicodeNormalizationEnum n_type)
+{
+ int buf_len, out_len;
+ uint32_t *buf, *out_buf;
+
+ buf_len = JS_ToUTF32String(ctx, &buf, val);
+ if (buf_len < 0)
+ return -1;
+ out_len = unicode_normalize(&out_buf, buf, buf_len, n_type,
+ ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
+ js_free(ctx, buf);
+ if (out_len < 0)
+ return -1;
+ *pout_buf = out_buf;
+ return out_len;
+}
+
static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
const char *form, *p;
size_t form_len;
- int is_compat, buf_len, out_len;
+ int is_compat, out_len;
UnicodeNormalizationEnum n_type;
JSValue val;
- uint32_t *buf, *out_buf;
+ uint32_t *out_buf;
val = JS_ToStringCheckObject(ctx, this_val);
if (JS_IsException(val))
return val;
- buf_len = JS_ToUTF32String(ctx, &buf, val);
- JS_FreeValue(ctx, val);
- if (buf_len < 0)
- return JS_EXCEPTION;
if (argc == 0 || JS_IsUndefined(argv[0])) {
n_type = UNICODE_NFC;
@@ -41556,22 +42866,96 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,
JS_FreeCString(ctx, form);
JS_ThrowRangeError(ctx, "bad normalization form");
fail1:
- js_free(ctx, buf);
+ JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
JS_FreeCString(ctx, form);
}
- out_len = unicode_normalize(&out_buf, buf, buf_len, n_type,
- ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
- js_free(ctx, buf);
+ out_len = js_string_normalize1(ctx, &out_buf, val, n_type);
+ JS_FreeValue(ctx, val);
if (out_len < 0)
return JS_EXCEPTION;
val = JS_NewUTF32String(ctx, out_buf, out_len);
js_free(ctx, out_buf);
return val;
}
-#endif /* CONFIG_ALL_UNICODE */
+
+/* return < 0, 0 or > 0 */
+static int js_UTF32_compare(const uint32_t *buf1, int buf1_len,
+ const uint32_t *buf2, int buf2_len)
+{
+ int i, len, c, res;
+ len = min_int(buf1_len, buf2_len);
+ for(i = 0; i < len; i++) {
+ /* Note: range is limited so a subtraction is valid */
+ c = buf1[i] - buf2[i];
+ if (c != 0)
+ return c;
+ }
+ if (buf1_len == buf2_len)
+ res = 0;
+ else if (buf1_len < buf2_len)
+ res = -1;
+ else
+ res = 1;
+ return res;
+}
+
+static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue a, b;
+ int cmp, a_len, b_len;
+ uint32_t *a_buf, *b_buf;
+
+ a = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(a))
+ return JS_EXCEPTION;
+ b = JS_ToString(ctx, argv[0]);
+ if (JS_IsException(b)) {
+ JS_FreeValue(ctx, a);
+ return JS_EXCEPTION;
+ }
+ a_len = js_string_normalize1(ctx, &a_buf, a, UNICODE_NFC);
+ JS_FreeValue(ctx, a);
+ if (a_len < 0) {
+ JS_FreeValue(ctx, b);
+ return JS_EXCEPTION;
+ }
+
+ b_len = js_string_normalize1(ctx, &b_buf, b, UNICODE_NFC);
+ JS_FreeValue(ctx, b);
+ if (b_len < 0) {
+ js_free(ctx, a_buf);
+ return JS_EXCEPTION;
+ }
+ cmp = js_UTF32_compare(a_buf, a_len, b_buf, b_len);
+ js_free(ctx, a_buf);
+ js_free(ctx, b_buf);
+ return JS_NewInt32(ctx, cmp);
+}
+#else /* CONFIG_ALL_UNICODE */
+static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue a, b;
+ int cmp;
+
+ a = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(a))
+ return JS_EXCEPTION;
+ b = JS_ToString(ctx, argv[0]);
+ if (JS_IsException(b)) {
+ JS_FreeValue(ctx, a);
+ return JS_EXCEPTION;
+ }
+ cmp = js_string_compare(ctx, JS_VALUE_GET_STRING(a), JS_VALUE_GET_STRING(b));
+ JS_FreeValue(ctx, a);
+ JS_FreeValue(ctx, b);
+ return JS_NewInt32(ctx, cmp);
+}
+#endif /* !CONFIG_ALL_UNICODE */
/* also used for String.prototype.valueOf */
static JSValue js_string_toString(JSContext *ctx, JSValueConst this_val,
@@ -41743,10 +43127,13 @@ static const JSCFunctionListEntry js_string_funcs[] = {
static const JSCFunctionListEntry js_string_proto_funcs[] = {
JS_PROP_INT32_DEF("length", 0, JS_PROP_CONFIGURABLE ),
+ JS_CFUNC_MAGIC_DEF("at", 1, js_string_charAt, 1 ),
JS_CFUNC_DEF("charCodeAt", 1, js_string_charCodeAt ),
- JS_CFUNC_DEF("charAt", 1, js_string_charAt ),
+ JS_CFUNC_MAGIC_DEF("charAt", 1, js_string_charAt, 0 ),
JS_CFUNC_DEF("concat", 1, js_string_concat ),
JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),
+ JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ),
+ JS_CFUNC_DEF("toWellFormed", 0, js_string_toWellFormed ),
JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ),
JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ),
JS_CFUNC_MAGIC_DEF("includes", 1, js_string_includes, 0 ),
@@ -41852,7 +43239,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,
uint32_t tag;
if (unlikely(argc == 0)) {
- return JS_NewFloat64Impl(ctx, is_max ? INFINITY : -INFINITY);
+ return __JS_NewFloat64(ctx, is_max ? INFINITY : -INFINITY);
}
tag = JS_VALUE_GET_TAG(argv[0]);
@@ -41966,14 +43353,16 @@ static double js_math_fround(double a)
static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
- int a, b;
+ uint32_t a, b, c;
+ int32_t d;
- if (JS_ToInt32(ctx, &a, argv[0]))
+ if (JS_ToUint32(ctx, &a, argv[0]))
return JS_EXCEPTION;
- if (JS_ToInt32(ctx, &b, argv[1]))
+ if (JS_ToUint32(ctx, &b, argv[1]))
return JS_EXCEPTION;
- /* purposely ignoring overflow */
- return JS_NewInt32(ctx, a * b);
+ c = a * b;
+ memcpy(&d, &c, sizeof(d));
+ return JS_NewInt32(ctx, d);
}
static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val,
@@ -42025,7 +43414,7 @@ static JSValue js_math_random(JSContext *ctx, JSValueConst this_val,
v = xorshift64star(&ctx->random_state);
/* 1.0 <= u.d < 2 */
u.u64 = ((uint64_t)0x3ff << 52) | (v >> 12);
- return JS_NewFloat64Impl(ctx, u.d - 1.0);
+ return __JS_NewFloat64(ctx, u.d - 1.0);
}
// MSVC inexplicably refuses to initialize the array below with
@@ -42089,47 +43478,12 @@ static const JSCFunctionListEntry js_math_obj[] = {
/* Date */
-#if 0
-/* OS dependent: return the UTC time in ms since 1970. */
-static JSValue js___date_now(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- int64_t d;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- d = (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
- return JS_NewInt64(ctx, d);
-}
-#endif
-
-/* OS dependent: return the UTC time in microseconds since 1970. */
-// FIXME: Unused, remove?
-static JSValue js___date_clock(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- int64_t d;
-#ifdef _MSC_VER
- SYSTEMTIME st;
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, (FILETIME *) &d);
- d /= 10;
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- d = (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
-#endif
- return JS_NewInt64(ctx, d);
-}
-
/* OS dependent. d = argv[0] is in ms from 1970. Return the difference
between UTC time and local time 'd' in minutes */
-static int getTimezoneOffset(int64_t time) {
-#if defined(_WIN32)
- /* XXX: TODO */
- return 0;
-#else
+static int getTimezoneOffset(int64_t time)
+{
time_t ti;
- struct tm tm;
+ int res;
time /= 1000; /* convert to seconds */
if (sizeof(time_t) == 4) {
@@ -42153,9 +43507,27 @@ static int getTimezoneOffset(int64_t time) {
}
}
ti = time;
- localtime_r(&ti, &tm);
- return -tm.tm_gmtoff / 60;
+#if defined(_WIN32)
+ {
+ struct tm *tm;
+ time_t gm_ti, loc_ti;
+
+ tm = gmtime(&ti);
+ gm_ti = mktime(tm);
+
+ tm = localtime(&ti);
+ loc_ti = mktime(tm);
+
+ res = (gm_ti - loc_ti) / 60;
+ }
+#else
+ {
+ struct tm tm;
+ localtime_r(&ti, &tm);
+ res = -tm.tm_gmtoff / 60;
+ }
#endif
+ return res;
}
#if 0
@@ -42167,7 +43539,7 @@ static JSValue js___date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val
if (JS_ToFloat64(ctx, &dd, argv[0]))
return JS_EXCEPTION;
if (isnan(dd))
- return __JS_NewFloat64(ctx, dd);
+ return JS_NewFloat64(ctx, dd);
else
return JS_NewInt32(ctx, getTimezoneOffset((int64_t)dd));
}
@@ -42232,6 +43604,9 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
/* XXX: re_flags = LRE_FLAG_OCTAL unless strict mode? */
for (i = 0; i < len; i++) {
switch(str[i]) {
+ case 'd':
+ mask = LRE_FLAG_INDICES;
+ break;
case 'g':
mask = LRE_FLAG_GLOBAL;
break;
@@ -42245,7 +43620,7 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
mask = LRE_FLAG_DOTALL;
break;
case 'u':
- mask = LRE_FLAG_UTF16;
+ mask = LRE_FLAG_UNICODE;
break;
case 'y':
mask = LRE_FLAG_STICKY;
@@ -42263,7 +43638,7 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
JS_FreeCString(ctx, str);
}
- str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UTF16));
+ str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UNICODE));
if (!str)
return JS_EXCEPTION;
re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg,
@@ -42564,7 +43939,7 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas
}
flags = lre_get_flags(re->bytecode->u.str8);
- return JS_NewBool(ctx, (flags & mask) != 0);
+ return JS_NewBool(ctx, flags & mask);
}
static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)
@@ -42575,6 +43950,11 @@ static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)
if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
return JS_ThrowTypeErrorNotAnObject(ctx);
+ res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "hasIndices"));
+ if (res < 0)
+ goto exception;
+ if (res)
+ *p++ = 'd';
res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_global));
if (res < 0)
goto exception;
@@ -42654,25 +44034,32 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
{
JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);
JSString *str;
- JSValue str_val, obj, val, groups = JS_UNDEFINED;
+ JSValue t, ret, str_val, obj, val, groups;
+ JSValue indices, indices_groups;
uint8_t *re_bytecode;
- int ret;
uint8_t **capture, *str_buf;
- int capture_count, shift, i, re_flags;
+ int rc, capture_count, shift, i, re_flags;
int64_t last_index;
const char *group_name_ptr;
if (!re)
return JS_EXCEPTION;
+
str_val = JS_ToString(ctx, argv[0]);
if (JS_IsException(str_val))
- return str_val;
- val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex);
- if (JS_IsException(val) ||
- JS_ToLengthFree(ctx, &last_index, val)) {
- JS_FreeValue(ctx, str_val);
return JS_EXCEPTION;
- }
+
+ ret = JS_EXCEPTION;
+ obj = JS_NULL;
+ groups = JS_UNDEFINED;
+ indices = JS_UNDEFINED;
+ indices_groups = JS_UNDEFINED;
+ capture = NULL;
+
+ val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex);
+ if (JS_IsException(val) || JS_ToLengthFree(ctx, &last_index, val))
+ goto fail;
+
re_bytecode = re->bytecode->u.str8;
re_flags = lre_get_flags(re_bytecode);
if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) {
@@ -42680,27 +44067,23 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
}
str = JS_VALUE_GET_STRING(str_val);
capture_count = lre_get_capture_count(re_bytecode);
- capture = NULL;
if (capture_count > 0) {
capture = js_malloc(ctx, sizeof(capture[0]) * capture_count * 2);
- if (!capture) {
- JS_FreeValue(ctx, str_val);
- return JS_EXCEPTION;
- }
+ if (!capture)
+ goto fail;
}
shift = str->is_wide_char;
str_buf = str->u.str8;
if (last_index > str->len) {
- ret = 2;
+ rc = 2;
} else {
- ret = lre_exec(capture, re_bytecode,
- str_buf, last_index, str->len,
- shift, ctx);
+ rc = lre_exec(capture, re_bytecode,
+ str_buf, last_index, str->len,
+ shift, ctx);
}
- obj = JS_NULL;
- if (ret != 1) {
- if (ret >= 0) {
- if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {
+ if (rc != 1) {
+ if (rc >= 0) {
+ if (rc == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {
if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,
JS_NewInt32(ctx, 0)) < 0)
goto fail;
@@ -42709,7 +44092,6 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
JS_ThrowInternalError(ctx, "out of memory in regexp execution");
goto fail;
}
- JS_FreeValue(ctx, str_val);
} else {
int prop_flags;
if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) {
@@ -42727,52 +44109,124 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(groups))
goto fail;
}
+ if (re_flags & LRE_FLAG_INDICES) {
+ indices = JS_NewArray(ctx);
+ if (JS_IsException(indices))
+ goto fail;
+ if (group_name_ptr) {
+ indices_groups = JS_NewObjectProto(ctx, JS_NULL);
+ if (JS_IsException(indices_groups))
+ goto fail;
+ }
+ }
for(i = 0; i < capture_count; i++) {
- int start, end;
+ const char *name = NULL;
+ uint8_t **match = &capture[2 * i];
+ int start = -1;
+ int end = -1;
JSValue val;
- if (capture[2 * i] == NULL ||
- capture[2 * i + 1] == NULL) {
+
+ if (group_name_ptr && i > 0) {
+ if (*group_name_ptr) name = group_name_ptr;
+ group_name_ptr += strlen(group_name_ptr) + 1;
+ }
+
+ if (match[0] && match[1]) {
+ start = (match[0] - str_buf) >> shift;
+ end = (match[1] - str_buf) >> shift;
+ }
+
+ if (!JS_IsUndefined(indices)) {
val = JS_UNDEFINED;
- } else {
- start = (capture[2 * i] - str_buf) >> shift;
- end = (capture[2 * i + 1] - str_buf) >> shift;
+ if (start != -1) {
+ val = JS_NewArray(ctx);
+ if (JS_IsException(val))
+ goto fail;
+ if (JS_DefinePropertyValueUint32(ctx, val, 0,
+ JS_NewInt32(ctx, start),
+ prop_flags) < 0) {
+ JS_FreeValue(ctx, val);
+ goto fail;
+ }
+ if (JS_DefinePropertyValueUint32(ctx, val, 1,
+ JS_NewInt32(ctx, end),
+ prop_flags) < 0) {
+ JS_FreeValue(ctx, val);
+ goto fail;
+ }
+ }
+ if (name && !JS_IsUndefined(indices_groups)) {
+ val = JS_DupValue(ctx, val);
+ if (JS_DefinePropertyValueStr(ctx, indices_groups,
+ name, val, prop_flags) < 0) {
+ JS_FreeValue(ctx, val);
+ goto fail;
+ }
+ }
+ if (JS_DefinePropertyValueUint32(ctx, indices, i, val,
+ prop_flags) < 0) {
+ goto fail;
+ }
+ }
+
+ val = JS_UNDEFINED;
+ if (start != -1) {
val = js_sub_string(ctx, str, start, end);
if (JS_IsException(val))
goto fail;
}
- if (group_name_ptr && i > 0) {
- if (*group_name_ptr) {
- if (JS_DefinePropertyValueStr(ctx, groups, group_name_ptr,
- JS_DupValue(ctx, val),
- prop_flags) < 0) {
- JS_FreeValue(ctx, val);
- goto fail;
- }
+
+ if (name) {
+ if (JS_DefinePropertyValueStr(ctx, groups, name,
+ JS_DupValue(ctx, val),
+ prop_flags) < 0) {
+ JS_FreeValue(ctx, val);
+ goto fail;
}
- group_name_ptr += strlen(group_name_ptr) + 1;
}
+
if (JS_DefinePropertyValueUint32(ctx, obj, i, val, prop_flags) < 0)
goto fail;
}
+
+ t = groups, groups = JS_UNDEFINED;
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups,
- groups, prop_flags) < 0)
+ t, prop_flags) < 0) {
goto fail;
- if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index,
- JS_NewInt32(ctx, (capture[0] - str_buf) >> shift), prop_flags) < 0)
+ }
+
+ t = JS_NewInt32(ctx, (capture[0] - str_buf) >> shift);
+ if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index, t, prop_flags) < 0)
goto fail;
- if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, str_val, prop_flags) < 0)
- goto fail1;
+
+ t = str_val, str_val = JS_UNDEFINED;
+ if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, t, prop_flags) < 0)
+ goto fail;
+
+ if (!JS_IsUndefined(indices)) {
+ t = indices_groups, indices_groups = JS_UNDEFINED;
+ if (JS_DefinePropertyValue(ctx, indices, JS_ATOM_groups,
+ t, prop_flags) < 0) {
+ goto fail;
+ }
+ t = indices, indices = JS_UNDEFINED;
+ if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_indices,
+ t, prop_flags) < 0) {
+ goto fail;
+ }
+ }
}
- js_free(ctx, capture);
- return obj;
+ ret = obj;
+ obj = JS_UNDEFINED;
fail:
- JS_FreeValue(ctx, groups);
+ JS_FreeValue(ctx, indices_groups);
+ JS_FreeValue(ctx, indices);
JS_FreeValue(ctx, str_val);
-fail1:
+ JS_FreeValue(ctx, groups);
JS_FreeValue(ctx, obj);
js_free(ctx, capture);
- return JS_EXCEPTION;
+ return ret;
}
/* delete portions of a string that match a given regex */
@@ -42851,7 +44305,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueCon
break;
}
if (end == start) {
- if (!(re_flags & LRE_FLAG_UTF16) || (unsigned)end >= str->len || !str->is_wide_char) {
+ if (!(re_flags & LRE_FLAG_UNICODE) || (unsigned)end >= str->len || !str->is_wide_char) {
end++;
} else {
string_getc(str, &end);
@@ -42924,7 +44378,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
{
// [Symbol.match](str)
JSValueConst rx = this_val;
- JSValue A, S, result, matchStr;
+ JSValue A, S, flags, result, matchStr;
int global, n, fullUnicode, isEmpty;
JSString *p;
@@ -42932,16 +44386,23 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
return JS_ThrowTypeErrorNotAnObject(ctx);
A = JS_UNDEFINED;
+ flags = JS_UNDEFINED;
result = JS_UNDEFINED;
matchStr = JS_UNDEFINED;
S = JS_ToString(ctx, argv[0]);
if (JS_IsException(S))
goto exception;
- global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global));
- if (global < 0)
+ flags = JS_GetProperty(ctx, rx, JS_ATOM_flags);
+ if (JS_IsException(flags))
+ goto exception;
+ flags = JS_ToStringFree(ctx, flags);
+ if (JS_IsException(flags))
goto exception;
+ p = JS_VALUE_GET_STRING(flags);
+ // TODO(bnoordhuis) query 'u' flag the same way?
+ global = (-1 != string_indexof_char(p, 'g', 0));
if (!global) {
A = JS_RegExpExec(ctx, rx, S);
} else {
@@ -42985,12 +44446,14 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
}
}
JS_FreeValue(ctx, result);
+ JS_FreeValue(ctx, flags);
JS_FreeValue(ctx, S);
return A;
exception:
JS_FreeValue(ctx, A);
JS_FreeValue(ctx, result);
+ JS_FreeValue(ctx, flags);
JS_FreeValue(ctx, S);
return JS_EXCEPTION;
}
@@ -43233,8 +44696,8 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
// [Symbol.replace](str, rep)
JSValueConst rx = this_val, rep = argv[1];
JSValueConst args[6];
- JSValue str, rep_val, matched, tab, rep_str, namedCaptures, res;
- JSString *sp, *rp;
+ JSValue flags, str, rep_val, matched, tab, rep_str, namedCaptures, res;
+ JSString *p, *sp, *rp;
StringBuffer b_s, *b = &b_s;
ValueBuffer v_b, *results = &v_b;
int nextSourcePosition, n, j, functionalReplace, is_global, fullUnicode;
@@ -43250,6 +44713,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
rep_val = JS_UNDEFINED;
matched = JS_UNDEFINED;
tab = JS_UNDEFINED;
+ flags = JS_UNDEFINED;
rep_str = JS_UNDEFINED;
namedCaptures = JS_UNDEFINED;
@@ -43266,10 +44730,18 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
goto exception;
rp = JS_VALUE_GET_STRING(rep_val);
}
- fullUnicode = 0;
- is_global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global));
- if (is_global < 0)
+
+ flags = JS_GetProperty(ctx, rx, JS_ATOM_flags);
+ if (JS_IsException(flags))
goto exception;
+ flags = JS_ToStringFree(ctx, flags);
+ if (JS_IsException(flags))
+ goto exception;
+ p = JS_VALUE_GET_STRING(flags);
+
+ // TODO(bnoordhuis) query 'u' flag the same way?
+ fullUnicode = 0;
+ is_global = (-1 != string_indexof_char(p, 'g', 0));
if (is_global) {
fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));
if (fullUnicode < 0)
@@ -43403,6 +44875,7 @@ done1:
value_buffer_free(results);
JS_FreeValue(ctx, rep_val);
JS_FreeValue(ctx, matched);
+ JS_FreeValue(ctx, flags);
JS_FreeValue(ctx, tab);
JS_FreeValue(ctx, rep_str);
JS_FreeValue(ctx, namedCaptures);
@@ -43603,12 +45076,13 @@ static const JSCFunctionListEntry js_regexp_funcs[] = {
static const JSCFunctionListEntry js_regexp_proto_funcs[] = {
JS_CGETSET_DEF("flags", js_regexp_get_flags, NULL ),
JS_CGETSET_DEF("source", js_regexp_get_source, NULL ),
- JS_CGETSET_MAGIC_DEF("global", js_regexp_get_flag, NULL, 1 ),
- JS_CGETSET_MAGIC_DEF("ignoreCase", js_regexp_get_flag, NULL, 2 ),
- JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, 4 ),
- JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, 8 ),
- JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, 16 ),
- JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, 32 ),
+ JS_CGETSET_MAGIC_DEF("global", js_regexp_get_flag, NULL, LRE_FLAG_GLOBAL ),
+ JS_CGETSET_MAGIC_DEF("ignoreCase", js_regexp_get_flag, NULL, LRE_FLAG_IGNORECASE ),
+ JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, LRE_FLAG_MULTILINE ),
+ JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, LRE_FLAG_DOTALL ),
+ JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, LRE_FLAG_UNICODE ),
+ JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, LRE_FLAG_STICKY ),
+ JS_CGETSET_MAGIC_DEF("hasIndices", js_regexp_get_flag, NULL, LRE_FLAG_INDICES ),
JS_CFUNC_DEF("exec", 1, js_regexp_exec ),
JS_CFUNC_DEF("compile", 2, js_regexp_compile ),
JS_CFUNC_DEF("test", 1, js_regexp_test ),
@@ -43766,7 +45240,7 @@ static JSValue json_parse_value(JSParseState *s)
case TOK_IDENT:
if (s->token.u.ident.atom == JS_ATOM_false ||
s->token.u.ident.atom == JS_ATOM_true) {
- val = JS_NewBool(ctx, (s->token.u.ident.atom == JS_ATOM_true));
+ val = JS_NewBool(ctx, s->token.u.ident.atom == JS_ATOM_true);
} else if (s->token.u.ident.atom == JS_ATOM_null) {
val = JS_NULL;
} else {
@@ -43778,7 +45252,7 @@ static JSValue json_parse_value(JSParseState *s)
default:
def_token:
if (s->token.val == TOK_EOF) {
- js_parse_error(s, "unexpected end of input");
+ js_parse_error(s, "Unexpected end of JSON input");
} else {
js_parse_error(s, "unexpected token: '%.*s'",
(int)(s->buf_ptr - s->token.ptr), s->token.ptr);
@@ -43945,24 +45419,27 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
JSValue v;
JSValueConst args[2];
- if (JS_IsObject(val)
+ /* check for object.toJSON method */
+ /* ECMA specifies this is done only for Object and BigInt */
+ /* we do it for BigFloat and BigDecimal as an extension */
+ if (JS_IsObject(val) || JS_IsBigInt(ctx, val)
#ifdef CONFIG_BIGNUM
- || JS_IsBigInt(ctx, val) /* XXX: probably useless */
+ || JS_IsBigFloat(val) || JS_IsBigDecimal(val)
#endif
) {
- JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
- if (JS_IsException(f))
+ JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
+ if (JS_IsException(f))
+ goto exception;
+ if (JS_IsFunction(ctx, f)) {
+ v = JS_CallFree(ctx, f, val, 1, &key);
+ JS_FreeValue(ctx, val);
+ val = v;
+ if (JS_IsException(val))
goto exception;
- if (JS_IsFunction(ctx, f)) {
- v = JS_CallFree(ctx, f, val, 1, &key);
- JS_FreeValue(ctx, val);
- val = v;
- if (JS_IsException(val))
- goto exception;
- } else {
- JS_FreeValue(ctx, f);
- }
+ } else {
+ JS_FreeValue(ctx, f);
}
+ }
if (!JS_IsUndefined(jsc->replacer_func)) {
args[0] = key;
@@ -43981,13 +45458,12 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
case JS_TAG_STRING:
case JS_TAG_INT:
case JS_TAG_FLOAT64:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
case JS_TAG_BOOL:
case JS_TAG_NULL:
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
+ case JS_TAG_BIG_FLOAT:
+ case JS_TAG_BIG_DECIMAL:
#endif
case JS_TAG_EXCEPTION:
return val;
@@ -44018,37 +45494,31 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
tab = JS_UNDEFINED;
prop = JS_UNDEFINED;
- switch (JS_VALUE_GET_NORM_TAG(val)) {
- case JS_TAG_OBJECT:
+ if (JS_IsObject(val)) {
p = JS_VALUE_GET_OBJ(val);
cl = p->class_id;
if (cl == JS_CLASS_STRING) {
val = JS_ToStringFree(ctx, val);
if (JS_IsException(val))
goto exception;
- val = JS_ToQuotedStringFree(ctx, val);
- if (JS_IsException(val))
- goto exception;
- return string_buffer_concat_value_free(jsc->b, val);
+ goto concat_primitive;
} else if (cl == JS_CLASS_NUMBER) {
val = JS_ToNumberFree(ctx, val);
if (JS_IsException(val))
goto exception;
- return string_buffer_concat_value_free(jsc->b, val);
- } else if (cl == JS_CLASS_BOOLEAN) {
- ret = string_buffer_concat_value(jsc->b, p->u.object_data);
- JS_FreeValue(ctx, val);
- return ret;
- }
+ goto concat_primitive;
+ } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT
#ifdef CONFIG_BIGNUM
- else if (cl == JS_CLASS_BIG_FLOAT) {
- return string_buffer_concat_value_free(jsc->b, val);
- } else if (cl == JS_CLASS_BIG_INT) {
- JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");
- goto exception;
- }
+ || cl == JS_CLASS_BIG_FLOAT
+ || cl == JS_CLASS_BIG_DECIMAL
#endif
- v = js_array_includes(ctx, jsc->stack, 1, &val);
+ )
+ {
+ /* This will thow the same error as for the primitive object */
+ set_value(ctx, &val, JS_DupValue(ctx, p->u.object_data));
+ goto concat_primitive;
+ }
+ v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);
if (JS_IsException(v))
goto exception;
if (JS_ToBoolFree(ctx, v)) {
@@ -44069,7 +45539,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
sep = JS_DupValue(ctx, jsc->empty);
sep1 = JS_DupValue(ctx, jsc->empty);
}
- v = js_array_push(ctx, jsc->stack, 1, &val, 0);
+ v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0);
if (check_exception_free(ctx, v))
goto exception;
ret = JS_IsArray(ctx, val);
@@ -44109,7 +45579,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
if (!JS_IsUndefined(jsc->property_list))
tab = JS_DupValue(ctx, jsc->property_list);
else
- tab = js_object_keys(ctx, JS_UNDEFINED, 1, &val, JS_ITERATOR_KIND_KEY);
+ tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);
if (JS_IsException(tab))
goto exception;
if (js_get_length64(ctx, &len, tab))
@@ -44144,7 +45614,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
has_content = TRUE;
}
}
- if (has_content && JS_VALUE_GET_STRING(jsc->gap)->len != 0) {
+ if (has_content && !JS_IsEmptyString(jsc->gap)) {
string_buffer_putc8(jsc->b, '\n');
string_buffer_concat_value(jsc->b, indent);
}
@@ -44159,6 +45629,9 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
JS_FreeValue(ctx, indent1);
JS_FreeValue(ctx, prop);
return 0;
+ }
+ concat_primitive:
+ switch (JS_VALUE_GET_NORM_TAG(val)) {
case JS_TAG_STRING:
val = JS_ToQuotedStringFree(ctx, val);
if (JS_IsException(val))
@@ -44170,18 +45643,18 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
}
goto concat_value;
case JS_TAG_INT:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
case JS_TAG_BOOL:
case JS_TAG_NULL:
concat_value:
return string_buffer_concat_value_free(jsc->b, val);
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
- JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");
- goto exception;
+#ifdef CONFIG_BIGNUM
+ case JS_TAG_BIG_FLOAT:
+ case JS_TAG_BIG_DECIMAL:
#endif
+ /* reject big numbers: use toJSON method to override */
+ JS_ThrowTypeError(ctx, "Do not know how to serialize a BigInt");
+ goto exception;
default:
JS_FreeValue(ctx, val);
return 0;
@@ -44257,7 +45730,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
continue;
}
present = js_array_includes(ctx, jsc->property_list,
- 1, &v);
+ 1, (JSValueConst *)&v);
if (JS_IsException(present)) {
JS_FreeValue(ctx, v);
goto exception;
@@ -44381,7 +45854,7 @@ static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
tab = build_arg_list(ctx, &len, array_arg);
if (!tab)
return JS_EXCEPTION;
- ret = JS_CallConstructor2(ctx, func, new_target, len, tab);
+ ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab);
free_arg_list(ctx, tab, len);
return ret;
}
@@ -44471,8 +45944,8 @@ static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val,
atom = JS_ValueToAtom(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL))
return JS_EXCEPTION;
- ret = JS_SetPropertyGeneric(ctx, obj, atom,
- JS_DupValue(ctx, val), receiver, 0);
+ ret = JS_SetPropertyInternal(ctx, obj, atom,
+ JS_DupValue(ctx, val), receiver, 0);
JS_FreeAtom(ctx, atom);
if (ret < 0)
return JS_EXCEPTION;
@@ -44586,7 +46059,7 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)
return JS_EXCEPTION;
if (JS_IsUndefined(method))
return JS_GetPrototype(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
if (JS_IsException(ret))
return ret;
if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL &&
@@ -44673,7 +46146,7 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)
return -1;
if (JS_IsUndefined(method))
return JS_IsExtensible(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
if (JS_IsException(ret))
return -1;
res = JS_ToBoolFree(ctx, ret);
@@ -44699,7 +46172,7 @@ static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)
return -1;
if (JS_IsUndefined(method))
return JS_PreventExtensions(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
if (JS_IsException(ret))
return -1;
res = JS_ToBoolFree(ctx, ret);
@@ -44819,9 +46292,9 @@ static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom,
if (!s)
return -1;
if (JS_IsUndefined(method)) {
- return JS_SetPropertyGeneric(ctx, s->target, atom,
- JS_DupValue(ctx, value), receiver,
- flags);
+ return JS_SetPropertyInternal(ctx, s->target, atom,
+ JS_DupValue(ctx, value), receiver,
+ flags);
}
atom_val = JS_AtomToValue(ctx, atom);
if (JS_IsException(atom_val)) {
@@ -44887,17 +46360,17 @@ static JSValue js_create_desc(JSContext *ctx, JSValueConst val,
}
if (flags & JS_PROP_HAS_WRITABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,
- JS_NewBool(ctx, (flags & JS_PROP_WRITABLE) != 0),
+ JS_NewBool(ctx, flags & JS_PROP_WRITABLE),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_ENUMERABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,
- JS_NewBool(ctx, (flags & JS_PROP_ENUMERABLE) != 0),
+ JS_NewBool(ctx, flags & JS_PROP_ENUMERABLE),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_CONFIGURABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,
- JS_NewBool(ctx, (flags & JS_PROP_CONFIGURABLE) != 0),
+ JS_NewBool(ctx, flags & JS_PROP_CONFIGURABLE),
JS_PROP_C_W_E);
}
return ret;
@@ -45183,7 +46656,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
JS_VALUE_GET_OBJ(s->target),
JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK);
}
- prop_array = JS_CallFree(ctx, method, s->handler, 1, &s->target);
+ prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
if (JS_IsException(prop_array))
return -1;
tab = NULL;
@@ -45349,20 +46822,35 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,
return ret;
}
-static int js_proxy_isArray(JSContext *ctx, JSValueConst obj)
-{
- JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);
- if (!s)
- return FALSE;
- if (js_check_stack_overflow(ctx->rt, 0)) {
- JS_ThrowStackOverflow(ctx);
- return -1;
- }
- if (s->is_revoked) {
- JS_ThrowTypeErrorRevokedProxy(ctx);
- return -1;
+/* `js_resolve_proxy`: resolve the proxy chain
+ `*pval` is updated with to ultimate proxy target
+ `throw_exception` controls whether exceptions are thown or not
+ - return -1 in case of error
+ - otherwise return 0
+ */
+static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, BOOL throw_exception) {
+ int depth = 0;
+ JSObject *p;
+ JSProxyData *s;
+
+ while (JS_VALUE_GET_TAG(*pval) == JS_TAG_OBJECT) {
+ p = JS_VALUE_GET_OBJ(*pval);
+ if (p->class_id != JS_CLASS_PROXY)
+ break;
+ if (depth++ > 1000) {
+ if (throw_exception)
+ JS_ThrowStackOverflow(ctx);
+ return -1;
+ }
+ s = p->u.opaque;
+ if (s->is_revoked) {
+ if (throw_exception)
+ JS_ThrowTypeErrorRevokedProxy(ctx);
+ return -1;
+ }
+ *pval = s->target;
}
- return JS_IsArray(ctx, s->target);
+ return 0;
}
static const JSClassExoticMethods js_proxy_exotic_methods = {
@@ -45523,7 +47011,7 @@ static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(val))
return val;
/* XXX: use JS_ToStringInternal() with a flags */
- ret = js_string_constructor(ctx, JS_UNDEFINED, 1, &val);
+ ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val);
JS_FreeValue(ctx, val);
return ret;
}
@@ -45673,7 +47161,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
break;
}
if (is_set) {
- ret = JS_Call(ctx, adder, obj, 1, &item);
+ ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item);
if (JS_IsException(ret)) {
JS_FreeValue(ctx, item);
goto fail;
@@ -45757,7 +47245,7 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
h = (uintptr_t)JS_VALUE_GET_PTR(key) * 3163;
break;
case JS_TAG_INT:
- d = JS_VALUE_GET_INT(key) * 3163;
+ d = JS_VALUE_GET_INT(key);
goto hash_float64;
case JS_TAG_FLOAT64:
d = JS_VALUE_GET_FLOAT64(key);
@@ -45767,7 +47255,7 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
hash_float64:
u.d = d;
h = (u.u32[0] ^ u.u32[1]) * 3163;
- break;
+ return h ^= JS_TAG_FLOAT64;
default:
h = 0; /* XXX: bignum support */
break;
@@ -45991,7 +47479,7 @@ static JSValue js_map_has(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
key = map_normalize_key(ctx, argv[0]);
mr = map_find_record(ctx, s, key);
- return JS_NewBool(ctx, (mr != NULL));
+ return JS_NewBool(ctx, mr != NULL);
}
static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val,
@@ -46083,6 +47571,123 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,
return JS_UNDEFINED;
}
+static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int is_map)
+{
+ JSValueConst cb, args[2];
+ JSValue res, iter, next, groups, key, v, prop;
+ JSAtom key_atom = JS_ATOM_NULL;
+ int64_t idx;
+ BOOL done;
+
+ // "is function?" check must be observed before argv[0] is accessed
+ cb = argv[1];
+ if (check_function(ctx, cb))
+ return JS_EXCEPTION;
+
+ iter = JS_GetIterator(ctx, argv[0], /*is_async*/FALSE);
+ if (JS_IsException(iter))
+ return JS_EXCEPTION;
+
+ key = JS_UNDEFINED;
+ key_atom = JS_ATOM_NULL;
+ v = JS_UNDEFINED;
+ prop = JS_UNDEFINED;
+ groups = JS_UNDEFINED;
+
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+
+ if (is_map) {
+ groups = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 0);
+ } else {
+ groups = JS_NewObjectProto(ctx, JS_NULL);
+ }
+ if (JS_IsException(groups))
+ goto exception;
+
+ for (idx = 0; ; idx++) {
+ if (idx >= MAX_SAFE_INTEGER) {
+ JS_ThrowTypeError(ctx, "too many elements");
+ goto iterator_close_exception;
+ }
+ v = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(v))
+ goto exception;
+ if (done)
+ break; // v is JS_UNDEFINED
+
+ args[0] = v;
+ args[1] = JS_NewInt64(ctx, idx);
+ key = JS_Call(ctx, cb, ctx->global_obj, 2, args);
+ if (JS_IsException(key))
+ goto iterator_close_exception;
+
+ if (is_map) {
+ prop = js_map_get(ctx, groups, 1, (JSValueConst *)&key, 0);
+ } else {
+ key_atom = JS_ValueToAtom(ctx, key);
+ JS_FreeValue(ctx, key);
+ key = JS_UNDEFINED;
+ if (key_atom == JS_ATOM_NULL)
+ goto iterator_close_exception;
+ prop = JS_GetProperty(ctx, groups, key_atom);
+ }
+ if (JS_IsException(prop))
+ goto exception;
+
+ if (JS_IsUndefined(prop)) {
+ prop = JS_NewArray(ctx);
+ if (JS_IsException(prop))
+ goto exception;
+ if (is_map) {
+ args[0] = key;
+ args[1] = prop;
+ res = js_map_set(ctx, groups, 2, args, 0);
+ if (JS_IsException(res))
+ goto exception;
+ JS_FreeValue(ctx, res);
+ } else {
+ prop = JS_DupValue(ctx, prop);
+ if (JS_DefinePropertyValue(ctx, groups, key_atom, prop,
+ JS_PROP_C_W_E) < 0) {
+ goto exception;
+ }
+ }
+ }
+ res = js_array_push(ctx, prop, 1, (JSValueConst *)&v, /*unshift*/0);
+ if (JS_IsException(res))
+ goto exception;
+ // res is an int64
+
+ JS_FreeValue(ctx, prop);
+ JS_FreeValue(ctx, key);
+ JS_FreeAtom(ctx, key_atom);
+ JS_FreeValue(ctx, v);
+ prop = JS_UNDEFINED;
+ key = JS_UNDEFINED;
+ key_atom = JS_ATOM_NULL;
+ v = JS_UNDEFINED;
+ }
+
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return groups;
+
+ iterator_close_exception:
+ JS_IteratorClose(ctx, iter, TRUE);
+ exception:
+ JS_FreeAtom(ctx, key_atom);
+ JS_FreeValue(ctx, prop);
+ JS_FreeValue(ctx, key);
+ JS_FreeValue(ctx, v);
+ JS_FreeValue(ctx, groups);
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return JS_EXCEPTION;
+}
+
static void js_map_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p;
@@ -46263,6 +47868,7 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val,
}
static const JSCFunctionListEntry js_map_funcs[] = {
+ JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 1 ),
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
};
@@ -46383,12 +47989,6 @@ static const JSCFunctionListEntry js_generator_proto_funcs[] = {
/* Promise */
-typedef enum JSPromiseStateEnum {
- JS_PROMISE_PENDING,
- JS_PROMISE_FULFILLED,
- JS_PROMISE_REJECTED,
-} JSPromiseStateEnum;
-
typedef struct JSPromiseData {
JSPromiseStateEnum promise_state;
/* 0=fulfill, 1=reject, list of JSPromiseReactionData.link */
@@ -46413,6 +48013,22 @@ typedef struct JSPromiseReactionData {
JSValue handler;
} JSPromiseReactionData;
+JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise)
+{
+ JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
+ if (!s)
+ return -1;
+ return s->promise_state;
+}
+
+JSValue JS_PromiseResult(JSContext *ctx, JSValue promise)
+{
+ JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
+ if (!s)
+ return JS_UNDEFINED;
+ return JS_DupValue(ctx, s->promise_result);
+}
+
static int js_create_resolving_functions(JSContext *ctx, JSValue *args,
JSValueConst promise);
@@ -46458,7 +48074,7 @@ static JSValue promise_reaction_job(JSContext *ctx, int argc,
functions */
if (!JS_IsUndefined(func)) {
res2 = JS_Call(ctx, func, JS_UNDEFINED,
- 1, &res);
+ 1, (JSValueConst *)&res);
} else {
res2 = JS_UNDEFINED;
}
@@ -46541,7 +48157,7 @@ static JSValue js_promise_resolve_thenable_job(JSContext *ctx,
res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args);
if (JS_IsException(res)) {
JSValue error = JS_GetException(ctx);
- res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
+ res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
JS_FreeValue(ctx, error);
}
JS_FreeValue(ctx, args[0]);
@@ -46741,7 +48357,7 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,
if (JS_IsException(ret)) {
JSValue ret2, error;
error = JS_GetException(ctx);
- ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
+ ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret2))
goto fail1;
@@ -46798,10 +48414,10 @@ static JSValue js_new_promise_capability(JSContext *ctx,
if (JS_IsUndefined(ctor)) {
result_promise = js_promise_constructor(ctx, ctor, 1,
- &executor);
+ (JSValueConst *)&executor);
} else {
result_promise = JS_CallConstructor(ctx, ctor, 1,
- &executor);
+ (JSValueConst *)&executor);
}
if (JS_IsException(result_promise))
goto fail;
@@ -46858,17 +48474,14 @@ static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,
return result_promise;
}
-#if 0
-static JSValue js_promise___newPromiseCapability(JSContext *ctx,
- JSValueConst this_val,
- int argc, JSValueConst *argv)
+static JSValue js_promise_withResolvers(JSContext *ctx,
+ JSValueConst this_val,
+ int argc, JSValueConst *argv)
{
JSValue result_promise, resolving_funcs[2], obj;
- JSValueConst ctor;
- ctor = argv[0];
- if (!JS_IsObject(ctor))
+ if (!JS_IsObject(this_val))
return JS_ThrowTypeErrorNotAnObject(ctx);
- result_promise = js_new_promise_capability(ctx, resolving_funcs, ctor);
+ result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
if (JS_IsException(result_promise))
return result_promise;
obj = JS_NewObject(ctx);
@@ -46883,9 +48496,8 @@ static JSValue js_promise___newPromiseCapability(JSContext *ctx,
JS_DefinePropertyValue(ctx, obj, JS_ATOM_reject, resolving_funcs[1], JS_PROP_C_W_E);
return obj;
}
-#endif
-static warn_unused int remainingElementsCount_add(JSContext *ctx,
+static __exception int remainingElementsCount_add(JSContext *ctx,
JSValueConst resolve_element_env,
int addend)
{
@@ -46966,10 +48578,10 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
error = js_aggregate_error_constructor(ctx, values);
if (JS_IsException(error))
return JS_EXCEPTION;
- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &error);
+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error);
JS_FreeValue(ctx, error);
} else {
- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &values);
+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);
}
if (JS_IsException(ret))
return ret;
@@ -47005,7 +48617,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
fail_reject:
error = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
- &error);
+ (JSValueConst *)&error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret))
goto fail;
@@ -47036,7 +48648,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
if (done)
break;
next_promise = JS_Call(ctx, promise_resolve,
- this_val, 1, &item);
+ this_val, 1, (JSValueConst *)&item);
JS_FreeValue(ctx, item);
if (JS_IsException(next_promise)) {
fail_reject1:
@@ -47104,7 +48716,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
values = error;
}
ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED,
- 1, &values);
+ 1, (JSValueConst *)&values);
if (check_exception_free(ctx, ret))
goto fail_reject;
}
@@ -47147,7 +48759,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
fail_reject:
error = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
- &error);
+ (JSValueConst *)&error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret))
goto fail;
@@ -47166,7 +48778,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
if (done)
break;
next_promise = JS_Call(ctx, promise_resolve,
- this_val, 1, &item);
+ this_val, 1, (JSValueConst *)&item);
JS_FreeValue(ctx, item);
if (JS_IsException(next_promise)) {
fail_reject1:
@@ -47193,7 +48805,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
goto done;
}
-static warn_unused int perform_promise_then(JSContext *ctx,
+static __exception int perform_promise_then(JSContext *ctx,
JSValueConst promise,
JSValueConst *resolve_reject,
JSValueConst *cap_resolving_funcs)
@@ -47311,7 +48923,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL);
if (JS_IsException(res))
return res;
- promise = js_promise_resolve(ctx, ctor, 1, &res, 0);
+ promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0);
JS_FreeValue(ctx, res);
if (JS_IsException(promise))
return promise;
@@ -47326,7 +48938,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
JS_FreeValue(ctx, promise);
return then_func;
}
- ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, &then_func);
+ ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, (JSValueConst *)&then_func);
JS_FreeValue(ctx, then_func);
return ret;
}
@@ -47373,7 +48985,7 @@ static const JSCFunctionListEntry js_promise_funcs[] = {
JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, PROMISE_MAGIC_allSettled ),
JS_CFUNC_MAGIC_DEF("any", 1, js_promise_all, PROMISE_MAGIC_any ),
JS_CFUNC_DEF("race", 1, js_promise_race ),
- //JS_CFUNC_DEF("__newPromiseCapability", 1, js_promise___newPromiseCapability ),
+ JS_CFUNC_DEF("withResolvers", 0, js_promise_withResolvers ),
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL),
};
@@ -47526,7 +49138,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
is_reject = 1;
done_resolve:
res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED,
- 1, &err);
+ 1, (JSValueConst *)&err);
JS_FreeValue(ctx, err);
JS_FreeValue(ctx, res2);
JS_FreeValue(ctx, resolving_funcs[0]);
@@ -47538,7 +49150,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
int res;
value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor,
- 1, &value, 0);
+ 1, (JSValueConst *)&value, 0);
if (JS_IsException(value_wrapper_promise)) {
JS_FreeValue(ctx, value);
goto reject;
@@ -47786,8 +49398,7 @@ static JSValue js_global_decodeURI(JSContext *ctx, JSValueConst this_val,
}
c = (c << 6) | (c1 & 0x3f);
}
- if (c < c_min || c > 0x10FFFF ||
- (c >= 0xd800 && c < 0xe000)) {
+ if (c < c_min || c > 0x10FFFF || is_surrogate(c)) {
js_throw_URIError(ctx, "malformed UTF-8");
goto fail;
}
@@ -47862,21 +49473,21 @@ static JSValue js_global_encodeURI(JSContext *ctx, JSValueConst this_val,
if (isURIUnescaped(c, isComponent)) {
string_buffer_putc16(b, c);
} else {
- if (c >= 0xdc00 && c <= 0xdfff) {
+ if (is_lo_surrogate(c)) {
js_throw_URIError(ctx, "invalid character");
goto fail;
- } else if (c >= 0xd800 && c <= 0xdbff) {
+ } else if (is_hi_surrogate(c)) {
if (k >= p->len) {
js_throw_URIError(ctx, "expecting surrogate pair");
goto fail;
}
c1 = string_get(p, k);
k++;
- if (c1 < 0xdc00 || c1 > 0xdfff) {
+ if (!is_lo_surrogate(c1)) {
js_throw_URIError(ctx, "expecting surrogate pair");
goto fail;
}
- c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
+ c = from_surrogate(c, c1);
}
if (c < 0x80) {
encodeURI_hex(b, c);
@@ -47984,12 +49595,7 @@ static const JSCFunctionListEntry js_global_funcs[] = {
JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ),
JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),
JS_PROP_UNDEFINED_DEF("undefined", 0 ),
-
- /* for the 'Date' implementation */
- JS_CFUNC_DEF("__date_clock", 0, js___date_clock ),
- //JS_CFUNC_DEF("__date_now", 0, js___date_now ),
- //JS_CFUNC_DEF("__date_getTimezoneOffset", 1, js___date_getTimezoneOffset ),
- //JS_CFUNC_DEF("__date_create", 3, js___date_create ),
+ JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ),
};
/* Date */
@@ -48009,7 +49615,7 @@ static int64_t floor_div(int64_t a, int64_t b) {
static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv);
-static warn_unused int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
+static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
{
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
@@ -48069,8 +49675,8 @@ static int const month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
static char const day_names[] = "SunMonTueWedThuFriSat";
-static warn_unused int get_date_fields(JSContext *ctx, JSValueConst obj,
- double fields[9], int is_local, int force)
+static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
+ double fields[minimum_length(9)], int is_local, int force)
{
double dval;
int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0;
@@ -48083,7 +49689,7 @@ static warn_unused int get_date_fields(JSContext *ctx, JSValueConst obj,
return FALSE; /* NaN */
d = 0; /* initialize all fields to 0 */
} else {
- d = dval;
+ d = dval; /* assuming -8.64e15 <= dval <= -8.64e15 */
if (is_local) {
tz = -getTimezoneOffset(d);
d += tz * 60000;
@@ -48129,33 +49735,63 @@ static double time_clip(double t) {
return NAN;
}
-/* The spec mandates the use of 'double' and it fixes the order
+/* The spec mandates the use of 'double' and it specifies the order
of the operations */
-static double set_date_fields(const 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)
- m += 12;
- y = (int64_t)(fields[0] + floor(m1 / 12));
- days = days_from_year(y);
-
- for(i = 0; i < m; i++) {
- md = month_days[i];
+static double set_date_fields(double fields[minimum_length(7)], int is_local) {
+ double y, m, dt, ym, mn, day, h, s, milli, time, tv;
+ int yi, mi, i;
+ int64_t days;
+ volatile double temp; /* enforce evaluation order */
+
+ /* emulate 21.4.1.15 MakeDay ( year, month, date ) */
+ y = fields[0];
+ m = fields[1];
+ dt = fields[2];
+ ym = y + floor(m / 12);
+ mn = fmod(m, 12);
+ if (mn < 0)
+ mn += 12;
+ if (ym < -271821 || ym > 275760)
+ return NAN;
+
+ yi = ym;
+ mi = mn;
+ days = days_from_year(yi);
+ for(i = 0; i < mi; i++) {
+ days += month_days[i];
if (i == 1)
- md += days_in_year(y) - 365;
- days += md;
+ days += days_in_year(yi) - 365;
+ }
+ day = days + dt - 1;
+
+ /* emulate 21.4.1.14 MakeTime ( hour, min, sec, ms ) */
+ h = fields[3];
+ m = fields[4];
+ s = fields[5];
+ milli = fields[6];
+ /* Use a volatile intermediary variable to ensure order of evaluation
+ * as specified in ECMA. This fixes a test262 error on
+ * test262/test/built-ins/Date/UTC/fp-evaluation-order.js.
+ * Without the volatile qualifier, the compile can generate code
+ * that performs the computation in a different order or with instructions
+ * that produce a different result such as FMA (float multiply and add).
+ */
+ time = h * 3600000;
+ time += (temp = m * 60000);
+ time += (temp = s * 1000);
+ time += milli;
+
+ /* emulate 21.4.1.16 MakeDate ( day, time ) */
+ tv = (temp = day * 86400000) + time; /* prevent generation of FMA */
+ if (!isfinite(tv))
+ return NAN;
+
+ /* adjust for local time and clip */
+ if (is_local) {
+ int64_t ti = tv < INT64_MIN ? INT64_MIN : tv >= 0x1p63 ? INT64_MAX : (int64_t)tv;
+ tv += getTimezoneOffset(ti) * 60000;
}
- days += fields[2] - 1;
- h = fields[3] * 3600000 + fields[4] * 60000 +
- fields[5] * 1000 + fields[6];
- d = days * 86400000 + h;
- if (is_local)
- d += getTimezoneOffset(d) * 60000;
- return time_clip(d);
+ return time_clip(tv);
}
static JSValue get_date_field(JSContext *ctx, JSValueConst this_val,
@@ -48195,20 +49831,19 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,
res = get_date_fields(ctx, this_val, fields, is_local, first_field == 0);
if (res < 0)
return JS_EXCEPTION;
- if (res && argc > 0) {
- n = end_field - first_field;
- if (argc < n)
- n = argc;
- for(i = 0; i < n; i++) {
- if (JS_ToFloat64(ctx, &a, argv[i]))
- return JS_EXCEPTION;
- if (!isfinite(a))
- goto done;
- fields[first_field + i] = trunc(a);
- }
- d = set_date_fields(fields, is_local);
+
+ // Argument coercion is observable and must be done unconditionally.
+ n = min_int(argc, end_field - first_field);
+ for(i = 0; i < n; i++) {
+ if (JS_ToFloat64(ctx, &a, argv[i]))
+ return JS_EXCEPTION;
+ if (!isfinite(a))
+ res = FALSE;
+ fields[first_field + i] = trunc(a);
}
-done:
+ if (res && argc > 0)
+ d = set_date_fields(fields, is_local);
+
return JS_SetThisTimeValue(ctx, this_val, d);
}
@@ -48318,7 +49953,7 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
break;
case 3:
pos += snprintf(buf + pos, sizeof(buf) - pos,
- "%02d:%02d:%02d %cM", (h + 1) % 12 - 1, m, s,
+ "%02d:%02d:%02d %cM", (h + 11) % 12 + 1, m, s,
(h < 12) ? 'A' : 'P');
break;
}
@@ -48369,7 +50004,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
}
v = JS_ToPrimitive(ctx, argv[0], HINT_NONE);
if (JS_IsString(v)) {
- dv = js_Date_parse(ctx, JS_UNDEFINED, 1, &v);
+ dv = js_Date_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&v);
JS_FreeValue(ctx, v);
if (JS_IsException(dv))
return JS_EXCEPTION;
@@ -48442,142 +50077,418 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,
return JS_NewFloat64(ctx, set_date_fields(fields, 0));
}
-static void string_skip_spaces(JSString *sp, int *pp) {
- while (*pp < sp->len && string_get(sp, *pp) == ' ')
+/* Date string parsing */
+
+static BOOL string_skip_char(const uint8_t *sp, int *pp, int c) {
+ if (sp[*pp] == c) {
*pp += 1;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
}
-static void string_skip_non_spaces(JSString *sp, int *pp) {
- while (*pp < sp->len && string_get(sp, *pp) != ' ')
+/* skip spaces, update offset, return next char */
+static int string_skip_spaces(const uint8_t *sp, int *pp) {
+ int c;
+ while ((c = sp[*pp]) == ' ')
*pp += 1;
+ return c;
}
-/* parse a numeric field with an optional sign if accept_sign is TRUE */
-static int string_get_digits(JSString *sp, int *pp, int64_t *pval) {
- int64_t v = 0;
+/* skip dashes dots and commas */
+static int string_skip_separators(const uint8_t *sp, int *pp) {
+ int c;
+ while ((c = sp[*pp]) == '-' || c == '/' || c == '.' || c == ',')
+ *pp += 1;
+ return c;
+}
+
+/* skip a word, stop on spaces, digits and separators, update offset */
+static int string_skip_until(const uint8_t *sp, int *pp, const char *stoplist) {
+ int c;
+ while (!strchr(stoplist, c = sp[*pp]))
+ *pp += 1;
+ return c;
+}
+
+/* parse a numeric field (max_digits = 0 -> no maximum) */
+static BOOL string_get_digits(const uint8_t *sp, int *pp, int *pval,
+ int min_digits, int max_digits)
+{
+ int v = 0;
int c, p = *pp, p_start;
- if (p >= sp->len)
- return -1;
p_start = p;
- while (p < sp->len) {
- c = string_get(sp, p);
- if (!(c >= '0' && c <= '9')) {
- if (p == p_start)
- return -1;
- else
- break;
- }
+ while ((c = sp[p]) >= '0' && c <= '9') {
v = v * 10 + c - '0';
p++;
+ if (p - p_start == max_digits)
+ break;
}
+ if (p - p_start < min_digits)
+ return FALSE;
*pval = v;
*pp = p;
- return 0;
+ return TRUE;
}
-static int string_get_signed_digits(JSString *sp, int *pp, int64_t *pval) {
- int res, sgn, p = *pp;
-
- if (p >= sp->len)
- return -1;
+static BOOL string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) {
+ /* parse optional fractional part as milliseconds and truncate. */
+ /* spec does not indicate which rounding should be used */
+ int mul = 100, ms = 0, c, p_start, p = *pp;
- sgn = string_get(sp, p);
- if (sgn == '-' || sgn == '+')
+ c = sp[p];
+ if (c == '.' || c == ',') {
p++;
+ p_start = p;
+ while ((c = sp[p]) >= '0' && c <= '9') {
+ ms += (c - '0') * mul;
+ mul /= 10;
+ p++;
+ if (p - p_start == 9)
+ break;
+ }
+ if (p > p_start) {
+ /* only consume the separator if digits are present */
+ *pval = ms;
+ *pp = p;
+ }
+ }
+ return TRUE;
+}
- res = string_get_digits(sp, &p, pval);
- if (res == 0 && sgn == '-')
- *pval = -*pval;
- *pp = p;
- return res;
+static uint8_t upper_ascii(uint8_t c) {
+ return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
}
-/* parse a fixed width numeric field */
-static int string_get_fixed_width_digits(JSString *sp, int *pp, int n, int64_t *pval) {
- int64_t v = 0;
- int i, c, p = *pp;
+static BOOL string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, BOOL strict) {
+ int tz = 0, sgn, hh, mm, p = *pp;
- for(i = 0; i < n; i++) {
- if (p >= sp->len)
- return -1;
- c = string_get(sp, p);
- if (!(c >= '0' && c <= '9'))
- return -1;
- v = v * 10 + c - '0';
- p++;
+ sgn = sp[p++];
+ if (sgn == '+' || sgn == '-') {
+ int n = p;
+ if (!string_get_digits(sp, &p, &hh, 1, 9))
+ return FALSE;
+ n = p - n;
+ if (strict && n != 2 && n != 4)
+ return FALSE;
+ while (n > 4) {
+ n -= 2;
+ hh /= 100;
+ }
+ if (n > 2) {
+ mm = hh % 100;
+ hh = hh / 100;
+ } else {
+ mm = 0;
+ if (string_skip_char(sp, &p, ':') /* optional separator */
+ && !string_get_digits(sp, &p, &mm, 2, 2))
+ return FALSE;
+ }
+ if (hh > 23 || mm > 59)
+ return FALSE;
+ tz = hh * 60 + mm;
+ if (sgn != '+')
+ tz = -tz;
+ } else
+ if (sgn != 'Z') {
+ return FALSE;
}
- *pval = v;
*pp = p;
- return 0;
+ *tzp = tz;
+ return TRUE;
}
-static int string_get_milliseconds(JSString *sp, int *pp, int64_t *pval) {
- /* parse milliseconds as a fractional part, round to nearest */
- /* XXX: the spec does not indicate which rounding should be used */
- int mul = 1000, ms = 0, p = *pp, c, p_start;
- if (p >= sp->len)
- return -1;
- p_start = p;
- while (p < sp->len) {
- c = string_get(sp, p);
- if (!(c >= '0' && c <= '9')) {
- if (p == p_start)
- return -1;
- else
- break;
- }
- if (mul == 1 && c >= '5')
- ms += 1;
- ms += (c - '0') * (mul /= 10);
+static BOOL string_match(const uint8_t *sp, int *pp, const char *s) {
+ int p = *pp;
+ while (*s != '\0') {
+ if (upper_ascii(sp[p]) != upper_ascii(*s++))
+ return FALSE;
p++;
}
- *pval = ms;
*pp = p;
- return 0;
+ return TRUE;
}
-
-static int find_abbrev(JSString *sp, int p, const char *list, int count) {
+static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) {
int n, i;
- if (p + 3 <= sp->len) {
- for (n = 0; n < count; n++) {
- for (i = 0; i < 3; i++) {
- if (string_get(sp, p + i) != month_names[n * 3 + i])
- goto next;
- }
- return n;
- next:;
+ for (n = 0; n < count; n++) {
+ for (i = 0;; i++) {
+ if (upper_ascii(sp[p + i]) != upper_ascii(list[n * 3 + i]))
+ break;
+ if (i == 2)
+ return n;
}
}
return -1;
}
-static int string_get_month(JSString *sp, int *pp, int64_t *pval) {
+static BOOL string_get_month(const uint8_t *sp, int *pp, int *pval) {
int n;
- string_skip_spaces(sp, pp);
n = find_abbrev(sp, *pp, month_names, 12);
if (n < 0)
- return -1;
+ return FALSE;
- *pval = n;
+ *pval = n + 1;
*pp += 3;
- return 0;
+ return TRUE;
+}
+
+/* parse toISOString format */
+static BOOL js_date_parse_isostring(const uint8_t *sp, int fields[9], BOOL *is_local) {
+ int sgn, i, p = 0;
+
+ /* initialize fields to the beginning of the Epoch */
+ for (i = 0; i < 9; i++) {
+ fields[i] = (i == 2);
+ }
+ *is_local = FALSE;
+
+ /* year is either yyyy digits or [+-]yyyyyy */
+ sgn = sp[p];
+ if (sgn == '-' || sgn == '+') {
+ p++;
+ if (!string_get_digits(sp, &p, &fields[0], 6, 6))
+ return FALSE;
+ if (sgn == '-') {
+ if (fields[0] == 0)
+ return FALSE; // reject -000000
+ fields[0] = -fields[0];
+ }
+ } else {
+ if (!string_get_digits(sp, &p, &fields[0], 4, 4))
+ return FALSE;
+ }
+ if (string_skip_char(sp, &p, '-')) {
+ if (!string_get_digits(sp, &p, &fields[1], 2, 2)) /* month */
+ return FALSE;
+ if (fields[1] < 1)
+ return FALSE;
+ fields[1] -= 1;
+ if (string_skip_char(sp, &p, '-')) {
+ if (!string_get_digits(sp, &p, &fields[2], 2, 2)) /* day */
+ return FALSE;
+ if (fields[2] < 1)
+ return FALSE;
+ }
+ }
+ if (string_skip_char(sp, &p, 'T')) {
+ *is_local = TRUE;
+ if (!string_get_digits(sp, &p, &fields[3], 2, 2) /* hour */
+ || !string_skip_char(sp, &p, ':')
+ || !string_get_digits(sp, &p, &fields[4], 2, 2)) { /* minute */
+ fields[3] = 100; // reject unconditionally
+ return TRUE;
+ }
+ if (string_skip_char(sp, &p, ':')) {
+ if (!string_get_digits(sp, &p, &fields[5], 2, 2)) /* second */
+ return FALSE;
+ string_get_milliseconds(sp, &p, &fields[6]);
+ }
+ }
+ /* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */
+ if (sp[p]) {
+ *is_local = FALSE;
+ if (!string_get_tzoffset(sp, &p, &fields[8], TRUE))
+ return FALSE;
+ }
+ /* error if extraneous characters */
+ return sp[p] == '\0';
+}
+
+static struct {
+ char name[6];
+ int16_t offset;
+} const js_tzabbr[] = {
+ { "GMT", 0 }, // Greenwich Mean Time
+ { "UTC", 0 }, // Coordinated Universal Time
+ { "UT", 0 }, // Universal Time
+ { "Z", 0 }, // Zulu Time
+ { "EDT", -4 * 60 }, // Eastern Daylight Time
+ { "EST", -5 * 60 }, // Eastern Standard Time
+ { "CDT", -5 * 60 }, // Central Daylight Time
+ { "CST", -6 * 60 }, // Central Standard Time
+ { "MDT", -6 * 60 }, // Mountain Daylight Time
+ { "MST", -7 * 60 }, // Mountain Standard Time
+ { "PDT", -7 * 60 }, // Pacific Daylight Time
+ { "PST", -8 * 60 }, // Pacific Standard Time
+ { "WET", +0 * 60 }, // Western European Time
+ { "WEST", +1 * 60 }, // Western European Summer Time
+ { "CET", +1 * 60 }, // Central European Time
+ { "CEST", +2 * 60 }, // Central European Summer Time
+ { "EET", +2 * 60 }, // Eastern European Time
+ { "EEST", +3 * 60 }, // Eastern European Summer Time
+};
+
+static BOOL string_get_tzabbr(const uint8_t *sp, int *pp, int *offset) {
+ for (size_t i = 0; i < countof(js_tzabbr); i++) {
+ if (string_match(sp, pp, js_tzabbr[i].name)) {
+ *offset = js_tzabbr[i].offset;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* parse toString, toUTCString and other formats */
+static BOOL js_date_parse_otherstring(const uint8_t *sp,
+ int fields[minimum_length(9)],
+ BOOL *is_local) {
+ int c, i, val, p = 0, p_start;
+ int num[3];
+ BOOL has_year = FALSE;
+ BOOL has_mon = FALSE;
+ BOOL has_time = FALSE;
+ int num_index = 0;
+
+ /* initialize fields to the beginning of 2001-01-01 */
+ fields[0] = 2001;
+ fields[1] = 1;
+ fields[2] = 1;
+ for (i = 3; i < 9; i++) {
+ fields[i] = 0;
+ }
+ *is_local = TRUE;
+
+ while (string_skip_spaces(sp, &p)) {
+ p_start = p;
+ if ((c = sp[p]) == '+' || c == '-') {
+ if (has_time && string_get_tzoffset(sp, &p, &fields[8], FALSE)) {
+ *is_local = FALSE;
+ } else {
+ p++;
+ if (string_get_digits(sp, &p, &val, 1, 9)) {
+ if (c == '-') {
+ if (val == 0)
+ return FALSE;
+ val = -val;
+ }
+ fields[0] = val;
+ has_year = TRUE;
+ }
+ }
+ } else
+ if (string_get_digits(sp, &p, &val, 1, 9)) {
+ if (string_skip_char(sp, &p, ':')) {
+ /* time part */
+ fields[3] = val;
+ if (!string_get_digits(sp, &p, &fields[4], 1, 2))
+ return FALSE;
+ if (string_skip_char(sp, &p, ':')) {
+ if (!string_get_digits(sp, &p, &fields[5], 1, 2))
+ return FALSE;
+ string_get_milliseconds(sp, &p, &fields[6]);
+ }
+ has_time = TRUE;
+ } else {
+ if (p - p_start > 2) {
+ fields[0] = val;
+ has_year = TRUE;
+ } else
+ if (val < 1 || val > 31) {
+ fields[0] = val + (val < 100) * 1900 + (val < 50) * 100;
+ has_year = TRUE;
+ } else {
+ if (num_index == 3)
+ return FALSE;
+ num[num_index++] = val;
+ }
+ }
+ } else
+ if (string_get_month(sp, &p, &fields[1])) {
+ has_mon = TRUE;
+ string_skip_until(sp, &p, "0123456789 -/(");
+ } else
+ if (has_time && string_match(sp, &p, "PM")) {
+ if (fields[3] < 12)
+ fields[3] += 12;
+ continue;
+ } else
+ if (has_time && string_match(sp, &p, "AM")) {
+ if (fields[3] == 12)
+ fields[3] -= 12;
+ continue;
+ } else
+ if (string_get_tzabbr(sp, &p, &fields[8])) {
+ *is_local = FALSE;
+ continue;
+ } else
+ if (c == '(') { /* skip parenthesized phrase */
+ int level = 0;
+ while ((c = sp[p]) != '\0') {
+ p++;
+ level += (c == '(');
+ level -= (c == ')');
+ if (!level)
+ break;
+ }
+ if (level > 0)
+ return FALSE;
+ } else
+ if (c == ')') {
+ return FALSE;
+ } else {
+ if (has_year + has_mon + has_time + num_index)
+ return FALSE;
+ /* skip a word */
+ string_skip_until(sp, &p, " -/(");
+ }
+ string_skip_separators(sp, &p);
+ }
+ if (num_index + has_year + has_mon > 3)
+ return FALSE;
+
+ switch (num_index) {
+ case 0:
+ if (!has_year)
+ return FALSE;
+ break;
+ case 1:
+ if (has_mon)
+ fields[2] = num[0];
+ else
+ fields[1] = num[0];
+ break;
+ case 2:
+ if (has_year) {
+ fields[1] = num[0];
+ fields[2] = num[1];
+ } else
+ if (has_mon) {
+ fields[0] = num[1] + (num[1] < 100) * 1900 + (num[1] < 50) * 100;
+ fields[2] = num[0];
+ } else {
+ fields[1] = num[0];
+ fields[2] = num[1];
+ }
+ break;
+ case 3:
+ fields[0] = num[2] + (num[2] < 100) * 1900 + (num[2] < 50) * 100;
+ fields[1] = num[0];
+ fields[2] = num[1];
+ break;
+ default:
+ return FALSE;
+ }
+ if (fields[1] < 1 || fields[2] < 1)
+ return FALSE;
+ fields[1] -= 1;
+ return TRUE;
}
static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
- // parse(s)
JSValue s, rv;
- int64_t fields[] = { 0, 1, 1, 0, 0, 0, 0 };
- double fields1[7];
- int64_t tz, hh, mm;
+ int fields[9];
+ double fields1[9];
double d;
- int p, i, c, sgn, l;
+ int i, c;
JSString *sp;
+ uint8_t buf[128];
BOOL is_local;
rv = JS_NAN;
@@ -48587,145 +50498,33 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
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 == '-')) {
- /* ISO format */
- /* year field can be negative */
- if (string_get_signed_digits(sp, &p, &fields[0]))
- goto done;
-
- for (i = 1; i < 7; i++) {
- if (p >= sp->len)
- break;
- switch(i) {
- case 1:
- case 2:
- c = '-';
- break;
- case 3:
- c = 'T';
- break;
- case 4:
- case 5:
- c = ':';
- break;
- case 6:
- c = '.';
- break;
- }
- if (string_get(sp, p) != c)
- break;
- p++;
- if (i == 6) {
- if (string_get_milliseconds(sp, &p, &fields[i]))
- goto done;
- } else {
- if (string_get_digits(sp, &p, &fields[i]))
- goto done;
- }
- }
- /* no time: UTC by default */
- is_local = (i > 3);
- fields[1] -= 1;
-
- /* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */
- tz = 0;
- if (p < sp->len) {
- sgn = string_get(sp, p);
- if (sgn == '+' || sgn == '-') {
- p++;
- l = sp->len - p;
- if (l != 4 && l != 5)
- goto done;
- if (string_get_fixed_width_digits(sp, &p, 2, &hh))
- goto done;
- if (l == 5) {
- if (string_get(sp, p) != ':')
- goto done;
- p++;
- }
- if (string_get_fixed_width_digits(sp, &p, 2, &mm))
- goto done;
- tz = hh * 60 + mm;
- if (sgn == '-')
- tz = -tz;
- is_local = FALSE;
- } else if (sgn == 'Z') {
- p++;
- is_local = FALSE;
- } else {
- goto done;
- }
- /* error if extraneous characters */
- if (p != sp->len)
- goto done;
- }
- } else {
- /* toString or toUTCString format */
- /* skip the day of the week */
- string_skip_non_spaces(sp, &p);
- string_skip_spaces(sp, &p);
- if (p >= sp->len)
- goto done;
- c = string_get(sp, p);
- if (c >= '0' && c <= '9') {
- /* day of month first */
- if (string_get_digits(sp, &p, &fields[2]))
- goto done;
- if (string_get_month(sp, &p, &fields[1]))
- goto done;
- } else {
- /* month first */
- if (string_get_month(sp, &p, &fields[1]))
- goto done;
- string_skip_spaces(sp, &p);
- if (string_get_digits(sp, &p, &fields[2]))
- goto done;
- }
- /* year */
- string_skip_spaces(sp, &p);
- if (string_get_signed_digits(sp, &p, &fields[0]))
- goto done;
-
- /* hour, min, seconds */
- string_skip_spaces(sp, &p);
- for(i = 0; i < 3; i++) {
- if (i == 1 || i == 2) {
- if (p >= sp->len)
- goto done;
- if (string_get(sp, p) != ':')
- goto done;
- p++;
- }
- if (string_get_digits(sp, &p, &fields[3 + i]))
- goto done;
- }
- // XXX: parse optional milliseconds?
-
- /* parse the time zone offset if present: [+-]HHmm */
- is_local = FALSE;
- tz = 0;
- for (tz = 0; p < sp->len; p++) {
- sgn = string_get(sp, p);
- if (sgn == '+' || sgn == '-') {
- p++;
- if (string_get_fixed_width_digits(sp, &p, 2, &hh))
- goto done;
- if (string_get_fixed_width_digits(sp, &p, 2, &mm))
- goto done;
- tz = hh * 60 + mm;
- if (sgn == '-')
- tz = -tz;
- break;
- }
+ /* convert the string as a byte array */
+ for (i = 0; i < sp->len && i < (int)countof(buf) - 1; i++) {
+ c = string_get(sp, i);
+ if (c > 255)
+ c = (c == 0x2212) ? '-' : 'x';
+ buf[i] = c;
+ }
+ buf[i] = '\0';
+ if (js_date_parse_isostring(buf, fields, &is_local)
+ || js_date_parse_otherstring(buf, fields, &is_local)) {
+ static int const field_max[6] = { 0, 11, 31, 24, 59, 59 };
+ BOOL valid = TRUE;
+ /* check field maximum values */
+ for (i = 1; i < 6; i++) {
+ if (fields[i] > field_max[i])
+ valid = FALSE;
+ }
+ /* special case 24:00:00.000 */
+ if (fields[3] == 24 && (fields[4] | fields[5] | fields[6]))
+ valid = FALSE;
+ if (valid) {
+ for(i = 0; i < 7; i++)
+ fields1[i] = fields[i];
+ d = set_date_fields(fields1, is_local) - fields[8] * 60000;
+ rv = JS_NewFloat64(ctx, d);
}
}
- for(i = 0; i < 7; i++)
- fields1[i] = fields[i];
- d = set_date_fields(fields1, is_local) - tz * 60000;
- rv = JS_NewFloat64(ctx, d);
-
-done:
JS_FreeValue(ctx, s);
return rv;
}
@@ -48756,9 +50555,7 @@ static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val,
}
switch (hint) {
case JS_ATOM_number:
-#ifdef CONFIG_BIGNUM
case JS_ATOM_integer:
-#endif
hint_num = HINT_NUMBER;
break;
case JS_ATOM_string:
@@ -48782,6 +50579,7 @@ static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,
if (isnan(v))
return JS_NAN;
else
+ /* assuming -8.64e15 <= v <= -8.64e15 */
return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v)));
}
@@ -48920,6 +50718,23 @@ static const JSCFunctionListEntry js_date_proto_funcs[] = {
JS_CFUNC_DEF("toJSON", 1, js_date_toJSON ),
};
+JSValue JS_NewDate(JSContext *ctx, double epoch_ms)
+{
+ JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_DATE);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ JS_SetObjectData(ctx, obj, __JS_NewFloat64(ctx, time_clip(epoch_ms)));
+ return obj;
+}
+
+JS_BOOL JS_IsDate(JSValue v)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
+ return FALSE;
+ return JS_VALUE_GET_OBJ(v)->class_id == JS_CLASS_DATE;
+}
+
void JS_AddIntrinsicDate(JSContext *ctx)
{
JSValueConst obj;
@@ -48937,7 +50752,7 @@ void JS_AddIntrinsicDate(JSContext *ctx)
void JS_AddIntrinsicEval(JSContext *ctx)
{
- ctx->eval_internal = JS_EvalInternalImpl;
+ ctx->eval_internal = __JS_EvalInternal;
}
#ifdef CONFIG_BIGNUM
@@ -49239,6 +51054,7 @@ void JS_AddIntrinsicOperators(JSContext *ctx)
js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT]);
js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL]);
}
+#endif /* CONFIG_BIGNUM */
/* BigInt */
@@ -49256,14 +51072,20 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
case JS_TAG_BIG_INT:
break;
case JS_TAG_FLOAT64:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
bf_t *a, a_s;
a = JS_ToBigFloat(ctx, &a_s, val);
+ if (!a) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
if (!bf_is_finite(a)) {
JS_FreeValue(ctx, val);
- val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to bigint");
+ val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to BigInt");
} else {
JSValue val1 = JS_NewBigInt(ctx);
bf_t *r;
@@ -49281,7 +51103,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
val = JS_ThrowOutOfMemory(ctx);
} else if (ret & BF_ST_INEXACT) {
JS_FreeValue(ctx, val1);
- val = JS_ThrowRangeError(ctx, "cannot convert to bigint: not an integer");
+ val = JS_ThrowRangeError(ctx, "cannot convert to BigInt: not an integer");
} else {
val = JS_CompactBigInt(ctx, val1);
}
@@ -49290,11 +51112,13 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
bf_delete(a);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL:
val = JS_ToStringFree(ctx, val);
- if (JS_IsException(val))
+ if (JS_IsException(val))
break;
goto redo;
+#endif
case JS_TAG_STRING:
val = JS_StringToBigIntErr(ctx, val);
break;
@@ -49307,7 +51131,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
case JS_TAG_UNDEFINED:
default:
JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert to bigint");
+ return JS_ThrowTypeError(ctx, "cannot convert to BigInt");
}
return val;
}
@@ -49333,7 +51157,7 @@ static JSValue js_thisBigIntValue(JSContext *ctx, JSValueConst this_val)
return JS_DupValue(ctx, p->u.object_data);
}
}
- return JS_ThrowTypeError(ctx, "not a bigint");
+ return JS_ThrowTypeError(ctx, "not a BigInt");
}
static JSValue js_bigint_toString(JSContext *ctx, JSValueConst this_val,
@@ -49367,6 +51191,7 @@ static JSValue js_bigint_valueOf(JSContext *ctx, JSValueConst this_val,
return js_thisBigIntValue(ctx, this_val);
}
+#ifdef CONFIG_BIGNUM
static JSValue js_bigint_div(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv, int magic)
@@ -49495,6 +51320,7 @@ static JSValue js_bigint_op1(JSContext *ctx,
JS_FreeBigInt(ctx, a, &a_s);
return JS_NewBigInt64(ctx, res);
}
+#endif
static JSValue js_bigint_asUintN(JSContext *ctx,
JSValueConst this_val,
@@ -49539,6 +51365,7 @@ static JSValue js_bigint_asUintN(JSContext *ctx,
static const JSCFunctionListEntry js_bigint_funcs[] = {
JS_CFUNC_MAGIC_DEF("asUintN", 2, js_bigint_asUintN, 0 ),
JS_CFUNC_MAGIC_DEF("asIntN", 2, js_bigint_asUintN, 1 ),
+#ifdef CONFIG_BIGNUM
/* QuickJS extensions */
JS_CFUNC_MAGIC_DEF("tdiv", 2, js_bigint_div, BF_RNDZ ),
JS_CFUNC_MAGIC_DEF("fdiv", 2, js_bigint_div, BF_RNDD ),
@@ -49552,6 +51379,7 @@ static const JSCFunctionListEntry js_bigint_funcs[] = {
JS_CFUNC_MAGIC_DEF("sqrtrem", 1, js_bigint_sqrt, 1 ),
JS_CFUNC_MAGIC_DEF("floorLog2", 1, js_bigint_op1, 0 ),
JS_CFUNC_MAGIC_DEF("ctz", 1, js_bigint_op1, 1 ),
+#endif
};
static const JSCFunctionListEntry js_bigint_proto_funcs[] = {
@@ -49581,6 +51409,8 @@ void JS_AddIntrinsicBigInt(JSContext *ctx)
countof(js_bigint_funcs));
}
+#ifdef CONFIG_BIGNUM
+
/* BigFloat */
static JSValue js_thisBigFloatValue(JSContext *ctx, JSValueConst this_val)
@@ -50054,6 +51884,10 @@ static JSValue js_bigfloat_fop(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(op1))
return op1;
a = JS_ToBigFloat(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, op1);
+ return JS_EXCEPTION;
+ }
fe = &ctx->fp_env;
if (argc > 1) {
fe = JS_GetOpaque2(ctx, argv[1], JS_CLASS_FLOAT_ENV);
@@ -50152,7 +51986,11 @@ static JSValue js_bigfloat_fop2(JSContext *ctx, JSValueConst this_val,
return op2;
}
a = JS_ToBigFloat(ctx, &a_s, op1);
+ if (!a)
+ goto fail1;
b = JS_ToBigFloat(ctx, &b_s, op2);
+ if (!b)
+ goto fail2;
fe = &ctx->fp_env;
if (argc > 2) {
fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV);
@@ -50162,10 +52000,12 @@ static JSValue js_bigfloat_fop2(JSContext *ctx, JSValueConst this_val,
res = JS_NewBigFloat(ctx);
if (JS_IsException(res)) {
fail:
- if (a == &a_s)
- bf_delete(a);
if (b == &b_s)
bf_delete(b);
+ fail2:
+ if (a == &a_s)
+ bf_delete(a);
+ fail1:
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
return JS_EXCEPTION;
@@ -50358,9 +52198,9 @@ static JSValue js_float_env_proto_get_status(JSContext *ctx, JSValueConst this_v
case FE_RNDMODE:
return JS_NewInt32(ctx, fe->flags & BF_RND_MASK);
case FE_SUBNORMAL:
- return JS_NewBool(ctx, (fe->flags & BF_FLAG_SUBNORMAL) != 0);
+ return JS_NewBool(ctx, fe->flags & BF_FLAG_SUBNORMAL);
default:
- return JS_NewBool(ctx, (fe->status & magic) != 0);
+ return JS_NewBool(ctx, fe->status & magic);
}
}
@@ -51057,7 +52897,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_PROP_HAS_GET | JS_PROP_HAS_SET |
JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);
JS_FreeValue(ctx, obj1);
- JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, &ctx->throw_type_error, 1));
+ JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1));
ctx->global_obj = JS_NewObject(ctx);
ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL);
@@ -51083,11 +52923,13 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_NewGlobalCConstructor2(ctx, obj1,
"Error", ctx->class_proto[JS_CLASS_ERROR]);
+ /* Used to squelch a -Wcast-function-type warning. */
+ JSCFunctionType ft = { .generic_magic = js_error_constructor };
for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
JSValue func_obj;
int n_args;
n_args = 1 + (i == JS_AGGREGATE_ERROR);
- func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_error_constructor,
+ func_obj = JS_NewCFunction3(ctx, ft.generic,
native_error_name[i], n_args,
JS_CFUNC_constructor_or_func_magic, i, obj1);
JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i],
@@ -51114,8 +52956,22 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
/* XXX: create auto_initializer */
{
/* initialize Array.prototype[Symbol.unscopables] */
- char const unscopables[] = "copyWithin" "\0" "entries" "\0" "fill" "\0" "find" "\0"
- "findIndex" "\0" "flat" "\0" "flatMap" "\0" "includes" "\0" "keys" "\0" "values" "\0";
+ static const char unscopables[] =
+ "copyWithin" "\0"
+ "entries" "\0"
+ "fill" "\0"
+ "find" "\0"
+ "findIndex" "\0"
+ "findLast" "\0"
+ "findLastIndex" "\0"
+ "flat" "\0"
+ "flatMap" "\0"
+ "includes" "\0"
+ "keys" "\0"
+ "toReversed" "\0"
+ "toSorted" "\0"
+ "toSpliced" "\0"
+ "values" "\0";
const char *p = unscopables;
obj1 = JS_NewObjectProto(ctx, JS_NULL);
for(p = unscopables; *p; p += strlen(p) + 1) {
@@ -51239,9 +53095,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = {
0, 0, 0, 1, 1, 2, 2,
-#ifdef CONFIG_BIGNUM
3, 3, /* BigInt64Array, BigUint64Array */
-#endif
2, 3
};
@@ -51371,11 +53225,26 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JSArrayBuffer *abuf = p->u.array_buffer;
+ struct list_head *el, *el1;
+
if (abuf) {
/* The ArrayBuffer finalizer may be called before the typed
array finalizers using it, so abuf->array_list is not
necessarily empty. */
- // assert(list_empty(&abuf->array_list));
+ list_for_each_safe(el, el1, &abuf->array_list) {
+ JSTypedArray *ta;
+ JSObject *p1;
+
+ ta = list_entry(el, JSTypedArray, link);
+ ta->link.prev = NULL;
+ ta->link.next = NULL;
+ p1 = ta->obj;
+ /* Note: the typed array length and offset fields are not modified */
+ if (p1->class_id != JS_CLASS_DATAVIEW) {
+ p1->u.array.count = 0;
+ p1->u.array.u.ptr = NULL;
+ }
+ }
if (abuf->shared && rt->sab_funcs.sab_free) {
rt->sab_funcs.sab_free(rt->sab_funcs.sab_opaque, abuf->data);
} else {
@@ -51685,6 +53554,16 @@ static JSValue js_typed_array_get_byteOffset(JSContext *ctx,
return JS_NewInt32(ctx, ta->offset);
}
+JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
+ JSTypedArrayEnum type)
+{
+ if (type < JS_TYPED_ARRAY_UINT8C || type > JS_TYPED_ARRAY_FLOAT64)
+ return JS_ThrowRangeError(ctx, "invalid typed array type");
+
+ return js_typed_array_constructor(ctx, JS_UNDEFINED, argc, argv,
+ JS_CLASS_UINT8C_ARRAY + type);
+}
+
/* Return the buffer associated to the typed array or an exception if
it is not a typed array or if the buffer is detached. pbyte_offset,
pbyte_length or pbytes_per_element can be NULL. */
@@ -51802,6 +53681,69 @@ fail:
return JS_EXCEPTION;
}
+static JSValue js_typed_array_at(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSObject *p;
+ int64_t idx, len;
+
+ p = get_typed_array(ctx, this_val, 0);
+ if (!p)
+ return JS_EXCEPTION;
+
+ if (typed_array_is_detached(ctx, p)) {
+ JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ return JS_EXCEPTION;
+ }
+
+ if (JS_ToInt64Sat(ctx, &idx, argv[0]))
+ return JS_EXCEPTION;
+
+ len = p->u.array.count;
+ if (idx < 0)
+ idx = len + idx;
+ if (idx < 0 || idx >= len)
+ return JS_UNDEFINED;
+ return JS_GetPropertyInt64(ctx, this_val, idx);
+}
+
+static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, val;
+ JSObject *p;
+ int64_t idx, len;
+
+ p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ if (!p)
+ return JS_EXCEPTION;
+
+ if (JS_ToInt64Sat(ctx, &idx, argv[0]))
+ return JS_EXCEPTION;
+
+ len = p->u.array.count;
+ if (idx < 0)
+ idx = len + idx;
+ if (idx < 0 || idx >= len)
+ return JS_ThrowRangeError(ctx, "invalid array index");
+
+ val = JS_ToPrimitive(ctx, argv[1], HINT_NUMBER);
+ if (JS_IsException(val))
+ return JS_EXCEPTION;
+
+ arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
+ p->class_id);
+ if (JS_IsException(arr)) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
+ if (JS_SetPropertyInt64(ctx, arr, idx, val) < 0) {
+ JS_FreeValue(ctx, arr);
+ return JS_EXCEPTION;
+ }
+ return arr;
+}
+
static JSValue js_typed_array_set(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv)
@@ -52091,14 +54033,10 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
if (JS_ToUint32(ctx, &v, argv[0]))
return JS_EXCEPTION;
v64 = v;
- } else
-#ifdef CONFIG_BIGNUM
- if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
+ } else if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
if (JS_ToBigInt64(ctx, (int64_t *)&v64, argv[0]))
return JS_EXCEPTION;
- } else
-#endif
- {
+ } else {
double d;
if (JS_ToFloat64(ctx, &d, argv[0]))
return JS_EXCEPTION;
@@ -52160,12 +54098,13 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
}
static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int findIndex)
+ int argc, JSValueConst *argv, int mode)
{
JSValueConst func, this_arg;
JSValueConst args[3];
JSValue val, index_val, res;
- int len, k;
+ int len, k, end;
+ int dir;
val = JS_UNDEFINED;
len = js_typed_array_get_length_internal(ctx, this_val);
@@ -52180,7 +54119,16 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
if (argc > 1)
this_arg = argv[1];
- for(k = 0; k < len; k++) {
+ k = 0;
+ dir = 1;
+ end = len;
+ if (mode == ArrayFindLast || mode == ArrayFindLastIndex) {
+ k = len - 1;
+ dir = -1;
+ end = -1;
+ }
+
+ for(; k != end; k += dir) {
index_val = JS_NewInt32(ctx, k);
val = JS_GetPropertyValue(ctx, this_val, index_val);
if (JS_IsException(val))
@@ -52192,7 +54140,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(res))
goto exception;
if (JS_ToBoolFree(ctx, res)) {
- if (findIndex) {
+ if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) {
JS_FreeValue(ctx, val);
return index_val;
} else {
@@ -52201,7 +54149,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
}
JS_FreeValue(ctx, val);
}
- if (findIndex)
+ if (mode == ArrayFindIndex || mode == ArrayFindLastIndex)
return JS_NewInt32(ctx, -1);
else
return JS_UNDEFINED;
@@ -52213,7 +54161,7 @@ exception:
#define special_indexOf 0
#define special_lastIndexOf 1
-#define special_includes (-1)
+#define special_includes -1
static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int special)
@@ -52280,13 +54228,14 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
is_int = 1;
v64 = JS_VALUE_GET_INT(argv[0]);
d = v64;
- } else if (tag == JS_TAG_FLOAT64) {
- d = JS_VALUE_GET_FLOAT64(argv[0]);
- v64 = d;
- is_int = (v64 == d);
} else
-#ifdef CONFIG_BIGNUM
- if (tag == JS_TAG_BIG_INT) {
+ if (tag == JS_TAG_FLOAT64) {
+ d = JS_VALUE_GET_FLOAT64(argv[0]);
+ if (d >= INT64_MIN && d < 0x1p63) {
+ v64 = d;
+ is_int = (v64 == d);
+ }
+ } else if (tag == JS_TAG_BIG_INT) {
JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]);
if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) {
@@ -52300,9 +54249,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
d = 0;
is_bigint = 1;
- } else
-#endif
- {
+ } else {
goto done;
}
@@ -52419,7 +54366,6 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
}
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
if (is_bigint || (is_math_mode(ctx) && is_int &&
v64 >= -MAX_SAFE_INTEGER &&
@@ -52443,7 +54389,6 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
}
break;
-#endif
}
done:
@@ -52578,6 +54523,24 @@ static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val,
return JS_DupValue(ctx, this_val);
}
+static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, ret;
+ JSObject *p;
+
+ p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ if (!p)
+ return JS_EXCEPTION;
+ arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
+ p->class_id);
+ if (JS_IsException(arr))
+ return JS_EXCEPTION;
+ ret = js_typed_array_reverse(ctx, arr, argc, argv);
+ JS_FreeValue(ctx, arr);
+ return ret;
+}
+
static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -52724,7 +54687,6 @@ static int js_TA_cmp_uint32(const void *a, const void *b, void *opaque) {
return (y < x) - (y > x);
}
-#ifdef CONFIG_BIGNUM
static int js_TA_cmp_int64(const void *a, const void *b, void *opaque) {
int64_t x = *(const int64_t *)a;
int64_t y = *(const int64_t *)b;
@@ -52736,7 +54698,6 @@ static int js_TA_cmp_uint64(const void *a, const void *b, void *opaque) {
uint64_t y = *(const uint64_t *)b;
return (y < x) - (y > x);
}
-#endif
static int js_TA_cmp_float32(const void *a, const void *b, void *opaque) {
return js_cmp_doubles(*(const float *)a, *(const float *)b);
@@ -52770,7 +54731,6 @@ static JSValue js_TA_get_uint32(JSContext *ctx, const void *a) {
return JS_NewUint32(ctx, *(const uint32_t *)a);
}
-#ifdef CONFIG_BIGNUM
static JSValue js_TA_get_int64(JSContext *ctx, const void *a) {
return JS_NewBigInt64(ctx, *(int64_t *)a);
}
@@ -52778,19 +54738,18 @@ static JSValue js_TA_get_int64(JSContext *ctx, const void *a) {
static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) {
return JS_NewBigUint64(ctx, *(uint64_t *)a);
}
-#endif
static JSValue js_TA_get_float32(JSContext *ctx, const void *a) {
- return JS_NewFloat64Impl(ctx, *(const float *)a);
+ return __JS_NewFloat64(ctx, *(const float *)a);
}
static JSValue js_TA_get_float64(JSContext *ctx, const void *a) {
- return JS_NewFloat64Impl(ctx, *(const double *)a);
+ return __JS_NewFloat64(ctx, *(const double *)a);
}
struct TA_sort_context {
JSContext *ctx;
- int exception;
+ int exception; /* 1 = exception, 2 = detached typed array */
JSValueConst arr;
JSValueConst cmp;
JSValue (*getfun)(JSContext *ctx, const void *a);
@@ -52808,6 +54767,8 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
cmp = 0;
if (!psc->exception) {
+ /* Note: the typed array can be detached without causing an
+ error */
a_idx = *(uint32_t *)a;
b_idx = *(uint32_t *)b;
argv[0] = psc->getfun(ctx, psc->array_ptr +
@@ -52835,8 +54796,9 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
/* make sort stable: compare array offsets */
cmp = (a_idx > b_idx) - (a_idx < b_idx);
}
- if (validate_typed_array(ctx, psc->arr) < 0) {
- psc->exception = 1;
+ if (unlikely(typed_array_is_detached(ctx,
+ JS_VALUE_GET_PTR(psc->arr)))) {
+ psc->exception = 2;
}
done:
JS_FreeValue(ctx, argv[0]);
@@ -52860,11 +54822,11 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
tsc.arr = this_val;
tsc.cmp = argv[0];
+ if (!JS_IsUndefined(tsc.cmp) && check_function(ctx, tsc.cmp))
+ return JS_EXCEPTION;
len = js_typed_array_get_length_internal(ctx, this_val);
if (len < 0)
return JS_EXCEPTION;
- if (!JS_IsUndefined(tsc.cmp) && check_function(ctx, tsc.cmp))
- return JS_EXCEPTION;
if (len > 1) {
p = JS_VALUE_GET_OBJ(this_val);
@@ -52894,7 +54856,6 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
tsc.getfun = js_TA_get_uint32;
cmpfun = js_TA_cmp_uint32;
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
tsc.getfun = js_TA_get_int64;
cmpfun = js_TA_cmp_int64;
@@ -52903,7 +54864,6 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
tsc.getfun = js_TA_get_uint64;
cmpfun = js_TA_cmp_uint64;
break;
-#endif
case JS_CLASS_FLOAT32_ARRAY:
tsc.getfun = js_TA_get_float32;
cmpfun = js_TA_cmp_float32;
@@ -52932,44 +54892,48 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
tsc.elt_size = elt_size;
rqsort(array_idx, len, sizeof(array_idx[0]),
js_TA_cmp_generic, &tsc);
- if (tsc.exception)
- goto fail;
- array_tmp = js_malloc(ctx, len * elt_size);
- if (!array_tmp) {
- fail:
- js_free(ctx, array_idx);
- return JS_EXCEPTION;
- }
- memcpy(array_tmp, array_ptr, len * elt_size);
- switch(elt_size) {
- case 1:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint8_t *)array_ptr)[i] = ((uint8_t *)array_tmp)[j];
- }
- break;
- case 2:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint16_t *)array_ptr)[i] = ((uint16_t *)array_tmp)[j];
- }
- break;
- case 4:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint32_t *)array_ptr)[i] = ((uint32_t *)array_tmp)[j];
+ if (tsc.exception) {
+ if (tsc.exception == 1)
+ goto fail;
+ /* detached typed array during the sort: no error */
+ } else {
+ array_tmp = js_malloc(ctx, len * elt_size);
+ if (!array_tmp) {
+ fail:
+ js_free(ctx, array_idx);
+ return JS_EXCEPTION;
}
- break;
- case 8:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint64_t *)array_ptr)[i] = ((uint64_t *)array_tmp)[j];
+ memcpy(array_tmp, array_ptr, len * elt_size);
+ switch(elt_size) {
+ case 1:
+ for(i = 0; i < len; i++) {
+ j = array_idx[i];
+ ((uint8_t *)array_ptr)[i] = ((uint8_t *)array_tmp)[j];
+ }
+ break;
+ case 2:
+ for(i = 0; i < len; i++) {
+ j = array_idx[i];
+ ((uint16_t *)array_ptr)[i] = ((uint16_t *)array_tmp)[j];
+ }
+ break;
+ case 4:
+ for(i = 0; i < len; i++) {
+ j = array_idx[i];
+ ((uint32_t *)array_ptr)[i] = ((uint32_t *)array_tmp)[j];
+ }
+ break;
+ case 8:
+ for(i = 0; i < len; i++) {
+ j = array_idx[i];
+ ((uint64_t *)array_ptr)[i] = ((uint64_t *)array_tmp)[j];
+ }
+ break;
+ default:
+ abort();
}
- break;
- default:
- abort();
+ js_free(ctx, array_tmp);
}
- js_free(ctx, array_tmp);
js_free(ctx, array_idx);
} else {
rqsort(array_ptr, len, elt_size, cmpfun, &tsc);
@@ -52980,6 +54944,24 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
return JS_DupValue(ctx, this_val);
}
+static JSValue js_typed_array_toSorted(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, ret;
+ JSObject *p;
+
+ p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ if (!p)
+ return JS_EXCEPTION;
+ arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
+ p->class_id);
+ if (JS_IsException(arr))
+ return JS_EXCEPTION;
+ ret = js_typed_array_sort(ctx, arr, argc, argv);
+ JS_FreeValue(ctx, arr);
+ return ret;
+}
+
static const JSCFunctionListEntry js_typed_array_base_funcs[] = {
JS_CFUNC_DEF("from", 1, js_typed_array_from ),
JS_CFUNC_DEF("of", 0, js_typed_array_of ),
@@ -52991,6 +54973,8 @@ static const JSCFunctionListEntry js_typed_array_base_funcs[] = {
static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = {
JS_CGETSET_DEF("length", js_typed_array_get_length, NULL ),
+ JS_CFUNC_DEF("at", 1, js_typed_array_at ),
+ JS_CFUNC_DEF("with", 2, js_typed_array_with ),
JS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 0 ),
JS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, 0 ),
JS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, 0 ),
@@ -53009,12 +54993,16 @@ static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce | special_TA ),
JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight | special_TA ),
JS_CFUNC_DEF("fill", 1, js_typed_array_fill ),
- JS_CFUNC_MAGIC_DEF("find", 1, js_typed_array_find, 0 ),
- JS_CFUNC_MAGIC_DEF("findIndex", 1, js_typed_array_find, 1 ),
+ JS_CFUNC_MAGIC_DEF("find", 1, js_typed_array_find, ArrayFind ),
+ JS_CFUNC_MAGIC_DEF("findIndex", 1, js_typed_array_find, ArrayFindIndex ),
+ JS_CFUNC_MAGIC_DEF("findLast", 1, js_typed_array_find, ArrayFindLast ),
+ JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_typed_array_find, ArrayFindLastIndex ),
JS_CFUNC_DEF("reverse", 0, js_typed_array_reverse ),
+ JS_CFUNC_DEF("toReversed", 0, js_typed_array_toReversed ),
JS_CFUNC_DEF("slice", 2, js_typed_array_slice ),
JS_CFUNC_DEF("subarray", 2, js_typed_array_subarray ),
JS_CFUNC_DEF("sort", 1, js_typed_array_sort ),
+ JS_CFUNC_DEF("toSorted", 1, js_typed_array_toSorted ),
JS_CFUNC_MAGIC_DEF("join", 1, js_typed_array_join, 0 ),
JS_CFUNC_MAGIC_DEF("toLocaleString", 0, js_typed_array_join, 1 ),
JS_CFUNC_MAGIC_DEF("indexOf", 1, js_typed_array_indexOf, special_indexOf ),
@@ -53161,7 +55149,7 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx,
{
JSObject *p, *src_buffer;
JSTypedArray *ta;
- JSValue ctor, obj, buffer;
+ JSValue obj, buffer;
uint32_t len, i;
int size_log2;
JSArrayBuffer *src_abuf, *abuf;
@@ -53178,19 +55166,9 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx,
len = p->u.array.count;
src_buffer = ta->buffer;
src_abuf = src_buffer->u.array_buffer;
- if (!src_abuf->shared) {
- ctor = JS_SpeciesConstructor(ctx, JS_MKPTR(JS_TAG_OBJECT, src_buffer),
- JS_UNDEFINED);
- if (JS_IsException(ctor))
- goto fail;
- } else {
- /* force ArrayBuffer default constructor */
- ctor = JS_UNDEFINED;
- }
size_log2 = typed_array_size_log2(classid);
- buffer = js_array_buffer_constructor1(ctx, ctor,
+ buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED,
(uint64_t)len << size_log2);
- JS_FreeValue(ctx, ctor);
if (JS_IsException(buffer))
goto fail;
/* necessary because it could have been detached */
@@ -53296,7 +55274,7 @@ static void js_typed_array_finalizer(JSRuntime *rt, JSValue val)
if (ta) {
/* during the GC the finalizers are called in an arbitrary
order so the ArrayBuffer finalizer may have been called */
- if (JS_IsLiveObject(rt, JS_MKPTR(JS_TAG_OBJECT, ta->buffer))) {
+ if (ta->link.next) {
list_del(&ta->link);
}
JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ta->buffer));
@@ -53379,7 +55357,8 @@ static JSValue js_dataview_getValue(JSContext *ctx,
{
JSTypedArray *ta;
JSArrayBuffer *abuf;
- int is_swap, size;
+ BOOL littleEndian, is_swap;
+ int size;
uint8_t *ptr;
uint32_t v;
uint64_t pos;
@@ -53390,12 +55369,8 @@ static JSValue js_dataview_getValue(JSContext *ctx,
size = 1 << typed_array_size_log2(class_id);
if (JS_ToIndex(ctx, &pos, argv[0]))
return JS_EXCEPTION;
- is_swap = FALSE;
- if (argc > 1)
- is_swap = JS_ToBool(ctx, argv[1]);
-#ifndef WORDS_BIGENDIAN
- is_swap ^= 1;
-#endif
+ littleEndian = argc > 1 && JS_ToBool(ctx, argv[1]);
+ is_swap = littleEndian ^ !is_be();
abuf = ta->buffer->u.array_buffer;
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
@@ -53407,7 +55382,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
case JS_CLASS_INT8_ARRAY:
return JS_NewInt32(ctx, *(int8_t *)ptr);
case JS_CLASS_UINT8_ARRAY:
- return JS_NewInt32(ctx, *ptr);
+ return JS_NewInt32(ctx, *(uint8_t *)ptr);
case JS_CLASS_INT16_ARRAY:
v = get_u16(ptr);
if (is_swap)
@@ -53428,7 +55403,6 @@ static JSValue js_dataview_getValue(JSContext *ctx,
if (is_swap)
v = bswap32(v);
return JS_NewUint32(ctx, v);
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
{
uint64_t v;
@@ -53447,7 +55421,6 @@ static JSValue js_dataview_getValue(JSContext *ctx,
return JS_NewBigUint64(ctx, v);
}
break;
-#endif
case JS_CLASS_FLOAT32_ARRAY:
{
union {
@@ -53458,7 +55431,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
if (is_swap)
v = bswap32(v);
u.i = v;
- return JS_NewFloat64Impl(ctx, u.f);
+ return __JS_NewFloat64(ctx, u.f);
}
case JS_CLASS_FLOAT64_ARRAY:
{
@@ -53469,7 +55442,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
u.i = get_u64(ptr);
if (is_swap)
u.i = bswap64(u.i);
- return JS_NewFloat64Impl(ctx, u.f);
+ return __JS_NewFloat64(ctx, u.f);
}
default:
abort();
@@ -53482,7 +55455,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
{
JSTypedArray *ta;
JSArrayBuffer *abuf;
- int is_swap, size;
+ BOOL littleEndian, is_swap;
+ int size;
uint8_t *ptr;
uint64_t v64;
uint32_t v;
@@ -53501,14 +55475,10 @@ static JSValue js_dataview_setValue(JSContext *ctx,
if (class_id <= JS_CLASS_UINT32_ARRAY) {
if (JS_ToUint32(ctx, &v, val))
return JS_EXCEPTION;
- } else
-#ifdef CONFIG_BIGNUM
- if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
+ } else if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
if (JS_ToBigInt64(ctx, (int64_t *)&v64, val))
return JS_EXCEPTION;
- } else
-#endif
- {
+ } else {
double d;
if (JS_ToFloat64(ctx, &d, val))
return JS_EXCEPTION;
@@ -53525,12 +55495,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
v64 = u.u64;
}
}
- is_swap = FALSE;
- if (argc > 2)
- is_swap = JS_ToBool(ctx, argv[2]);
-#ifndef WORDS_BIGENDIAN
- is_swap ^= 1;
-#endif
+ littleEndian = argc > 2 && JS_ToBool(ctx, argv[2]);
+ is_swap = littleEndian ^ !is_be();
abuf = ta->buffer->u.array_buffer;
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
@@ -53556,10 +55522,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
v = bswap32(v);
put_u32(ptr, v);
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
-#endif
case JS_CLASS_FLOAT64_ARRAY:
if (is_swap)
v64 = bswap64(v64);
@@ -53581,10 +55545,8 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("getUint16", 1, js_dataview_getValue, JS_CLASS_UINT16_ARRAY ),
JS_CFUNC_MAGIC_DEF("getInt32", 1, js_dataview_getValue, JS_CLASS_INT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("getUint32", 1, js_dataview_getValue, JS_CLASS_UINT32_ARRAY ),
-#ifdef CONFIG_BIGNUM
JS_CFUNC_MAGIC_DEF("getBigInt64", 1, js_dataview_getValue, JS_CLASS_BIG_INT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("getBigUint64", 1, js_dataview_getValue, JS_CLASS_BIG_UINT64_ARRAY ),
-#endif
JS_CFUNC_MAGIC_DEF("getFloat32", 1, js_dataview_getValue, JS_CLASS_FLOAT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("getFloat64", 1, js_dataview_getValue, JS_CLASS_FLOAT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("setInt8", 2, js_dataview_setValue, JS_CLASS_INT8_ARRAY ),
@@ -53593,10 +55555,8 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("setUint16", 2, js_dataview_setValue, JS_CLASS_UINT16_ARRAY ),
JS_CFUNC_MAGIC_DEF("setInt32", 2, js_dataview_setValue, JS_CLASS_INT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("setUint32", 2, js_dataview_setValue, JS_CLASS_UINT32_ARRAY ),
-#ifdef CONFIG_BIGNUM
JS_CFUNC_MAGIC_DEF("setBigInt64", 2, js_dataview_setValue, JS_CLASS_BIG_INT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("setBigUint64", 2, js_dataview_setValue, JS_CLASS_BIG_UINT64_ARRAY ),
-#endif
JS_CFUNC_MAGIC_DEF("setFloat32", 2, js_dataview_setValue, JS_CLASS_FLOAT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("setFloat64", 2, js_dataview_setValue, JS_CLASS_FLOAT64_ARRAY ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DataView", JS_PROP_CONFIGURABLE ),
@@ -53633,20 +55593,12 @@ static void *js_atomics_get_ptr(JSContext *ctx,
if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
goto fail;
p = JS_VALUE_GET_OBJ(obj);
-#ifdef CONFIG_BIGNUM
if (is_waitable)
err = (p->class_id != JS_CLASS_INT32_ARRAY &&
p->class_id != JS_CLASS_BIG_INT64_ARRAY);
else
err = !(p->class_id >= JS_CLASS_INT8_ARRAY &&
p->class_id <= JS_CLASS_BIG_UINT64_ARRAY);
-#else
- if (is_waitable)
- err = (p->class_id != JS_CLASS_INT32_ARRAY);
- else
- err = !(p->class_id >= JS_CLASS_INT8_ARRAY &&
- p->class_id <= JS_CLASS_UINT32_ARRAY);
-#endif
if (err) {
fail:
JS_ThrowTypeError(ctx, "integer TypedArray expected");
@@ -53688,11 +55640,7 @@ static JSValue js_atomics_op(JSContext *ctx,
int argc, JSValueConst *argv, int op)
{
int size_log2;
-#ifdef CONFIG_BIGNUM
uint64_t v, a, rep_val;
-#else
- uint32_t v, a, rep_val;
-#endif
void *ptr;
JSValue ret;
JSClassID class_id;
@@ -53706,7 +55654,6 @@ static JSValue js_atomics_op(JSContext *ctx,
if (op == ATOMICS_OP_LOAD) {
v = 0;
} else {
-#ifdef CONFIG_BIGNUM
if (size_log2 == 3) {
int64_t v64;
if (JS_ToBigInt64(ctx, &v64, argv[2]))
@@ -53717,9 +55664,7 @@ static JSValue js_atomics_op(JSContext *ctx,
return JS_EXCEPTION;
rep_val = v64;
}
- } else
-#endif
- {
+ } else {
uint32_t v32;
if (JS_ToUint32(ctx, &v32, argv[2]))
return JS_EXCEPTION;
@@ -53736,7 +55681,6 @@ 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): \
a = func_name((_Atomic(uint8_t) *)ptr, v); \
@@ -53750,18 +55694,7 @@ static JSValue js_atomics_op(JSContext *ctx,
case ATOMICS_OP_ ## op_name | (3 << 3): \
a = func_name((_Atomic(uint64_t) *)ptr, v); \
break;
-#else
-#define OP(op_name, func_name) \
- case ATOMICS_OP_ ## op_name | (0 << 3): \
- a = func_name((_Atomic(uint8_t) *)ptr, v); \
- break; \
- case ATOMICS_OP_ ## op_name | (1 << 3): \
- a = func_name((_Atomic(uint16_t) *)ptr, v); \
- break; \
- case ATOMICS_OP_ ## op_name | (2 << 3): \
- a = func_name((_Atomic(uint32_t) *)ptr, v); \
- break;
-#endif
+
OP(ADD, atomic_fetch_add)
OP(AND, atomic_fetch_and)
OP(OR, atomic_fetch_or)
@@ -53779,11 +55712,9 @@ static JSValue js_atomics_op(JSContext *ctx,
case ATOMICS_OP_LOAD | (2 << 3):
a = atomic_load((_Atomic(uint32_t) *)ptr);
break;
-#ifdef CONFIG_BIGNUM
case ATOMICS_OP_LOAD | (3 << 3):
a = atomic_load((_Atomic(uint64_t) *)ptr);
break;
-#endif
case ATOMICS_OP_COMPARE_EXCHANGE | (0 << 3):
{
@@ -53806,7 +55737,6 @@ static JSValue js_atomics_op(JSContext *ctx,
a = v1;
}
break;
-#ifdef CONFIG_BIGNUM
case ATOMICS_OP_COMPARE_EXCHANGE | (3 << 3):
{
uint64_t v1 = v;
@@ -53814,7 +55744,6 @@ static JSValue js_atomics_op(JSContext *ctx,
a = v1;
}
break;
-#endif
default:
abort();
}
@@ -53839,14 +55768,12 @@ static JSValue js_atomics_op(JSContext *ctx,
case JS_CLASS_UINT32_ARRAY:
ret = JS_NewUint32(ctx, a);
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
ret = JS_NewBigInt64(ctx, a);
break;
case JS_CLASS_BIG_UINT64_ARRAY:
ret = JS_NewBigUint64(ctx, a);
break;
-#endif
default:
abort();
}
@@ -53866,7 +55793,6 @@ static JSValue js_atomics_store(JSContext *ctx,
argv[0], argv[1], 0);
if (!ptr)
return JS_EXCEPTION;
-#ifdef CONFIG_BIGNUM
if (size_log2 == 3) {
int64_t v64;
ret = JS_ToBigIntValueFree(ctx, JS_DupValue(ctx, argv[2]));
@@ -53879,9 +55805,7 @@ static JSValue js_atomics_store(JSContext *ctx,
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
atomic_store((_Atomic(uint64_t) *)ptr, v64);
- } else
-#endif
- {
+ } else {
uint32_t v;
/* XXX: spec, would be simpler to return the written value */
ret = JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[2]));
@@ -53917,11 +55841,7 @@ static JSValue js_atomics_isLockFree(JSContext *ctx,
int v, ret;
if (JS_ToInt32Sat(ctx, &v, argv[0]))
return JS_EXCEPTION;
- ret = (v == 1 || v == 2 || v == 4
-#ifdef CONFIG_BIGNUM
- || v == 8
-#endif
- );
+ ret = (v == 1 || v == 2 || v == 4 || v == 8);
return JS_NewBool(ctx, ret);
}
@@ -53953,20 +55873,18 @@ static JSValue js_atomics_wait(JSContext *ctx,
argv[0], argv[1], 2);
if (!ptr)
return JS_EXCEPTION;
-#ifdef CONFIG_BIGNUM
if (size_log2 == 3) {
if (JS_ToBigInt64(ctx, &v, argv[2]))
return JS_EXCEPTION;
- } else
-#endif
- {
+ } else {
if (JS_ToInt32(ctx, &v32, argv[2]))
return JS_EXCEPTION;
v = v32;
}
if (JS_ToFloat64(ctx, &d, argv[3]))
return JS_EXCEPTION;
- if (isnan(d) || d > INT64_MAX)
+ /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */
+ if (isnan(d) || d >= 0x1p63)
timeout = INT64_MAX;
else if (d < 0)
timeout = 0;
@@ -54144,6 +56062,8 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
countof(js_typed_array_base_funcs));
JS_SetConstructor(ctx, typed_array_base_func, typed_array_base_proto);
+ /* Used to squelch a -Wcast-function-type warning. */
+ JSCFunctionType ft = { .generic_magic = js_typed_array_constructor };
for(i = JS_CLASS_UINT8C_ARRAY; i < JS_CLASS_UINT8C_ARRAY + JS_TYPED_ARRAY_COUNT; i++) {
JSValue func_obj;
char buf[ATOM_GET_STR_BUF_SIZE];
@@ -54156,7 +56076,7 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
0);
name = JS_AtomGetStr(ctx, buf, sizeof(buf),
JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY);
- func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_typed_array_constructor,
+ func_obj = JS_NewCFunction3(ctx, ft.generic,
name, 3, JS_CFUNC_constructor_magic, i,
typed_array_base_func);
JS_NewGlobalCConstructor2(ctx, func_obj, name, ctx->class_proto[i]);
@@ -54269,7 +56189,7 @@ void JS_FreeValue(JSContext *ctx, JSValue v) {
notifyRefCountDecrease(p);
#endif
if (--p->ref_count <= 0) {
- JS_FreeValueImpl(ctx, v);
+ __JS_FreeValue(ctx, v);
}
}
}
@@ -54280,7 +56200,7 @@ void JS_FreeValueRT(JSRuntime *rt, JSValue v) {
notifyRefCountDecrease(p);
#endif
if (--p->ref_count <= 0) {
- JS_FreeValueRTImpl(rt, v);
+ __JS_FreeValueRT(rt, v);
}
}
}
@@ -54301,7 +56221,7 @@ JSValue JS_NewInt64(JSContext *ctx, int64_t val) {
if (val == (int32_t)val) {
v = JS_NewInt32(ctx, (int32_t)val);
} else {
- v = JS_NewFloat64Impl(ctx, (double)val);
+ v = __JS_NewFloat64(ctx, (double)val);
}
return v;
}
@@ -54310,29 +56230,29 @@ JSValue JS_NewUint32(JSContext *ctx, uint32_t val) {
if (val <= 0x7fffffff) {
v = JS_NewInt32(ctx, val);
} else {
- v = JS_NewFloat64Impl(ctx, val);
+ v = __JS_NewFloat64(ctx, val);
}
return v;
}
-JSValue JS_NewFloat64(JSContext *ctx, double d) {
- JSValue v;
+JSValue JS_NewFloat64(JSContext *ctx, double d)
+{
int32_t val;
union {
double d;
uint64_t u;
} u, t;
- u.d = d;
- val = (int32_t)d;
- t.d = val;
- /* -0 cannot be represented as integer, so we compare the bit
- representation */
- if (u.u == t.u) {
- v = JS_MKVAL(JS_TAG_INT, val);
- } else {
- v = JS_NewFloat64Impl(ctx, d);
+ if (d >= INT32_MIN && d <= INT32_MAX) {
+ u.d = d;
+ val = (int32_t)d;
+ t.d = val;
+ /* -0 cannot be represented as integer, so we compare the bit
+ representation */
+ if (u.u == t.u)
+ return JS_MKVAL(JS_TAG_INT, val);
}
- return v;
+ return __JS_NewFloat64(ctx, d);
}
+
JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
int length) {
return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
@@ -54345,23 +56265,3 @@ JS_BOOL JS_IsRegExp(JSContext *ctx, JSValue val)
return FALSE;
return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_REGEXP;
}
-
-int JS_IsDate(JSValue v)
-{
- JSObject *p;
- if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
- return FALSE;
- return JS_VALUE_GET_OBJ(v)->class_id == JS_CLASS_DATE;
-}
-
-JSValue JS_NewDate(JSContext *ctx, const char *s)
-{
- JSValue dateString = JS_NewString(ctx, s);
- JSAtom constrAtom = JS_NewAtom(ctx, "Date");
- JSValue constr = JS_GetGlobalVar(ctx, constrAtom, FALSE);
- JSValue date = js_date_constructor(ctx, constr, 1, &dateString);
- JS_FreeValue(ctx, constr);
- JS_FreeValue(ctx, dateString);
- JS_FreeAtom(ctx, constrAtom);
- return date;
-}
diff --git a/src/shared/quickjs/quickjs.diff b/src/shared/quickjs/quickjs.diff
deleted file mode 100644
index e87999050..000000000
--- a/src/shared/quickjs/quickjs.diff
+++ /dev/null
@@ -1,4061 +0,0 @@
-diff --git a/cutils.c b/cutils.c
-index a02fb76..1f66fff 100644
---- a/cutils.c
-+++ b/cutils.c
-@@ -166,8 +166,7 @@ int dbuf_putstr(DynBuf *s, const char *str)
- return dbuf_put(s, (const uint8_t *)str, strlen(str));
- }
-
--int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
-- const char *fmt, ...)
-+int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...)
- {
- va_list ap;
- char buf[128];
-diff --git a/cutils.h b/cutils.h
-index 31f7cd8..ee0ce4a 100644
---- a/cutils.h
-+++ b/cutils.h
-@@ -28,14 +28,33 @@
- #include <stdlib.h>
- #include <inttypes.h>
-
-+#if defined(_MSC_VER)
-+#include <BaseTsd.h>
-+typedef SSIZE_T ssize_t;
-+#else
-+#include <sys/types.h>
-+#endif
-+
- /* set if CPU is big endian */
- #undef WORDS_BIGENDIAN
-
-+#ifdef __GNUC__
- #define likely(x) __builtin_expect(!!(x), 1)
- #define unlikely(x) __builtin_expect(!!(x), 0)
- #define force_inline inline __attribute__((always_inline))
- #define no_inline __attribute__((noinline))
--#define __maybe_unused __attribute__((unused))
-+#define maybe_unused __attribute__((unused))
-+#else
-+#define likely(x) (x)
-+#define unlikely(x) (x)
-+#define force_inline
-+#define no_inline
-+#define maybe_unused
-+#endif
-+
-+#ifdef _MSC_VER
-+#define alloca _alloca
-+#endif
-
- #define xglue(x, y) x ## y
- #define glue(x, y) xglue(x, y)
-@@ -114,38 +133,24 @@ static inline int64_t min_int64(int64_t a, int64_t b)
- /* WARNING: undefined if a = 0 */
- static inline int clz32(unsigned int a)
- {
-+#ifdef _MSC_VER
-+ return (int) __lzcnt(a);
-+#else
- return __builtin_clz(a);
-+#endif
- }
-
--/* WARNING: undefined if a = 0 */
--static inline int clz64(uint64_t a)
--{
-- return __builtin_clzll(a);
--}
--
--/* WARNING: undefined if a = 0 */
--static inline int ctz32(unsigned int a)
--{
-- return __builtin_ctz(a);
--}
--
--/* WARNING: undefined if a = 0 */
--static inline int ctz64(uint64_t a)
--{
-- return __builtin_ctzll(a);
--}
--
--struct __attribute__((packed)) packed_u64 {
-+#pragma pack(push, 1)
-+struct packed_u64 {
- uint64_t v;
- };
--
--struct __attribute__((packed)) packed_u32 {
-+struct packed_u32 {
- uint32_t v;
- };
--
--struct __attribute__((packed)) packed_u16 {
-+struct packed_u16 {
- uint16_t v;
- };
-+#pragma pack(pop)
-
- static inline uint64_t get_u64(const uint8_t *tab)
- {
-@@ -262,8 +267,15 @@ static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
- {
- return dbuf_put(s, (uint8_t *)&val, 8);
- }
--int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
-- const char *fmt, ...);
-+
-+#ifdef __GNUC__
-+#define FORMAT_ATTR(x, y) __attribute__((format(printf, x, y)))
-+#else
-+#define FORMAT_ATTR(x, y)
-+#endif
-+
-+int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...);
-+
- void dbuf_free(DynBuf *s);
- static inline BOOL dbuf_error(DynBuf *s) {
- return s->error;
-diff --git a/libregexp.c b/libregexp.c
-index 379bfc7..ad91f78 100644
---- a/libregexp.c
-+++ b/libregexp.c
-@@ -271,7 +271,7 @@ static int cr_canonicalize(CharRange *cr)
- }
-
- #ifdef DUMP_REOP
--static __maybe_unused void lre_dump_bytecode(const uint8_t *buf,
-+static MAYBE_UNUSED void lre_dump_bytecode(const uint8_t *buf,
- int buf_len)
- {
- int pos, len, opcode, bc_len, re_flags, i;
-@@ -427,7 +427,7 @@ static void re_emit_op_u16(REParseState *s, int op, uint32_t val)
- dbuf_put_u16(&s->byte_code, val);
- }
-
--static int __attribute__((format(printf, 2, 3))) re_parse_error(REParseState *s, const char *fmt, ...)
-+static int FORMAT_ATTR(2, 3) re_parse_error(REParseState *s, const char *fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
-@@ -1472,7 +1472,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
- default:
- parse_class_atom:
- c = get_class_atom(s, cr, &p, FALSE);
-- if ((int)c < 0)
-+ if (c < 0)
- return -1;
- normal_char:
- last_atom_start = s->byte_code.size;
-@@ -1924,17 +1924,17 @@ static BOOL is_word_char(uint32_t c)
- #define GET_CHAR(c, cptr, cbuf_end) \
- do { \
- if (cbuf_type == 0) { \
-- c = *cptr++; \
-+ (c) = *(cptr)++; \
- } else { \
- uint32_t __c1; \
-- c = *(uint16_t *)cptr; \
-- cptr += 2; \
-- if (c >= 0xd800 && c < 0xdc00 && \
-- cbuf_type == 2 && cptr < cbuf_end) { \
-- __c1 = *(uint16_t *)cptr; \
-+ (c) = *(uint16_t *)(cptr); \
-+ (cptr) += 2; \
-+ if ((c) >= 0xd800 && (c) < 0xdc00 && \
-+ cbuf_type == 2 && (cptr) < (cbuf_end)) { \
-+ __c1 = *(uint16_t *)(cptr); \
- if (__c1 >= 0xdc00 && __c1 < 0xe000) { \
-- c = (((c & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
-- cptr += 2; \
-+ (c) = ((((c) & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
-+ (cptr) += 2; \
- } \
- } \
- } \
-@@ -1943,15 +1943,15 @@ static BOOL is_word_char(uint32_t c)
- #define PEEK_CHAR(c, cptr, cbuf_end) \
- do { \
- if (cbuf_type == 0) { \
-- c = cptr[0]; \
-+ (c) = (cptr)[0]; \
- } else { \
- uint32_t __c1; \
-- c = ((uint16_t *)cptr)[0]; \
-- if (c >= 0xd800 && c < 0xdc00 && \
-- cbuf_type == 2 && (cptr + 2) < cbuf_end) { \
-- __c1 = ((uint16_t *)cptr)[1]; \
-+ (c) = ((uint16_t *)(cptr))[0]; \
-+ if ((c) >= 0xd800 && (c) < 0xdc00 && \
-+ cbuf_type == 2 && ((cptr) + 2) < (cbuf_end)) { \
-+ __c1 = ((uint16_t *)(cptr))[1]; \
- if (__c1 >= 0xdc00 && __c1 < 0xe000) { \
-- c = (((c & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
-+ (c) = ((((c) & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
- } \
- } \
- } \
-@@ -1960,15 +1960,15 @@ static BOOL is_word_char(uint32_t c)
- #define PEEK_PREV_CHAR(c, cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
-- c = cptr[-1]; \
-+ (c) = (cptr)[-1]; \
- } else { \
- uint32_t __c1; \
-- c = ((uint16_t *)cptr)[-1]; \
-- if (c >= 0xdc00 && c < 0xe000 && \
-- cbuf_type == 2 && (cptr - 4) >= cbuf_start) { \
-- __c1 = ((uint16_t *)cptr)[-2]; \
-+ (c) = ((uint16_t *)(cptr))[-1]; \
-+ if ((c) >= 0xdc00 && (c) < 0xe000 && \
-+ cbuf_type == 2 && ((cptr) - 4) >= (cbuf_start)) { \
-+ __c1 = ((uint16_t *)(cptr))[-2]; \
- if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \
-- c = (((__c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000; \
-+ (c) = (((__c1 & 0x3ff) << 10) | ((c) & 0x3ff)) + 0x10000; \
- } \
- } \
- } \
-@@ -1977,18 +1977,18 @@ static BOOL is_word_char(uint32_t c)
- #define GET_PREV_CHAR(c, cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
-- cptr--; \
-- c = cptr[0]; \
-+ (cptr)--; \
-+ (c) = (cptr)[0]; \
- } else { \
- uint32_t __c1; \
-- cptr -= 2; \
-- c = ((uint16_t *)cptr)[0]; \
-- if (c >= 0xdc00 && c < 0xe000 && \
-- cbuf_type == 2 && cptr > cbuf_start) { \
-- __c1 = ((uint16_t *)cptr)[-1]; \
-+ (cptr) -= 2; \
-+ (c) = ((uint16_t *)(cptr))[0]; \
-+ if ((c) >= 0xdc00 && (c) < 0xe000 && \
-+ cbuf_type == 2 && (cptr) > (cbuf_start)) { \
-+ __c1 = ((uint16_t *)(cptr))[-1]; \
- if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \
-- cptr -= 2; \
-- c = (((__c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000; \
-+ (cptr) -= 2; \
-+ (c) = (((__c1 & 0x3ff) << 10) | ((c) & 0x3ff)) + 0x10000; \
- } \
- } \
- } \
-@@ -1997,15 +1997,15 @@ static BOOL is_word_char(uint32_t c)
- #define PREV_CHAR(cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
-- cptr--; \
-+ (cptr)--; \
- } else { \
-- cptr -= 2; \
-+ (cptr) -= 2; \
- if (cbuf_type == 2) { \
-- c = ((uint16_t *)cptr)[0]; \
-- if (c >= 0xdc00 && c < 0xe000 && cptr > cbuf_start) { \
-- c = ((uint16_t *)cptr)[-1]; \
-+ c = ((uint16_t *)(cptr))[0]; \
-+ if (c >= 0xdc00 && c < 0xe000 && (cptr) > (cbuf_start)) { \
-+ c = ((uint16_t *)(cptr))[-1]; \
- if (c >= 0xd800 && c < 0xdc00) \
-- cptr -= 2; \
-+ (cptr) -= 2; \
- } \
- } \
- } \
-@@ -2049,7 +2049,7 @@ typedef struct {
-
- static int push_state(REExecContext *s,
- uint8_t **capture,
-- StackInt *stack, size_t stack_len,
-+ const StackInt *stack, size_t stack_len,
- const uint8_t *pc, const uint8_t *cptr,
- REExecStateEnum type, size_t count)
- {
-diff --git a/libunicode.c b/libunicode.c
-index 63c12a0..112da72 100644
---- a/libunicode.c
-+++ b/libunicode.c
-@@ -271,7 +271,7 @@ BOOL lre_is_case_ignorable(uint32_t c)
-
- /* character range */
-
--static __maybe_unused void cr_dump(CharRange *cr)
-+static maybe_unused void cr_dump(CharRange *cr)
- {
- int i;
- for(i = 0; i < cr->len; i++)
-@@ -1315,11 +1315,13 @@ static int unicode_prop_ops(CharRange *cr, ...)
- }
- }
- done:
-+ va_end(ap);
- assert(stack_len == 1);
- ret = cr_copy(cr, &stack[0]);
- cr_free(&stack[0]);
- return ret;
- fail:
-+ va_end(ap);
- for(i = 0; i < stack_len; i++)
- cr_free(&stack[i]);
- return -1;
-diff --git a/list.h b/list.h
-index 0a1bc5a..e7f51a9 100644
---- a/list.h
-+++ b/list.h
-@@ -46,7 +46,7 @@ static inline void init_list_head(struct list_head *head)
- }
-
- /* insert 'el' between 'prev' and 'next' */
--static inline void __list_add(struct list_head *el,
-+static inline void list_add_impl(struct list_head *el,
- struct list_head *prev, struct list_head *next)
- {
- prev->next = el;
-@@ -58,13 +58,13 @@ static inline void __list_add(struct list_head *el,
- /* add 'el' at the head of the list 'head' (= after element head) */
- static inline void list_add(struct list_head *el, struct list_head *head)
- {
-- __list_add(el, head, head->next);
-+ list_add_impl(el, head, head->next);
- }
-
- /* add 'el' at the end of the list 'head' (= before element head) */
- static inline void list_add_tail(struct list_head *el, struct list_head *head)
- {
-- __list_add(el, head->prev, head);
-+ list_add_impl(el, head->prev, head);
- }
-
- static inline void list_del(struct list_head *el)
-diff --git a/quickjs.c b/quickjs.c
-index 7916013..f90fb9e 100644
---- a/quickjs.c
-+++ b/quickjs.c
-@@ -28,7 +28,9 @@
- #include <inttypes.h>
- #include <string.h>
- #include <assert.h>
-+#ifndef _MSC_VER
- #include <sys/time.h>
-+#endif
- #include <time.h>
- #include <fenv.h>
- #include <math.h>
-@@ -40,6 +42,18 @@
- #include <malloc_np.h>
- #endif
-
-+#ifdef _MSC_VER
-+#include <intrin.h>
-+#include <windows.h>
-+#endif
-+
-+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
-+ || defined(__APPLE__)
-+#include <xlocale.h>
-+#else
-+#include <locale.h>
-+#endif
-+
- #include "cutils.h"
- #include "list.h"
- #include "quickjs.h"
-@@ -48,9 +62,9 @@
- #include "libbf.h"
- #endif
-
--#define OPTIMIZE 1
-+#define OPTIMIZE 0
- #define SHORT_OPCODES 1
--#if defined(EMSCRIPTEN)
-+#if defined(EMSCRIPTEN) || defined(_MSC_VER)
- #define DIRECT_DISPATCH 0
- #else
- #define DIRECT_DISPATCH 1
-@@ -69,7 +83,7 @@
-
- /* define to include Atomics.* operations which depend on the OS
- threads */
--#if !defined(EMSCRIPTEN)
-+#if !defined(EMSCRIPTEN) && !defined(_MSC_VER)
- #define CONFIG_ATOMICS
- #endif
-
-@@ -78,7 +92,6 @@
- #define CONFIG_STACK_CHECK
- #endif
-
--
- /* dump object free */
- //#define DUMP_FREE
- //#define DUMP_CLOSURE
-@@ -115,6 +128,25 @@
- #include <errno.h>
- #endif
-
-+static double safe_strtod(const char *restrict nptr, char **restrict endptr)
-+{
-+#if defined(_MSC_VER) || defined(__MINGW32__)
-+ _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
-+ setlocale(LC_NUMERIC, "C");
-+#else
-+ const locale_t tempLoc = newlocale(LC_NUMERIC_MASK, "C", 0);
-+ uselocale(tempLoc);
-+#endif
-+ double d = strtod(nptr, endptr);
-+#if defined(_MSC_VER) || defined(__MINGW32__)
-+ _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
-+#else
-+ uselocale(LC_GLOBAL_LOCALE);
-+ freelocale(tempLoc);
-+#endif
-+ return d;
-+}
-+
- enum {
- /* classid tag */ /* union usage | properties */
- JS_CLASS_OBJECT = 1, /* must be first */
-@@ -204,7 +236,11 @@ typedef enum JSErrorEnum {
- #define JS_STACK_SIZE_MAX 65534
- #define JS_STRING_LEN_MAX ((1 << 30) - 1)
-
--#define __exception __attribute__((warn_unused_result))
-+#ifdef __GNUC__
-+#define warn_unused __attribute__((warn_unused_result))
-+#else
-+#define warn_unused
-+#endif
-
- typedef struct JSShape JSShape;
- typedef struct JSString JSString;
-@@ -362,8 +398,8 @@ typedef struct JSVarRef {
- union {
- JSGCObjectHeader header; /* must come first */
- struct {
-- int __gc_ref_count; /* corresponds to header.ref_count */
-- uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
-+ int _gc_ref_count; /* corresponds to header.ref_count */
-+ uint8_t _gc_mark; /* corresponds to header.mark/gc_obj_type */
-
- /* 0 : the JSVarRef is on the stack. header.link is an element
- of JSStackFrame.var_ref_list.
-@@ -455,8 +491,12 @@ struct JSContext {
- /* if NULL, eval is not supported */
- JSValue (*eval_internal)(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int flags, int scope_idx);
-+ const char *filename, int line, int flags, int scope_idx);
- void *user_opaque;
-+ ScopeLookup *scopeLookup;
-+ FoundUndefinedHandler *handleUndefined;
-+ FunctionEnteredHandler *handleFunctionEntered;
-+ FunctionExitedHandler *handleFunctionExited;
- };
-
- typedef union JSFloat64Union {
-@@ -867,8 +907,8 @@ struct JSObject {
- union {
- JSGCObjectHeader header;
- struct {
-- int __gc_ref_count; /* corresponds to header.ref_count */
-- uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
-+ 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 */
-@@ -950,7 +990,7 @@ struct JSObject {
- /* byte sizes: 40/48/72 */
- };
- enum {
-- __JS_ATOM_NULL = JS_ATOM_NULL,
-+ JS_ATOM_NULL_ = JS_ATOM_NULL,
- #define DEF(name, str) JS_ATOM_ ## name,
- #include "quickjs-atom.h"
- #undef DEF
-@@ -996,7 +1036,7 @@ enum OPCodeEnum {
- };
-
- static int JS_InitAtoms(JSRuntime *rt);
--static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
-+static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
- int atom_type);
- static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);
- static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);
-@@ -1017,24 +1057,23 @@ static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_o
- int argc, JSValueConst *argv);
- static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
- int argc, JSValueConst *argv);
--static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
-+static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
- JSValue val, BOOL is_array_ctor);
- static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
- JSValueConst val, int flags, int scope_idx);
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
--static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
--static __maybe_unused void JS_DumpString(JSRuntime *rt,
-+static maybe_unused void JS_DumpAtoms(JSRuntime *rt);
-+static maybe_unused void JS_DumpString(JSRuntime *rt,
- const JSString *p);
--static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
--static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
--static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
--static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
-+static maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
-+static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
-+static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
-+static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
- JSValueConst val);
--static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
--static __maybe_unused void JS_PrintValue(JSContext *ctx,
-+static maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
-+static maybe_unused void JS_PrintValue(JSContext *ctx,
- const char *str,
- JSValueConst val);
--static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
-+static maybe_unused void JS_DumpShapes(JSRuntime *rt);
- static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int magic);
- static void js_array_finalizer(JSRuntime *rt, JSValue val);
-@@ -1148,7 +1187,6 @@ static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,
- BOOL allow_null_or_undefined);
- static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val);
- #endif
--JSValue JS_ThrowOutOfMemory(JSContext *ctx);
- static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);
- static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);
- static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
-@@ -1187,7 +1225,7 @@ static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
- static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int flags, int scope_idx);
-+ const char *filename, int line, int flags, int scope_idx);
- static void js_free_module_def(JSContext *ctx, JSModuleDef *m);
- static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
- JS_MarkFunc *mark_func);
-@@ -1197,7 +1235,7 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);
- static JSValue js_new_promise_capability(JSContext *ctx,
- JSValue *resolving_funcs,
- JSValueConst ctor);
--static __exception int perform_promise_then(JSContext *ctx,
-+static warn_unused int perform_promise_then(JSContext *ctx,
- JSValueConst promise,
- JSValueConst *resolve_reject,
- JSValueConst *cap_resolving_funcs);
-@@ -1222,9 +1260,9 @@ static void js_free_shape_null(JSRuntime *rt, JSShape *sh);
- static int js_shape_prepare_update(JSContext *ctx, JSObject *p,
- JSShapeProperty **pprs);
- static int init_shape_hash(JSRuntime *rt);
--static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
-+static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
- JSValueConst obj);
--static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
-+static warn_unused int js_get_length64(JSContext *ctx, int64_t *pres,
- JSValueConst obj);
- static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len);
- static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
-@@ -1582,10 +1620,27 @@ static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
- return FALSE;
- }
- #else
--/* Note: OS and CPU dependent */
-+// Uses code from LLVM project.
- static inline uintptr_t js_get_stack_pointer(void)
- {
-+#ifdef _MSC_VER
-+ return (uintptr_t) _AddressOfReturnAddress();
-+#elif defined __has_builtin
-+#if __has_builtin(__builtin_frame_address)
- return (uintptr_t) __builtin_frame_address(0);
-+#endif
-+#elif defined __GNUC__
-+ return (uintptr_t) __builtin_frame_address(0);
-+#else
-+ char CharOnStack = 0;
-+ // The volatile store here is intended to escape the local variable, to
-+ // prevent the compiler from optimizing CharOnStack into anything other
-+ // than a char on the stack.
-+ //
-+ // Tested on: MSVC 2015 - 2019, GCC 4.9 - 9, Clang 3.2 - 9, ICC 13 - 19.
-+ char *volatile Ptr = &CharOnStack;
-+ return (uintptr_t) Ptr;
-+#endif
- }
-
- static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
-@@ -1980,6 +2035,7 @@ void JS_FreeRuntime(JSRuntime *rt)
- printf("Secondary object leaks: %d\n", count);
- }
- #endif
-+ fflush(stdout);
- assert(list_empty(&rt->gc_obj_list));
-
- /* free the classes */
-@@ -2386,7 +2442,7 @@ static inline BOOL is_math_mode(JSContext *ctx)
- /* return the max count from the hash size */
- #define JS_ATOM_COUNT_RESIZE(n) ((n) * 2)
-
--static inline BOOL __JS_AtomIsConst(JSAtom v)
-+static inline BOOL JS_AtomIsConst(JSAtom v)
- {
- #if defined(DUMP_LEAKS) && DUMP_LEAKS > 1
- return (int32_t)v <= 0;
-@@ -2395,17 +2451,17 @@ static inline BOOL __JS_AtomIsConst(JSAtom v)
- #endif
- }
-
--static inline BOOL __JS_AtomIsTaggedInt(JSAtom v)
-+static inline BOOL JS_AtomIsTaggedInt(JSAtom v)
- {
- return (v & JS_ATOM_TAG_INT) != 0;
- }
-
--static inline JSAtom __JS_AtomFromUInt32(uint32_t v)
-+static inline JSAtom JS_AtomFromUInt32(uint32_t v)
- {
- return v | JS_ATOM_TAG_INT;
- }
-
--static inline uint32_t __JS_AtomToUInt32(JSAtom atom)
-+static inline uint32_t JS_AtomToUInt32(JSAtom atom)
- {
- return atom & ~JS_ATOM_TAG_INT;
- }
-@@ -2485,7 +2541,7 @@ static uint32_t hash_string(const JSString *str, uint32_t h)
- return h;
- }
-
--static __maybe_unused void JS_DumpString(JSRuntime *rt,
-+static maybe_unused void JS_DumpString(JSRuntime *rt,
- const JSString *p)
- {
- int i, c, sep;
-@@ -2517,7 +2573,7 @@ static __maybe_unused void JS_DumpString(JSRuntime *rt,
- putchar(sep);
- }
-
--static __maybe_unused void JS_DumpAtoms(JSRuntime *rt)
-+static maybe_unused void JS_DumpAtoms(JSRuntime *rt)
- {
- JSAtomStruct *p;
- int h, i;
-@@ -2604,7 +2660,7 @@ static int JS_InitAtoms(JSRuntime *rt)
- else
- atom_type = JS_ATOM_TYPE_STRING;
- len = strlen(p);
-- if (__JS_NewAtomInit(rt, p, len, atom_type) == JS_ATOM_NULL)
-+ if (JS_NewAtomInitImpl(rt, p, len, atom_type) == JS_ATOM_NULL)
- return -1;
- p = p + len + 1;
- }
-@@ -2615,7 +2671,7 @@ static JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v)
- {
- JSAtomStruct *p;
-
-- if (!__JS_AtomIsConst(v)) {
-+ if (!JS_AtomIsConst(v)) {
- p = rt->atom_array[v];
- p->header.ref_count++;
- }
-@@ -2627,7 +2683,7 @@ JSAtom JS_DupAtom(JSContext *ctx, JSAtom v)
- JSRuntime *rt;
- JSAtomStruct *p;
-
-- if (!__JS_AtomIsConst(v)) {
-+ if (!JS_AtomIsConst(v)) {
- rt = ctx->rt;
- p = rt->atom_array[v];
- p->header.ref_count++;
-@@ -2641,7 +2697,7 @@ static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v)
- JSAtomStruct *p;
-
- rt = ctx->rt;
-- if (__JS_AtomIsTaggedInt(v))
-+ if (JS_AtomIsTaggedInt(v))
- return JS_ATOM_KIND_STRING;
- p = rt->atom_array[v];
- switch(p->atom_type) {
-@@ -2687,7 +2743,7 @@ static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p)
-
- /* string case (internal). Return JS_ATOM_NULL if error. 'str' is
- freed. */
--static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
-+static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
- {
- uint32_t h, h1, i;
- JSAtomStruct *p;
-@@ -2702,7 +2758,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
- /* str is the atom, return its index */
- i = js_get_atom_index(rt, str);
- /* reduce string refcount and increase atom's unless constant */
-- if (__JS_AtomIsConst(i))
-+ if (JS_AtomIsConst(i))
- str->header.ref_count--;
- return i;
- }
-@@ -2718,7 +2774,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
- p->atom_type == atom_type &&
- p->len == len &&
- js_string_memcmp(p, str, len) == 0) {
-- if (!__JS_AtomIsConst(i))
-+ if (!JS_AtomIsConst(i))
- p->header.ref_count++;
- goto done;
- }
-@@ -2843,7 +2899,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
- }
-
- /* only works with zero terminated 8 bit strings */
--static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
-+static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
- int atom_type)
- {
- JSString *p;
-@@ -2852,10 +2908,10 @@ static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
- return JS_ATOM_NULL;
- memcpy(p->u.str8, str, len);
- p->u.str8[len] = '\0';
-- return __JS_NewAtom(rt, p, atom_type);
-+ return JS_NewAtomImpl(rt, p, atom_type);
- }
-
--static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
-+static JSAtom JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
- int atom_type)
- {
- uint32_t h, h1, i;
-@@ -2872,7 +2928,7 @@ static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
- p->len == len &&
- p->is_wide_char == 0 &&
- memcmp(p->u.str8, str, len) == 0) {
-- if (!__JS_AtomIsConst(i))
-+ if (!JS_AtomIsConst(i))
- p->header.ref_count++;
- return i;
- }
-@@ -2924,7 +2980,7 @@ static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p)
- assert(rt->atom_count >= 0);
- }
-
--static void __JS_FreeAtom(JSRuntime *rt, uint32_t i)
-+static void JS_FreeAtomImpl(JSRuntime *rt, uint32_t i)
- {
- JSAtomStruct *p;
-
-@@ -2942,11 +2998,11 @@ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p)
- if (is_num_string(&n, p)) {
- if (n <= JS_ATOM_MAX_INT) {
- js_free_string(rt, p);
-- return __JS_AtomFromUInt32(n);
-+ return JS_AtomFromUInt32(n);
- }
- }
- /* XXX: should generate an exception */
-- return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING);
-+ return JS_NewAtomImpl(rt, p, JS_ATOM_TYPE_STRING);
- }
-
- JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)
-@@ -2954,7 +3010,7 @@ JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)
- JSValue val;
-
- if (len == 0 || !is_digit(*str)) {
-- JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
-+ JSAtom atom = JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
- if (atom)
- return atom;
- }
-@@ -2972,7 +3028,7 @@ JSAtom JS_NewAtom(JSContext *ctx, const char *str)
- JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
- {
- if (n <= JS_ATOM_MAX_INT) {
-- return __JS_AtomFromUInt32(n);
-+ return JS_AtomFromUInt32(n);
- } else {
- char buf[11];
- JSValue val;
-@@ -2980,7 +3036,7 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
- val = JS_NewString(ctx, buf);
- if (JS_IsException(val))
- return JS_ATOM_NULL;
-- return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
-+ return JS_NewAtomImpl(ctx->rt, JS_VALUE_GET_STRING(val),
- JS_ATOM_TYPE_STRING);
- }
- }
-@@ -2988,7 +3044,7 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
- static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
- {
- if ((uint64_t)n <= JS_ATOM_MAX_INT) {
-- return __JS_AtomFromUInt32((uint32_t)n);
-+ return JS_AtomFromUInt32((uint32_t)n);
- } else {
- char buf[24];
- JSValue val;
-@@ -2996,7 +3052,7 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
- val = JS_NewString(ctx, buf);
- if (JS_IsException(val))
- return JS_ATOM_NULL;
-- return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
-+ return JS_NewAtomImpl(ctx->rt, JS_VALUE_GET_STRING(val),
- JS_ATOM_TYPE_STRING);
- }
- }
-@@ -3006,7 +3062,7 @@ static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type)
- {
- JSRuntime *rt = ctx->rt;
- JSAtom atom;
-- atom = __JS_NewAtom(rt, p, atom_type);
-+ atom = JS_NewAtomImpl(rt, p, atom_type);
- if (atom == JS_ATOM_NULL)
- return JS_ThrowOutOfMemory(ctx);
- return JS_MKPTR(JS_TAG_SYMBOL, rt->atom_array[atom]);
-@@ -3019,7 +3075,7 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
- JSRuntime *rt = ctx->rt;
- JSString *p;
-
-- assert(!__JS_AtomIsTaggedInt(descr));
-+ assert(!JS_AtomIsTaggedInt(descr));
- assert(descr < rt->atom_size);
- p = rt->atom_array[descr];
- JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
-@@ -3032,8 +3088,8 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
- static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,
- JSAtom atom)
- {
-- if (__JS_AtomIsTaggedInt(atom)) {
-- snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom));
-+ if (JS_AtomIsTaggedInt(atom)) {
-+ snprintf(buf, buf_size, "%u", JS_AtomToUInt32(atom));
- } else {
- JSAtomStruct *p;
- assert(atom < rt->atom_size);
-@@ -3083,12 +3139,12 @@ static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom
- return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom);
- }
-
--static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)
-+static JSValue JS_AtomToValueImpl(JSContext *ctx, JSAtom atom, BOOL force_string)
- {
- char buf[ATOM_GET_STR_BUF_SIZE];
-
-- if (__JS_AtomIsTaggedInt(atom)) {
-- snprintf(buf, sizeof(buf), "%u", __JS_AtomToUInt32(atom));
-+ if (JS_AtomIsTaggedInt(atom)) {
-+ snprintf(buf, sizeof(buf), "%u", JS_AtomToUInt32(atom));
- return JS_NewString(ctx, buf);
- } else {
- JSRuntime *rt = ctx->rt;
-@@ -3112,20 +3168,20 @@ static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)
-
- JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom)
- {
-- return __JS_AtomToValue(ctx, atom, FALSE);
-+ return JS_AtomToValueImpl(ctx, atom, FALSE);
- }
-
- JSValue JS_AtomToString(JSContext *ctx, JSAtom atom)
- {
-- return __JS_AtomToValue(ctx, atom, TRUE);
-+ return JS_AtomToValueImpl(ctx, atom, TRUE);
- }
-
- /* return TRUE if the atom is an array index (i.e. 0 <= index <=
- 2^32-2 and return its value */
- static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom)
- {
-- if (__JS_AtomIsTaggedInt(atom)) {
-- *pval = __JS_AtomToUInt32(atom);
-+ if (JS_AtomIsTaggedInt(atom)) {
-+ *pval = JS_AtomToUInt32(atom);
- return TRUE;
- } else {
- JSRuntime *rt = ctx->rt;
-@@ -3156,8 +3212,8 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
- int c, len, ret;
- JSValue num, str;
-
-- if (__JS_AtomIsTaggedInt(atom))
-- return JS_NewInt32(ctx, __JS_AtomToUInt32(atom));
-+ if (JS_AtomIsTaggedInt(atom))
-+ return JS_NewInt32(ctx, JS_AtomToUInt32(atom));
- assert(atom < rt->atom_size);
- p1 = rt->atom_array[atom];
- if (p1->atom_type != JS_ATOM_TYPE_STRING)
-@@ -3199,7 +3255,7 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
- /* -0 case is specific */
- if (c == '0' && len == 2) {
- minus_zero:
-- return __JS_NewFloat64(ctx, -0.0);
-+ return JS_NewFloat64Impl(ctx, -0.0);
- }
- }
- if (!is_num(c)) {
-@@ -3244,14 +3300,14 @@ static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom)
-
- void JS_FreeAtom(JSContext *ctx, JSAtom v)
- {
-- if (!__JS_AtomIsConst(v))
-- __JS_FreeAtom(ctx->rt, v);
-+ if (!JS_AtomIsConst(v))
-+ JS_FreeAtomImpl(ctx->rt, v);
- }
-
- void JS_FreeAtomRT(JSRuntime *rt, JSAtom v)
- {
-- if (!__JS_AtomIsConst(v))
-- __JS_FreeAtom(rt, v);
-+ if (!JS_AtomIsConst(v))
-+ JS_FreeAtomImpl(rt, v);
- }
-
- /* return TRUE if 'v' is a symbol with a string description */
-@@ -3261,7 +3317,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
- JSAtomStruct *p;
-
- rt = ctx->rt;
-- if (__JS_AtomIsTaggedInt(v))
-+ if (JS_AtomIsTaggedInt(v))
- return FALSE;
- p = rt->atom_array[v];
- return (((p->atom_type == JS_ATOM_TYPE_SYMBOL &&
-@@ -3270,7 +3326,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
- !(p->len == 0 && p->is_wide_char != 0));
- }
-
--static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom)
-+static maybe_unused void print_atom(JSContext *ctx, JSAtom atom)
- {
- char buf[ATOM_GET_STR_BUF_SIZE];
- const char *p;
-@@ -3445,9 +3501,9 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def)
- JSAtom name;
-
- len = strlen(class_def->class_name);
-- name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
-+ name = JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
- if (name == JS_ATOM_NULL) {
-- name = __JS_NewAtomInit(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
-+ name = JS_NewAtomInitImpl(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
- if (name == JS_ATOM_NULL)
- return -1;
- }
-@@ -4614,7 +4670,7 @@ static int add_shape_property(JSContext *ctx, JSShape **psh,
- pr = &prop[sh->prop_count++];
- pr->atom = JS_DupAtom(ctx, atom);
- pr->flags = prop_flags;
-- sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom);
-+ sh->has_small_array_index |= JS_AtomIsTaggedInt(atom);
- /* add in hash table */
- hash_mask = sh->prop_hash_mask;
- h = atom & hash_mask;
-@@ -4675,7 +4731,7 @@ static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh,
- return NULL;
- }
-
--static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
-+static maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
- {
- char atom_buf[ATOM_GET_STR_BUF_SIZE];
- int j;
-@@ -4691,7 +4747,7 @@ static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
- printf("\n");
- }
-
--static __maybe_unused void JS_DumpShapes(JSRuntime *rt)
-+static maybe_unused void JS_DumpShapes(JSRuntime *rt)
- {
- int i;
- JSShape *sh;
-@@ -5471,7 +5527,7 @@ static void free_zero_refcount(JSRuntime *rt)
- }
-
- /* called with the ref_count of 'v' reaches zero. */
--void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
-+static void JS_FreeValueRTImpl(JSRuntime *rt, JSValue v)
- {
- uint32_t tag = JS_VALUE_GET_TAG(v);
-
-@@ -5546,9 +5602,9 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
- }
- }
-
--void __JS_FreeValue(JSContext *ctx, JSValue v)
-+static void JS_FreeValueImpl(JSContext *ctx, JSValue v)
- {
-- __JS_FreeValueRT(ctx->rt, v);
-+ JS_FreeValueRTImpl(ctx->rt, v);
- }
-
- /* garbage collection */
-@@ -6469,7 +6525,7 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func)
-
- /* if filename != NULL, an additional level is added with the filename
- and line number information (used for parse error). */
--static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
-+void build_backtrace(JSContext *ctx, JSValueConst error_obj,
- const char *filename, int line_num,
- int backtrace_flags)
- {
-@@ -6569,7 +6625,7 @@ JSValue JS_NewError(JSContext *ctx)
- static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,
- const char *fmt, va_list ap, BOOL add_backtrace)
- {
-- char buf[256];
-+ char buf[8192];
- JSValue obj, ret;
-
- vsnprintf(buf, sizeof(buf), fmt, ap);
-@@ -6604,7 +6660,7 @@ static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num,
- return JS_ThrowError2(ctx, error_num, fmt, ap, add_backtrace);
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6615,7 +6671,7 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext *ctx
- return val;
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6626,7 +6682,7 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext *ctx,
- return val;
- }
-
--static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...)
-+static int FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...)
- {
- va_list ap;
-
-@@ -6642,7 +6698,7 @@ static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSCont
- }
-
- /* never use it directly */
--static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
-+static JSValue FORMAT_ATTR(3, 4) JS_ThrowTypeErrorAtomImpl(JSContext *ctx, JSAtom atom, const char *fmt, ...)
- {
- char buf[ATOM_GET_STR_BUF_SIZE];
- return JS_ThrowTypeError(ctx, fmt,
-@@ -6650,7 +6706,7 @@ static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSC
- }
-
- /* never use it directly */
--static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
-+static JSValue FORMAT_ATTR(3, 4) JS_ThrowSyntaxErrorAtomImpl(JSContext *ctx, JSAtom atom, const char *fmt, ...)
- {
- char buf[ATOM_GET_STR_BUF_SIZE];
- return JS_ThrowSyntaxError(ctx, fmt,
-@@ -6659,8 +6715,8 @@ static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(J
-
- /* %s is replaced by 'atom'. The macro is used so that gcc can check
- the format string. */
--#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "")
--#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "")
-+#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) JS_ThrowTypeErrorAtomImpl(ctx, atom, fmt, "")
-+#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) JS_ThrowSyntaxErrorAtomImpl(ctx, atom, fmt, "")
-
- static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
- {
-@@ -6673,7 +6729,7 @@ static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
- }
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6684,7 +6740,7 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext *
- return val;
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6695,7 +6751,7 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowRangeError(JSContext *ctx,
- return val;
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6770,7 +6826,7 @@ static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)
- return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name);
- }
-
--static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
-+static no_inline warn_unused int js_poll_interrupts_impl(JSContext *ctx)
- {
- JSRuntime *rt = ctx->rt;
- ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
-@@ -6785,10 +6841,10 @@ static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
- return 0;
- }
-
--static inline __exception int js_poll_interrupts(JSContext *ctx)
-+static inline warn_unused int js_poll_interrupts(JSContext *ctx)
- {
- if (unlikely(--ctx->interrupt_counter <= 0)) {
-- return __js_poll_interrupts(ctx);
-+ return js_poll_interrupts_impl(ctx);
- } else {
- return 0;
- }
-@@ -7092,9 +7148,9 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
- case JS_TAG_STRING:
- {
- JSString *p1 = JS_VALUE_GET_STRING(obj);
-- if (__JS_AtomIsTaggedInt(prop)) {
-+ if (JS_AtomIsTaggedInt(prop)) {
- uint32_t idx, ch;
-- idx = __JS_AtomToUInt32(prop);
-+ idx = JS_AtomToUInt32(prop);
- if (idx < p1->len) {
- if (p1->is_wide_char)
- ch = p1->u.str16[idx];
-@@ -7144,14 +7200,16 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
- continue;
- }
- } else {
-+ if (JS_IsUndefined(pr->u.value) && ctx->handleUndefined)
-+ ctx->handleUndefined(ctx);
- return JS_DupValue(ctx, pr->u.value);
- }
- }
- if (unlikely(p->is_exotic)) {
- /* exotic behaviors */
- if (p->fast_array) {
-- if (__JS_AtomIsTaggedInt(prop)) {
-- uint32_t idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ uint32_t idx = JS_AtomToUInt32(prop);
- if (idx < p->u.array.count) {
- /* we avoid duplicating the code */
- return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
-@@ -7242,7 +7300,7 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj,
- JS_ThrowTypeErrorNotASymbol(ctx);
- goto fail;
- }
-- prop = js_symbol_to_atom(ctx, (JSValue)name);
-+ prop = js_symbol_to_atom(ctx, name);
- p = JS_VALUE_GET_OBJ(obj);
- prs = find_own_property(&pr, p, prop);
- if (prs) {
-@@ -7273,7 +7331,7 @@ static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj,
- /* safety check */
- if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL))
- return JS_ThrowTypeErrorNotASymbol(ctx);
-- prop = js_symbol_to_atom(ctx, (JSValue)name);
-+ prop = js_symbol_to_atom(ctx, name);
- p = JS_VALUE_GET_OBJ(obj);
- prs = find_own_property(&pr, p, prop);
- if (!prs) {
-@@ -7300,7 +7358,7 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,
- JS_ThrowTypeErrorNotASymbol(ctx);
- goto fail;
- }
-- prop = js_symbol_to_atom(ctx, (JSValue)name);
-+ prop = js_symbol_to_atom(ctx, name);
- p = JS_VALUE_GET_OBJ(obj);
- prs = find_own_property(&pr, p, prop);
- if (!prs) {
-@@ -7390,7 +7448,7 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
- if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
- goto not_obj;
- p = JS_VALUE_GET_OBJ(obj);
-- prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, (JSValue)brand));
-+ prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, brand));
- if (!prs) {
- JS_ThrowTypeError(ctx, "invalid brand on object");
- return -1;
-@@ -7445,7 +7503,7 @@ static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
-
- /* return < 0 in case if exception, 0 if OK. ptab and its atoms must
- be freed by the user. */
--static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
-+static int warn_unused JS_GetOwnPropertyNamesInternal(JSContext *ctx,
- JSPropertyEnum **ptab,
- uint32_t *plen,
- JSObject *p, int flags)
-@@ -7595,7 +7653,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
- len = js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
- add_array_keys:
- for(i = 0; i < len; i++) {
-- tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
-+ tab_atom[num_index].atom = JS_AtomFromUInt32(i);
- if (tab_atom[num_index].atom == JS_ATOM_NULL) {
- js_free_prop_enum(ctx, tab_atom, num_index);
- return -1;
-@@ -7703,9 +7761,9 @@ retry:
- if (p->is_exotic) {
- if (p->fast_array) {
- /* specific case for fast arrays */
-- if (__JS_AtomIsTaggedInt(prop)) {
-+ if (JS_AtomIsTaggedInt(prop)) {
- uint32_t idx;
-- idx = __JS_AtomToUInt32(prop);
-+ idx = JS_AtomToUInt32(prop);
- if (idx < p->u.array.count) {
- if (desc) {
- desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE |
-@@ -7825,7 +7883,7 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)
- if (tag == JS_TAG_INT &&
- (uint32_t)JS_VALUE_GET_INT(val) <= JS_ATOM_MAX_INT) {
- /* fast path for integer values */
-- atom = __JS_AtomFromUInt32(JS_VALUE_GET_INT(val));
-+ atom = JS_AtomFromUInt32(JS_VALUE_GET_INT(val));
- } else if (tag == JS_TAG_SYMBOL) {
- JSAtomStruct *p = JS_VALUE_GET_PTR(val);
- atom = JS_DupAtom(ctx, js_get_atom_index(ctx->rt, p));
-@@ -7856,7 +7914,7 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
- /* fast path for array access */
- p = JS_VALUE_GET_OBJ(this_obj);
- idx = JS_VALUE_GET_INT(prop);
-- len = (uint32_t)p->u.array.count;
-+ len = p->u.array.count;
- if (unlikely(idx >= len))
- goto slow_path;
- switch(p->class_id) {
-@@ -7883,9 +7941,9 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
- return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);
- #endif
- case JS_CLASS_FLOAT32_ARRAY:
-- return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]);
-+ return JS_NewFloat64Impl(ctx, p->u.array.u.float_ptr[idx]);
- case JS_CLASS_FLOAT64_ARRAY:
-- return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]);
-+ return JS_NewFloat64Impl(ctx, p->u.array.u.double_ptr[idx]);
- default:
- goto slow_path;
- }
-@@ -7920,7 +7978,7 @@ static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx,
-
- if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) {
- /* fast path */
-- present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx));
-+ present = JS_HasProperty(ctx, obj, JS_AtomFromUInt32(idx));
- if (present > 0) {
- val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));
- if (unlikely(JS_IsException(val)))
-@@ -8017,7 +8075,7 @@ static JSProperty *add_property(JSContext *ctx,
-
- /* can be called on Array or Arguments objects. return < 0 if
- memory alloc error. */
--static no_inline __exception int convert_fast_array_to_array(JSContext *ctx,
-+static no_inline warn_unused int convert_fast_array_to_array(JSContext *ctx,
- JSObject *p)
- {
- JSProperty *pr;
-@@ -8039,8 +8097,8 @@ static no_inline __exception int convert_fast_array_to_array(JSContext *ctx,
- tab = p->u.array.u.values;
- for(i = 0; i < len; i++) {
- /* add_property cannot fail here but
-- __JS_AtomFromUInt32(i) fails for i > INT32_MAX */
-- pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E);
-+ JS_AtomFromUInt32(i) fails for i > INT32_MAX */
-+ pr = add_property(ctx, p, JS_AtomFromUInt32(i), JS_PROP_C_W_E);
- pr->u.value = *tab++;
- }
- js_free(ctx, p->u.array.u.values);
-@@ -8145,7 +8203,7 @@ static int call_setter(JSContext *ctx, JSObject *setter,
- func = JS_MKPTR(JS_TAG_OBJECT, setter);
- /* Note: the field could be removed in the setter */
- func = JS_DupValue(ctx, func);
-- ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val);
-+ ret = JS_CallFree(ctx, func, this_obj, 1, &val);
- JS_FreeValue(ctx, val);
- if (JS_IsException(ret))
- return -1;
-@@ -8489,8 +8547,8 @@ retry:
- for(;;) {
- if (p1->is_exotic) {
- if (p1->fast_array) {
-- if (__JS_AtomIsTaggedInt(prop)) {
-- uint32_t idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ uint32_t idx = JS_AtomToUInt32(prop);
- if (idx < p1->u.array.count) {
- if (unlikely(p == p1))
- return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags);
-@@ -8610,8 +8668,8 @@ retry:
-
- if (p->is_exotic) {
- if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&
-- __JS_AtomIsTaggedInt(prop)) {
-- uint32_t idx = __JS_AtomToUInt32(prop);
-+ JS_AtomIsTaggedInt(prop)) {
-+ uint32_t idx = JS_AtomToUInt32(prop);
- if (idx == p->u.array.count) {
- /* fast case */
- return add_fast_array_element(ctx, p, val, flags);
-@@ -8662,7 +8720,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
- JSShape *sh1;
-
- /* fast path to add an element to the array */
-- if (idx != (uint32_t)p->u.array.count ||
-+ if (idx != p->u.array.count ||
- !p->fast_array || !p->extensible)
- goto slow_path;
- /* check if prototype chain has a numeric property */
-@@ -8837,8 +8895,8 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p,
- uint32_t idx, len;
-
- if (p->fast_array) {
-- if (__JS_AtomIsTaggedInt(prop)) {
-- idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ idx = JS_AtomToUInt32(prop);
- if (idx == p->u.array.count) {
- if (!p->extensible)
- goto not_extensible;
-@@ -9042,7 +9100,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- return -1;
- }
- /* this code relies on the fact that Uint32 are never allocated */
-- val = (JSValueConst)JS_NewUint32(ctx, array_length);
-+ val = JS_NewUint32(ctx, array_length);
- /* prs may have been modified */
- prs = find_own_property(&pr, p, prop);
- assert(prs != NULL);
-@@ -9214,8 +9272,8 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- uint32_t idx;
- uint32_t prop_flags;
- if (p->class_id == JS_CLASS_ARRAY) {
-- if (__JS_AtomIsTaggedInt(prop)) {
-- idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ idx = JS_AtomToUInt32(prop);
- if (idx < p->u.array.count) {
- prop_flags = get_prop_flags(flags, JS_PROP_C_W_E);
- if (prop_flags != JS_PROP_C_W_E)
-@@ -9238,7 +9296,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- JSValue num;
- int ret;
-
-- if (!__JS_AtomIsTaggedInt(prop)) {
-+ if (!JS_AtomIsTaggedInt(prop)) {
- /* slow path with to handle all numeric indexes */
- num = JS_AtomIsNumericIndex1(ctx, prop);
- if (JS_IsUndefined(num))
-@@ -9259,10 +9317,10 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- if (ret) {
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "negative index in typed array");
- }
-- if (!__JS_AtomIsTaggedInt(prop))
-+ if (!JS_AtomIsTaggedInt(prop))
- goto typed_array_oob;
- }
-- idx = __JS_AtomToUInt32(prop);
-+ idx = JS_AtomToUInt32(prop);
- /* if the typed array is detached, p->u.array.count = 0 */
- if (idx >= typed_array_get_length(ctx, p)) {
- typed_array_oob:
-@@ -9563,6 +9621,11 @@ static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop,
- return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
- return JS_DupValue(ctx, pr->u.value);
- }
-+ if (ctx->scopeLookup) {
-+ struct LookupResult result = ctx->scopeLookup(ctx, prop);
-+ if (result.useResult)
-+ return result.value;
-+ }
- return JS_GetPropertyInternal(ctx, ctx->global_obj, prop,
- ctx->global_obj, throw_ref_error);
- }
-@@ -9658,6 +9721,15 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
- flags = JS_PROP_THROW_STRICT;
- if (is_strict_mode(ctx))
- flags |= JS_PROP_NO_ADD;
-+
-+ if (ctx->scopeLookup) {
-+ struct LookupResult result = ctx->scopeLookup(ctx, prop);
-+ if (result.useResult) {
-+ JS_FreeValue(ctx, result.value);
-+ return JS_SetPropertyInternal(ctx, result.scope, prop, val, flags);
-+ }
-+ }
-+
- return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags);
- }
-
-@@ -9693,7 +9765,7 @@ int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int fl
-
- if ((uint64_t)idx <= JS_ATOM_MAX_INT) {
- /* fast path for fast arrays */
-- return JS_DeleteProperty(ctx, obj, __JS_AtomFromUInt32(idx), flags);
-+ return JS_DeleteProperty(ctx, obj, JS_AtomFromUInt32(idx), flags);
- }
- prop = JS_NewAtomInt64(ctx, idx);
- if (prop == JS_ATOM_NULL)
-@@ -9853,7 +9925,7 @@ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
- break;
- }
- arg = JS_AtomToString(ctx, atom);
-- ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg);
-+ ret = JS_CallFree(ctx, method, val, 1, &arg);
- JS_FreeValue(ctx, arg);
- if (JS_IsException(ret))
- goto exception;
-@@ -10057,7 +10129,7 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
- if (is_neg)
- d = -d;
- } else {
-- d = strtod(p, NULL);
-+ d = safe_strtod(p, NULL);
- }
- return d;
- }
-@@ -10237,7 +10309,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
- } else
- #endif
- {
-- double d = 1.0 / 0.0;
-+ double d = INFINITY;
- if (is_neg)
- d = -d;
- val = JS_NewFloat64(ctx, d);
-@@ -10270,11 +10342,8 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
- ((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) {
- const char *p1 = p + 1;
- is_float = TRUE;
-- if (*p1 == '+') {
-- p1++;
-- } else if (*p1 == '-') {
-+ if (*p1 == '+' || *p1 == '-')
- p1++;
-- }
- if (is_digit((uint8_t)*p1)) {
- p = p1 + 1;
- while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1])))
-@@ -10509,7 +10578,7 @@ static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val)
- return JS_ToNumericFree(ctx, JS_DupValue(ctx, val));
- }
-
--static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,
-+static warn_unused int JS_ToFloat64FreeImpl(JSContext *ctx, double *pres,
- JSValue val)
- {
- double d;
-@@ -10560,7 +10629,7 @@ static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val)
- *pres = JS_VALUE_GET_FLOAT64(val);
- return 0;
- } else {
-- return __JS_ToFloat64Free(ctx, pres, val);
-+ return JS_ToFloat64FreeImpl(ctx, pres, val);
- }
- }
-
-@@ -10575,7 +10644,7 @@ static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val)
- }
-
- /* same as JS_ToNumber() but return 0 in case of NaN/Undefined */
--static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
-+static maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
- {
- uint32_t tag;
- JSValue ret;
-@@ -10990,7 +11059,7 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)
- return 0;
- }
-
--static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
-+static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
- JSValue val, BOOL is_array_ctor)
- {
- uint32_t tag, len;
-@@ -11092,7 +11161,7 @@ int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val)
-
- /* convert a value to a length between 0 and MAX_SAFE_INTEGER.
- return -1 for exception */
--static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
-+static warn_unused int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
- JSValue val)
- {
- int res = JS_ToInt64Clamp(ctx, plen, val, 0, MAX_SAFE_INTEGER, 0);
-@@ -11338,7 +11407,7 @@ static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf,
- n_digits = (n_digits_min + n_digits_max) / 2;
- js_ecvt1(d, n_digits, decpt, sign, buf, FE_TONEAREST,
- buf_tmp, sizeof(buf_tmp));
-- if (strtod(buf_tmp, NULL) == d) {
-+ if (safe_strtod(buf_tmp, NULL) == d) {
- /* no need to keep the trailing zeros */
- while (n_digits >= 2 && buf[n_digits - 1] == '0')
- n_digits--;
-@@ -11700,14 +11769,14 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
- return JS_EXCEPTION;
- }
-
--static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)
-+static maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)
- {
- printf("%14s %4s %4s %14s %10s %s\n",
- "ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");
- }
-
- /* for debug only: dump an object without side effect */
--static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
-+static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
- {
- uint32_t i;
- char atom_buf[ATOM_GET_STR_BUF_SIZE];
-@@ -11784,7 +11853,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
- printf("[autoinit %p %d %p]",
- (void *)js_autoinit_get_realm(pr),
- js_autoinit_get_id(pr),
-- (void *)pr->u.init.opaque);
-+ pr->u.init.opaque);
- } else {
- JS_DumpValueShort(rt, pr->u.value);
- }
-@@ -11813,7 +11882,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
- printf("\n");
- }
-
--static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
-+static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
- {
- if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
- JS_DumpObject(rt, (JSObject *)p);
-@@ -11845,7 +11914,7 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
- }
- }
-
--static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
-+static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
- JSValueConst val)
- {
- uint32_t tag = JS_VALUE_GET_NORM_TAG(val);
-@@ -11950,13 +12019,13 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
- }
- }
-
--static __maybe_unused void JS_DumpValue(JSContext *ctx,
-+static maybe_unused void JS_DumpValue(JSContext *ctx,
- JSValueConst val)
- {
- JS_DumpValueShort(ctx->rt, val);
- }
-
--static __maybe_unused void JS_PrintValue(JSContext *ctx,
-+static maybe_unused void JS_PrintValue(JSContext *ctx,
- const char *str,
- JSValueConst val)
- {
-@@ -12439,7 +12508,7 @@ static JSObject *find_binary_op(JSBinaryOperatorDef *def,
-
- /* return -1 if exception, 0 if no operator overloading, 1 if
- overloaded operator called */
--static __exception int js_call_binary_op_fallback(JSContext *ctx,
-+static WARN_UNUSED int js_call_binary_op_fallback(JSContext *ctx,
- JSValue *pret,
- JSValueConst op1,
- JSValueConst op2,
-@@ -12568,7 +12637,7 @@ static __exception int js_call_binary_op_fallback(JSContext *ctx,
-
- /* try to call the operation on the operatorSet field of 'obj'. Only
- used for "/" and "**" on the BigInt prototype in math mode */
--static __exception int js_call_binary_op_simple(JSContext *ctx,
-+static WARN_UNUSED int js_call_binary_op_simple(JSContext *ctx,
- JSValue *pret,
- JSValueConst obj,
- JSValueConst op1,
-@@ -12625,7 +12694,7 @@ static __exception int js_call_binary_op_simple(JSContext *ctx,
-
- /* return -1 if exception, 0 if no operator overloading, 1 if
- overloaded operator called */
--static __exception int js_call_unary_op_fallback(JSContext *ctx,
-+static WARN_UNUSED int js_call_unary_op_fallback(JSContext *ctx,
- JSValue *pret,
- JSValueConst op1,
- OPCodeEnum op)
-@@ -12835,7 +12904,7 @@ static int js_unary_arith_bigdecimal(JSContext *ctx,
- return 0;
- }
-
--static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
-+static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
- {
-@@ -12933,7 +13002,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
- return -1;
- }
-
--static __exception int js_post_inc_slow(JSContext *ctx,
-+static WARN_UNUSED int js_post_inc_slow(JSContext *ctx,
- JSValue *sp, OPCodeEnum op)
- {
- JSValue op1;
-@@ -13288,7 +13357,7 @@ static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op,
- return -1;
- }
-
--static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
-+static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
- OPCodeEnum op)
- {
- JSValue op1, op2, res;
-@@ -13452,7 +13521,7 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
- return -1;
- }
-
--static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
-+static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2, res;
- uint32_t tag1, tag2;
-@@ -13566,7 +13635,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
- return -1;
- }
-
--static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
-+static no_inline WARN_UNUSED int js_binary_logic_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
- {
-@@ -13916,7 +13985,7 @@ static BOOL tag_is_number(uint32_t tag)
- tag == JS_TAG_BIG_DECIMAL);
- }
-
--static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
-+static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
- BOOL is_neq)
- {
- JSValue op1, op2, ret;
-@@ -14192,7 +14261,7 @@ int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
- return -1;
- }
-
--static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
-+static no_inline warn_unused int js_unary_arith_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
- {
-@@ -14224,7 +14293,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
- }
-
- /* specific case necessary for correct return value semantics */
--static __exception int js_post_inc_slow(JSContext *ctx,
-+static warn_unused int js_post_inc_slow(JSContext *ctx,
- JSValue *sp, OPCodeEnum op)
- {
- JSValue op1;
-@@ -14241,7 +14310,7 @@ static __exception int js_post_inc_slow(JSContext *ctx,
- return 0;
- }
-
--static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
-+static no_inline warn_unused int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
- OPCodeEnum op)
- {
- JSValue op1, op2;
-@@ -14283,7 +14352,7 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
- return -1;
- }
-
--static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
-+static no_inline warn_unused int js_add_slow(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2;
- uint32_t tag1, tag2;
-@@ -14331,7 +14400,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
- return -1;
- }
-
--static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
-+static no_inline warn_unused int js_binary_logic_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
- {
-@@ -14458,7 +14527,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
- return -1;
- }
-
--static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
-+static no_inline warn_unused int js_eq_slow(JSContext *ctx, JSValue *sp,
- BOOL is_neq)
- {
- JSValue op1, op2;
-@@ -14744,7 +14813,7 @@ static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp,
- return 0;
- }
-
--static __exception int js_operator_in(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_operator_in(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2;
- JSAtom atom;
-@@ -14770,7 +14839,7 @@ static __exception int js_operator_in(JSContext *ctx, JSValue *sp)
- return 0;
- }
-
--static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
-+static warn_unused int js_has_unscopable(JSContext *ctx, JSValueConst obj,
- JSAtom atom)
- {
- JSValue arr, val;
-@@ -14788,7 +14857,7 @@ static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
- return ret;
- }
-
--static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_operator_instanceof(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2;
- BOOL ret;
-@@ -14804,7 +14873,7 @@ static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)
- return 0;
- }
-
--static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
-+static warn_unused int js_operator_typeof(JSContext *ctx, JSValueConst op1)
- {
- JSAtom atom;
- uint32_t tag;
-@@ -14861,7 +14930,7 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
- return atom;
- }
-
--static __exception int js_operator_delete(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_operator_delete(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2;
- JSAtom atom;
-@@ -15016,7 +15085,7 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
- var_ref = get_var_ref(ctx, sf, i, TRUE);
- if (!var_ref)
- goto fail;
-- pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
-+ pr = add_property(ctx, p, JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
- if (!pr) {
- free_var_ref(ctx->rt, var_ref);
- goto fail;
-@@ -15188,7 +15257,7 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
- }
-
- /* obj -> enum_obj */
--static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_for_in_start(JSContext *ctx, JSValue *sp)
- {
- sp[-1] = build_for_in_iterator(ctx, sp[-1]);
- if (JS_IsException(sp[-1]))
-@@ -15197,7 +15266,7 @@ static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
- }
-
- /* enum_obj -> enum_obj value done */
--static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_for_in_next(JSContext *ctx, JSValue *sp)
- {
- JSValueConst enum_obj;
- JSObject *p;
-@@ -15218,7 +15287,7 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
- if (it->is_array) {
- if (it->idx >= it->array_length)
- goto done;
-- prop = __JS_AtomFromUInt32(it->idx);
-+ prop = JS_AtomFromUInt32(it->idx);
- it->idx++;
- } else {
- JSShape *sh = p->shape;
-@@ -15411,7 +15480,7 @@ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,
- }
-
- /* obj -> enum_rec (3 slots) */
--static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,
-+static warn_unused int js_for_of_start(JSContext *ctx, JSValue *sp,
- BOOL is_async)
- {
- JSValue op1, obj, method;
-@@ -15432,7 +15501,7 @@ static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,
- objs. If 'done' is true or in case of exception, 'enum_rec' is set
- to undefined. If 'done' is true, 'value' is always set to
- undefined. */
--static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
-+static warn_unused int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
- {
- JSValue value = JS_UNDEFINED;
- int done = 1;
-@@ -15478,7 +15547,7 @@ static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,
- return JS_EXCEPTION;
- }
-
--static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
- {
- JSValue obj, value;
- BOOL done;
-@@ -15554,7 +15623,7 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
- return FALSE;
- }
-
--static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_append_enumerate(JSContext *ctx, JSValue *sp)
- {
- JSValue iterator, enumobj, method, value;
- int is_array_iterator;
-@@ -15634,7 +15703,7 @@ exception:
- return -1;
- }
-
--static __exception int JS_CopyDataProperties(JSContext *ctx,
-+static warn_unused int JS_CopyDataProperties(JSContext *ctx,
- JSValueConst target,
- JSValueConst source,
- JSValueConst excluded,
-@@ -16043,7 +16112,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
- #else
- sf->js_mode = 0;
- #endif
-- sf->cur_func = (JSValue)func_obj;
-+ sf->cur_func = func_obj;
- sf->arg_count = argc;
- arg_buf = argv;
-
-@@ -16056,7 +16125,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
- arg_buf[i] = JS_UNDEFINED;
- sf->arg_count = arg_count;
- }
-- sf->arg_buf = (JSValue*)arg_buf;
-+ sf->arg_buf = arg_buf;
-
- func = p->u.cfunc.c_function;
- switch(cproto) {
-@@ -16226,7 +16295,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- #include "quickjs-opcode.h"
- [ OP_COUNT ... 255 ] = &&case_default
- };
--#define SWITCH(pc) goto *dispatch_table[opcode = *pc++];
-+#define SWITCH(pc) goto *dispatch_table[opcode = *(pc)++];
- #define CASE(op) case_ ## op
- #define DEFAULT case_default
- #define BREAK SWITCH(pc)
-@@ -16269,7 +16338,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- return JS_ThrowTypeError(caller_ctx, "not a function");
- }
- return call_func(caller_ctx, func_obj, this_obj, argc,
-- (JSValueConst *)argv, flags);
-+ argv, flags);
- }
- b = p->u.func.function_bytecode;
-
-@@ -16287,7 +16356,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- sf->js_mode = b->js_mode;
- arg_buf = argv;
- sf->arg_count = argc;
-- sf->cur_func = (JSValue)func_obj;
-+ sf->cur_func = func_obj;
- init_list_head(&sf->var_ref_list);
- var_refs = p->u.func.var_refs;
-
-@@ -16315,6 +16384,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- rt->current_stack_frame = sf;
- ctx = b->realm; /* set the current realm */
-
-+ if (ctx->handleFunctionEntered)
-+ ctx->handleFunctionEntered(ctx, this_obj);
-+
- restart:
- for(;;) {
- int call_argc;
-@@ -16420,12 +16492,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- int arg = *pc++;
- switch(arg) {
- case OP_SPECIAL_OBJECT_ARGUMENTS:
-- *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv);
-+ *sp++ = js_build_arguments(ctx, argc, argv);
- if (unlikely(JS_IsException(sp[-1])))
- goto exception;
- break;
- case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS:
-- *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv,
-+ *sp++ = js_build_mapped_arguments(ctx, argc, argv,
- sf, min_int(argc, b->arg_count));
- if (unlikely(JS_IsException(sp[-1])))
- goto exception;
-@@ -16465,7 +16537,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- {
- int first = get_u16(pc);
- pc += 2;
-- *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv);
-+ *sp++ = js_build_rest(ctx, first, argc, argv);
- if (unlikely(JS_IsException(sp[-1])))
- goto exception;
- }
-@@ -16698,7 +16770,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- goto exception;
- call_argv = sp - call_argc;
- for(i = 0; i < call_argc; i++) {
-- ret = JS_DefinePropertyValue(ctx, ret_val, __JS_AtomFromUInt32(i), call_argv[i],
-+ ret = JS_DefinePropertyValue(ctx, ret_val, JS_AtomFromUInt32(i), call_argv[i],
- JS_PROP_C_W_E | JS_PROP_THROW);
- call_argv[i] = JS_UNDEFINED;
- if (ret < 0) {
-@@ -16717,7 +16789,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- magic = get_u16(pc);
- pc += 2;
-
-- ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic);
-+ ret_val = js_function_apply(ctx, sp[-3], 2, &sp[-2], magic);
- if (unlikely(JS_IsException(ret_val)))
- goto exception;
- JS_FreeValue(ctx, sp[-3]);
-@@ -16850,7 +16922,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- JS_EVAL_TYPE_DIRECT, scope_idx);
- } else {
- ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len,
-- (JSValueConst *)tab);
-+ tab);
- }
- free_arg_list(ctx, tab, len);
- if (unlikely(JS_IsException(ret_val)))
-@@ -17474,7 +17546,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- {
- JSValue ret;
- ret = JS_Call(ctx, sp[-3], sp[-4],
-- 1, (JSValueConst *)(sp - 1));
-+ 1, (sp - 1));
- if (JS_IsException(ret))
- goto exception;
- JS_FreeValue(ctx, sp[-1]);
-@@ -17502,7 +17574,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- 0, NULL);
- } else {
- ret = JS_CallFree(ctx, method, sp[-4],
-- 1, (JSValueConst *)(sp - 1));
-+ 1, (sp - 1));
- }
- if (JS_IsException(ret))
- goto exception;
-@@ -17925,7 +17997,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- sp[-2] = JS_NewInt32(ctx, r);
- sp--;
- } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
-- sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) +
-+ sp[-2] = JS_NewFloat64Impl(ctx, JS_VALUE_GET_FLOAT64(op1) +
- JS_VALUE_GET_FLOAT64(op2));
- sp--;
- } else {
-@@ -17990,7 +18062,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- sp[-2] = JS_NewInt32(ctx, r);
- sp--;
- } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
-- sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) -
-+ sp[-2] = JS_NewFloat64Impl(ctx, JS_VALUE_GET_FLOAT64(op1) -
- JS_VALUE_GET_FLOAT64(op2));
- sp--;
- } else {
-@@ -18033,7 +18105,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- #endif
- d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);
- mul_fp_res:
-- sp[-2] = __JS_NewFloat64(ctx, d);
-+ sp[-2] = JS_NewFloat64Impl(ctx, d);
- sp--;
- } else {
- goto binary_arith_slow;
-@@ -18125,7 +18197,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- } else if (JS_TAG_IS_FLOAT64(tag)) {
- d = -JS_VALUE_GET_FLOAT64(op1);
- neg_fp_res:
-- sp[-1] = __JS_NewFloat64(ctx, d);
-+ sp[-1] = JS_NewFloat64Impl(ctx, d);
- } else {
- if (js_unary_arith_slow(ctx, sp, opcode))
- goto exception;
-@@ -18659,6 +18731,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- }
- }
- exception:
-+ if (JS_IsString(rt->current_exception)) {
-+ JSValue error_obj = JS_NewError(ctx);
-+ JSAtom msgProp = JS_NewAtom(ctx, "message");
-+ JS_DefinePropertyValue(ctx, error_obj, msgProp, rt->current_exception, 0);
-+ rt->current_exception = error_obj;
-+ JS_FreeAtom(ctx, msgProp);
-+ }
- if (is_backtrace_needed(ctx, rt->current_exception)) {
- /* add the backtrace information now (it is not done
- before if the exception happens in a bytecode
-@@ -18706,6 +18785,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- }
- }
- rt->current_stack_frame = sf->prev_frame;
-+ if (ctx->handleFunctionExited)
-+ ctx->handleFunctionExited(ctx);
- return ret_val;
- }
-
-@@ -18713,14 +18794,14 @@ JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
- {
- return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
-- argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
-+ argc, argv, JS_CALL_FLAG_COPY_ARGV);
- }
-
- static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
- {
- JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
-- argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
-+ argc, argv, JS_CALL_FLAG_COPY_ARGV);
- JS_FreeValue(ctx, func_obj);
- return res;
- }
-@@ -18825,7 +18906,7 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx,
- return JS_ThrowTypeError(ctx, "not a function");
- }
- return call_func(ctx, func_obj, new_target, argc,
-- (JSValueConst *)argv, flags);
-+ argv, flags);
- }
-
- b = p->u.func.function_bytecode;
-@@ -18854,7 +18935,7 @@ JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
- int argc, JSValueConst *argv)
- {
- return JS_CallConstructorInternal(ctx, func_obj, new_target,
-- argc, (JSValue *)argv,
-+ argc, argv,
- JS_CALL_FLAG_COPY_ARGV);
- }
-
-@@ -18862,7 +18943,7 @@ JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
- int argc, JSValueConst *argv)
- {
- return JS_CallConstructorInternal(ctx, func_obj, func_obj,
-- argc, (JSValue *)argv,
-+ argc, argv,
- JS_CALL_FLAG_COPY_ARGV);
- }
-
-@@ -18885,7 +18966,7 @@ static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
- }
-
- /* JSAsyncFunctionState (used by generator and async functions) */
--static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
-+static warn_unused int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
- JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
- {
-@@ -19227,7 +19308,7 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
- fail:
- error = JS_GetException(ctx);
- ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
-- 1, (JSValueConst *)&error);
-+ 1, &error);
- JS_FreeValue(ctx, error);
- js_async_function_terminate(ctx->rt, s);
- JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
-@@ -19238,7 +19319,7 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
- if (JS_IsUndefined(func_ret)) {
- /* function returned */
- ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
-- 1, (JSValueConst *)&value);
-+ 1, &value);
- JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, value);
- js_async_function_terminate(ctx->rt, s);
-@@ -19249,7 +19330,7 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
- /* await */
- JS_FreeValue(ctx, func_ret); /* not used */
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
-- 1, (JSValueConst *)&value, 0);
-+ 1, &value, 0);
- JS_FreeValue(ctx, value);
- if (JS_IsException(promise))
- goto fail;
-@@ -19531,7 +19612,7 @@ static int js_async_generator_completed_return(JSContext *ctx,
- int res;
-
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
-- 1, (JSValueConst *)&value, 0);
-+ 1, &value, 0);
- if (JS_IsException(promise))
- return -1;
- if (js_async_generator_resolve_function_create(ctx,
-@@ -19703,7 +19784,7 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,
- JS_ThrowTypeError(ctx, "not an AsyncGenerator object");
- err = JS_GetException(ctx);
- res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
-- 1, (JSValueConst *)&err);
-+ 1, &err);
- JS_FreeValue(ctx, err);
- JS_FreeValue(ctx, res2);
- JS_FreeValue(ctx, resolving_funcs[0]);
-@@ -20138,7 +20219,7 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {
- #define short_opcode_info(op) opcode_info[op]
- #endif
-
--static __exception int next_token(JSParseState *s);
-+static warn_unused int next_token(JSParseState *s);
-
- static void free_token(JSParseState *s, JSToken *token)
- {
-@@ -20169,7 +20250,7 @@ static void free_token(JSParseState *s, JSToken *token)
- }
- }
-
--static void __attribute((unused)) dump_token(JSParseState *s,
-+static void maybe_unused dump_token(JSParseState *s,
- const JSToken *token)
- {
- switch(token->val) {
-@@ -20230,7 +20311,7 @@ static void __attribute((unused)) dump_token(JSParseState *s,
- }
- }
-
--int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const char *fmt, ...)
-+int FORMAT_ATTR(2, 3) js_parse_error(JSParseState *s, const char *fmt, ...)
- {
- JSContext *ctx = s->ctx;
- va_list ap;
-@@ -20276,7 +20357,7 @@ static int js_parse_error_reserved_identifier(JSParseState *s)
- s->token.u.ident.atom));
- }
-
--static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
-+static warn_unused int js_parse_template_part(JSParseState *s, const uint8_t *p)
- {
- uint32_t c;
- StringBuffer b_s, *b = &b_s;
-@@ -20337,7 +20418,7 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
- return -1;
- }
-
--static __exception int js_parse_string(JSParseState *s, int sep,
-+static warn_unused int js_parse_string(JSParseState *s, int sep,
- BOOL do_throw, const uint8_t *p,
- JSToken *token, const uint8_t **pp)
- {
-@@ -20482,7 +20563,7 @@ static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) {
- !s->token.u.ident.has_escape;
- }
-
--static __exception int js_parse_regexp(JSParseState *s)
-+static warn_unused int js_parse_regexp(JSParseState *s)
- {
- const uint8_t *p;
- BOOL in_class;
-@@ -20580,8 +20661,8 @@ static __exception int js_parse_regexp(JSParseState *s)
- return -1;
- }
-
--static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
-- char *static_buf)
-+static warn_unused int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
-+ const char *static_buf)
- {
- char *buf, *new_buf;
- size_t size, new_size;
-@@ -20656,7 +20737,7 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
- }
-
-
--static __exception int next_token(JSParseState *s)
-+static warn_unused int next_token(JSParseState *s)
- {
- const uint8_t *p;
- int c;
-@@ -21204,7 +21285,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
- return atom;
- }
-
--static __exception int json_next_token(JSParseState *s)
-+static warn_unused int json_next_token(JSParseState *s)
- {
- const uint8_t *p;
- int c;
-@@ -21644,7 +21725,7 @@ static int cpool_add(JSParseState *s, JSValue val)
- return fd->cpool_count - 1;
- }
-
--static __exception int emit_push_const(JSParseState *s, JSValueConst val,
-+static warn_unused int emit_push_const(JSParseState *s, JSValueConst val,
- BOOL as_atom)
- {
- int idx;
-@@ -21654,7 +21735,7 @@ static __exception int emit_push_const(JSParseState *s, JSValueConst val,
- /* warning: JS_NewAtomStr frees the string value */
- JS_DupValue(s->ctx, val);
- atom = JS_NewAtomStr(s->ctx, JS_VALUE_GET_STRING(val));
-- if (atom != JS_ATOM_NULL && !__JS_AtomIsTaggedInt(atom)) {
-+ if (atom != JS_ATOM_NULL && !JS_AtomIsTaggedInt(atom)) {
- emit_op(s, OP_push_atom_value);
- emit_u32(s, atom);
- return 0;
-@@ -22118,14 +22199,14 @@ static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,
- return idx;
- }
-
--static __exception int js_parse_expr(JSParseState *s);
--static __exception int js_parse_function_decl(JSParseState *s,
-+static warn_unused int js_parse_expr(JSParseState *s);
-+static warn_unused int js_parse_function_decl(JSParseState *s,
- JSParseFunctionEnum func_type,
- JSFunctionKindEnum func_kind,
- JSAtom func_name, const uint8_t *ptr,
- int start_line);
- static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s);
--static __exception int js_parse_function_decl2(JSParseState *s,
-+static warn_unused int js_parse_function_decl2(JSParseState *s,
- JSParseFunctionEnum func_type,
- JSFunctionKindEnum func_kind,
- JSAtom func_name,
-@@ -22133,9 +22214,9 @@ static __exception int js_parse_function_decl2(JSParseState *s,
- int function_line_num,
- JSParseExportEnum export_flag,
- JSFunctionDef **pfd);
--static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags);
--static __exception int js_parse_assign_expr(JSParseState *s);
--static __exception int js_parse_unary(JSParseState *s, int parse_flags);
-+static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags);
-+static warn_unused int js_parse_assign_expr(JSParseState *s);
-+static warn_unused int js_parse_unary(JSParseState *s, int parse_flags);
- static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
- JSAtom label_name,
- int label_break, int label_cont,
-@@ -22162,7 +22243,7 @@ static int seal_template_obj(JSContext *ctx, JSValueConst obj)
- return 0;
- }
-
--static __exception int js_parse_template(JSParseState *s, int call, int *argc)
-+static warn_unused int js_parse_template(JSParseState *s, int call, int *argc)
- {
- JSContext *ctx = s->ctx;
- JSValue raw_array, template_object;
-@@ -22293,7 +22374,7 @@ static BOOL token_is_ident(int tok)
- }
-
- /* if the property is an expression, name = JS_ATOM_NULL */
--static int __exception js_parse_property_name(JSParseState *s,
-+static int warn_unused js_parse_property_name(JSParseState *s,
- JSAtom *pname,
- BOOL allow_method, BOOL allow_var,
- BOOL allow_private)
-@@ -22435,7 +22516,7 @@ static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)
- return 0;
- }
-
--static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
-+static warn_unused int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
- {
- s->token.line_num = sp->last_line_num;
- s->line_num = sp->line_num;
-@@ -22480,7 +22561,8 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_
- size_t level = 0;
- JSParsePos pos;
- int last_tok, tok = TOK_EOF;
-- int c, tok_len, bits = 0;
-+ int tok_len, bits = 0;
-+ char c;
-
- /* protect from underflow */
- state[level++] = 0;
-@@ -22640,7 +22722,7 @@ static void set_object_name_computed(JSParseState *s)
- }
- }
-
--static __exception int js_parse_object_literal(JSParseState *s)
-+static warn_unused int js_parse_object_literal(JSParseState *s)
- {
- JSAtom name = JS_ATOM_NULL;
- const uint8_t *start_ptr;
-@@ -22765,15 +22847,15 @@ static __exception int js_parse_object_literal(JSParseState *s)
- /* forbid the exponentiation operator in js_parse_unary() */
- #define PF_POW_FORBIDDEN (1 << 4)
-
--static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);
-+static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags);
-
--static __exception int js_parse_left_hand_side_expr(JSParseState *s)
-+static warn_unused int js_parse_left_hand_side_expr(JSParseState *s)
- {
- return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
- }
-
- /* XXX: could generate specific bytecode */
--static __exception int js_parse_class_default_ctor(JSParseState *s,
-+static warn_unused int js_parse_class_default_ctor(JSParseState *s,
- BOOL has_super,
- JSFunctionDef **pfd)
- {
-@@ -22864,7 +22946,7 @@ typedef struct {
- int brand_push_pos;
- } ClassFieldsDef;
-
--static __exception int emit_class_init_start(JSParseState *s,
-+static warn_unused int emit_class_init_start(JSParseState *s,
- ClassFieldsDef *cf)
- {
- int label_add_brand;
-@@ -22897,7 +22979,7 @@ static __exception int emit_class_init_start(JSParseState *s,
- return 0;
- }
-
--static __exception int add_brand(JSParseState *s, ClassFieldsDef *cf)
-+static warn_unused int add_brand(JSParseState *s, ClassFieldsDef *cf)
- {
- if (!cf->has_brand) {
- /* define the brand field in 'this' of the initializer */
-@@ -22929,7 +23011,7 @@ static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)
- }
-
-
--static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
-+static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
- JSParseExportEnum export_flag)
- {
- JSContext *ctx = s->ctx;
-@@ -23374,7 +23456,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
- return -1;
- }
-
--static __exception int js_parse_array_literal(JSParseState *s)
-+static warn_unused int js_parse_array_literal(JSParseState *s)
- {
- uint32_t idx;
- BOOL need_length;
-@@ -23410,7 +23492,7 @@ static __exception int js_parse_array_literal(JSParseState *s)
- if (js_parse_assign_expr(s))
- return -1;
- emit_op(s, OP_define_field);
-- emit_u32(s, __JS_AtomFromUInt32(idx));
-+ emit_u32(s, JS_AtomFromUInt32(idx));
- need_length = FALSE;
- }
- idx++;
-@@ -23520,7 +23602,7 @@ static BOOL has_with_scope(JSFunctionDef *s, int scope_level)
- return FALSE;
- }
-
--static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
-+static warn_unused int get_lvalue(JSParseState *s, int *popcode, int *pscope,
- JSAtom *pname, int *plabel, int *pdepth, BOOL keep,
- int tok)
- {
-@@ -23760,7 +23842,7 @@ static void put_lvalue(JSParseState *s, int opcode, int scope,
- }
- }
-
--static __exception int js_parse_expr_paren(JSParseState *s)
-+static warn_unused int js_parse_expr_paren(JSParseState *s)
- {
- if (js_parse_expect(s, '('))
- return -1;
-@@ -23778,7 +23860,7 @@ static int js_unsupported_keyword(JSParseState *s, JSAtom atom)
- JS_AtomGetStr(s->ctx, buf, sizeof(buf), atom));
- }
-
--static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
-+static warn_unused int js_define_var(JSParseState *s, JSAtom name, int tok)
- {
- JSFunctionDef *fd = s->cur_func;
- JSVarDefEnum var_def_type;
-@@ -24327,7 +24409,7 @@ static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,
- }
-
- /* allowed parse_flags: PF_POSTFIX_CALL, PF_ARROW_FUNC */
--static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
- {
- FuncCallType call_type;
- int optional_chaining_label;
-@@ -24963,17 +25045,16 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
- return 0;
- }
-
--static __exception int js_parse_delete(JSParseState *s)
-+static warn_unused int js_parse_delete(JSParseState *s)
- {
- JSFunctionDef *fd = s->cur_func;
- JSAtom name;
-- int opcode;
-
- if (next_token(s))
- return -1;
- if (js_parse_unary(s, PF_POW_FORBIDDEN))
- return -1;
-- switch(opcode = get_prev_opcode(fd)) {
-+ switch (get_prev_opcode(fd)) {
- case OP_get_field:
- {
- JSValue val;
-@@ -25024,7 +25105,7 @@ static __exception int js_parse_delete(JSParseState *s)
- }
-
- /* allowed parse_flags: PF_ARROW_FUNC, PF_POW_ALLOWED, PF_POW_FORBIDDEN */
--static __exception int js_parse_unary(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_unary(JSParseState *s, int parse_flags)
- {
- int op;
-
-@@ -25172,7 +25253,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
- }
-
- /* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
--static __exception int js_parse_expr_binary(JSParseState *s, int level,
-+static warn_unused int js_parse_expr_binary(JSParseState *s, int level,
- int parse_flags)
- {
- int op, opcode;
-@@ -25319,7 +25400,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
- }
-
- /* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
--static __exception int js_parse_logical_and_or(JSParseState *s, int op,
-+static warn_unused int js_parse_logical_and_or(JSParseState *s, int op,
- int parse_flags)
- {
- int label1;
-@@ -25361,7 +25442,7 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op,
- return 0;
- }
-
--static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
- {
- int label1;
-
-@@ -25389,7 +25470,7 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
- }
-
- /* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
--static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_cond_expr(JSParseState *s, int parse_flags)
- {
- int label1, label2;
-
-@@ -25420,7 +25501,7 @@ static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
- static void emit_return(JSParseState *s, BOOL hasval);
-
- /* allowed parse_flags: PF_IN_ACCEPTED */
--static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
- {
- int opcode, op, scope;
- JSAtom name0 = JS_ATOM_NULL;
-@@ -25666,13 +25747,13 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
- return 0;
- }
-
--static __exception int js_parse_assign_expr(JSParseState *s)
-+static warn_unused int js_parse_assign_expr(JSParseState *s)
- {
- return js_parse_assign_expr2(s, PF_IN_ACCEPTED);
- }
-
- /* allowed parse_flags: PF_IN_ACCEPTED */
--static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_expr2(JSParseState *s, int parse_flags)
- {
- BOOL comma = FALSE;
- for(;;) {
-@@ -25696,7 +25777,7 @@ static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
- return 0;
- }
-
--static __exception int js_parse_expr(JSParseState *s)
-+static warn_unused int js_parse_expr(JSParseState *s)
- {
- return js_parse_expr2(s, PF_IN_ACCEPTED);
- }
-@@ -25724,7 +25805,7 @@ static void pop_break_entry(JSFunctionDef *fd)
- fd->top_break = be->prev;
- }
-
--static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)
-+static warn_unused int emit_break(JSParseState *s, JSAtom name, int is_cont)
- {
- BlockEnv *top;
- int i, scope_level;
-@@ -25873,15 +25954,15 @@ static void emit_return(JSParseState *s, BOOL hasval)
- #define DECL_MASK_OTHER (1 << 2) /* all other declarations */
- #define DECL_MASK_ALL (DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL | DECL_MASK_OTHER)
-
--static __exception int js_parse_statement_or_decl(JSParseState *s,
-+static warn_unused int js_parse_statement_or_decl(JSParseState *s,
- int decl_mask);
-
--static __exception int js_parse_statement(JSParseState *s)
-+static warn_unused int js_parse_statement(JSParseState *s)
- {
- return js_parse_statement_or_decl(s, 0);
- }
-
--static __exception int js_parse_block(JSParseState *s)
-+static warn_unused int js_parse_block(JSParseState *s)
- {
- if (js_parse_expect(s, '{'))
- return -1;
-@@ -25901,7 +25982,7 @@ static __exception int js_parse_block(JSParseState *s)
- }
-
- /* allowed parse_flags: PF_IN_ACCEPTED */
--static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
-+static warn_unused int js_parse_var(JSParseState *s, int parse_flags, int tok,
- BOOL export_flag)
- {
- JSContext *ctx = s->ctx;
-@@ -26052,7 +26133,7 @@ static int is_let(JSParseState *s, int decl_mask)
-
- /* XXX: handle IteratorClose when exiting the loop before the
- enumeration is done */
--static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
-+static warn_unused int js_parse_for_in_of(JSParseState *s, int label_name,
- BOOL is_async)
- {
- JSContext *ctx = s->ctx;
-@@ -26283,7 +26364,7 @@ static void set_eval_ret_undefined(JSParseState *s)
- }
- }
-
--static __exception int js_parse_statement_or_decl(JSParseState *s,
-+static warn_unused int js_parse_statement_or_decl(JSParseState *s,
- int decl_mask)
- {
- JSContext *ctx = s->ctx;
-@@ -27603,7 +27684,7 @@ static int find_exported_name(GetExportNamesState *s, JSAtom name)
- return -1;
- }
-
--static __exception int get_exported_names(JSContext *ctx,
-+static warn_unused int get_exported_names(JSContext *ctx,
- GetExportNamesState *s,
- JSModuleDef *m, BOOL from_star)
- {
-@@ -27744,7 +27825,6 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
- en->u.var_ref = res_me->u.local.var_ref;
- } else {
- JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj);
-- p1 = JS_VALUE_GET_OBJ(res_m->func_obj);
- en->u.var_ref = p1->u.func.var_refs[res_me->u.local.var_idx];
- }
- }
-@@ -28237,7 +28317,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
- goto exception;
-
- ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
-- 1, (JSValueConst *)&ns);
-+ 1, &ns);
- JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, ns);
- JS_FreeCString(ctx, basename);
-@@ -28246,7 +28326,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
-
- err = JS_GetException(ctx);
- ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
-- 1, (JSValueConst *)&err);
-+ 1, &err);
- JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, err);
- JS_FreeCString(ctx, basename);
-@@ -28343,7 +28423,7 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
- return ret_val;
- }
-
--static __exception JSAtom js_parse_from_clause(JSParseState *s)
-+static warn_unused JSAtom js_parse_from_clause(JSParseState *s)
- {
- JSAtom module_name;
- if (!token_is_pseudo_keyword(s, JS_ATOM_from)) {
-@@ -28366,7 +28446,7 @@ static __exception JSAtom js_parse_from_clause(JSParseState *s)
- return module_name;
- }
-
--static __exception int js_parse_export(JSParseState *s)
-+static warn_unused int js_parse_export(JSParseState *s)
- {
- JSContext *ctx = s->ctx;
- JSModuleDef *m = s->cur_func->module;
-@@ -28569,7 +28649,7 @@ static int add_import(JSParseState *s, JSModuleDef *m,
- return 0;
- }
-
--static __exception int js_parse_import(JSParseState *s)
-+static warn_unused int js_parse_import(JSParseState *s)
- {
- JSContext *ctx = s->ctx;
- JSModuleDef *m = s->cur_func->module;
-@@ -28684,7 +28764,7 @@ static __exception int js_parse_import(JSParseState *s)
- return js_parse_expect_semi(s);
- }
-
--static __exception int js_parse_source_element(JSParseState *s)
-+static warn_unused int js_parse_source_element(JSParseState *s)
- {
- JSFunctionDef *fd = s->cur_func;
- int tok;
-@@ -29608,8 +29688,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
- }
- var_idx = idx;
- break;
-- } else
-- if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
-+ } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
- dbuf_putc(bc, OP_get_loc);
- dbuf_put_u16(bc, idx);
- var_object_test(ctx, s, var_name, op, bc, &label_done, 1);
-@@ -30359,7 +30438,7 @@ static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv,
-
- /* for direct eval compilation: add references to the variables of the
- calling function */
--static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
-+static warn_unused int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
- JSFunctionBytecode *b, int scope_idx)
- {
- int i, count;
-@@ -30779,7 +30858,7 @@ static int get_label_pos(JSFunctionDef *s, int label)
-
- /* convert global variable accesses to local variables or closure
- variables when necessary */
--static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
-+static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
- {
- int pos, pos_next, bc_len, op, len, i, idx, line_num;
- uint8_t *bc_buf;
-@@ -31343,7 +31422,7 @@ static void put_short_code(DynBuf *bc_out, int op, int idx)
- }
-
- /* peephole optimizations and resolve goto/labels */
--static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
-+static warn_unused int resolve_labels(JSContext *ctx, JSFunctionDef *s)
- {
- int pos, pos_next, bc_len, op, op1, len, i, line_num;
- const uint8_t *bc_buf;
-@@ -32152,8 +32231,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
- bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false);
- }
- goto shrink;
-- } else
-- if (diff == (int16_t)diff && op == OP_goto) {
-+ } else if (diff == (int16_t)diff && op == OP_goto) {
- //put_u16(bc_out.buf + pos, diff);
- jp->size = 2;
- delta = 2;
-@@ -32236,7 +32314,7 @@ typedef struct StackSizeState {
- } StackSizeState;
-
- /* 'op' is only used for error indication */
--static __exception int ss_check(JSContext *ctx, StackSizeState *s,
-+static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
- int pos, int op, int stack_len)
- {
- if ((unsigned)pos >= s->bc_len) {
-@@ -32272,7 +32350,7 @@ static __exception int ss_check(JSContext *ctx, StackSizeState *s,
- return 0;
- }
-
--static __exception int compute_stack_size(JSContext *ctx,
-+static warn_unused int compute_stack_size(JSContext *ctx,
- JSFunctionDef *fd,
- int *pstack_size)
- {
-@@ -32593,7 +32671,9 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
- }
- } else {
- b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
-+ if (fd->arg_count)
- memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
-+ if (fd->var_count)
- memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
- }
- b->var_count = fd->var_count;
-@@ -32721,7 +32801,7 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)
- }
- }
-
--static __exception int js_parse_directives(JSParseState *s)
-+static warn_unused int js_parse_directives(JSParseState *s)
- {
- char str[20];
- JSParsePos pos;
-@@ -32895,7 +32975,7 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s)
-
- /* func_name must be JS_ATOM_NULL for JS_PARSE_FUNC_STATEMENT and
- JS_PARSE_FUNC_EXPR, JS_PARSE_FUNC_ARROW and JS_PARSE_FUNC_VAR */
--static __exception int js_parse_function_decl2(JSParseState *s,
-+static warn_unused int js_parse_function_decl2(JSParseState *s,
- JSParseFunctionEnum func_type,
- JSFunctionKindEnum func_kind,
- JSAtom func_name,
-@@ -33443,7 +33523,7 @@ done:
- return -1;
- }
-
--static __exception int js_parse_function_decl(JSParseState *s,
-+static warn_unused int js_parse_function_decl(JSParseState *s,
- JSParseFunctionEnum func_type,
- JSFunctionKindEnum func_kind,
- JSAtom func_name,
-@@ -33455,7 +33535,7 @@ static __exception int js_parse_function_decl(JSParseState *s,
- NULL);
- }
-
--static __exception int js_parse_program(JSParseState *s)
-+static warn_unused int js_parse_program(JSParseState *s)
- {
- JSFunctionDef *fd = s->cur_func;
- int idx;
-@@ -33497,12 +33577,12 @@ static __exception int js_parse_program(JSParseState *s)
-
- static void js_parse_init(JSContext *ctx, JSParseState *s,
- const char *input, size_t input_len,
-- const char *filename)
-+ const char *filename, int line)
- {
- memset(s, 0, sizeof(*s));
- s->ctx = ctx;
- s->filename = filename;
-- s->line_num = 1;
-+ s->line_num = line;
- s->buf_ptr = (const uint8_t *)input;
- s->buf_end = s->buf_ptr + input_len;
- s->token.val = ' ';
-@@ -33573,9 +33653,9 @@ static void skip_shebang(JSParseState *s)
- }
-
- /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
--static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
-+static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int flags, int scope_idx)
-+ const char *filename, int line, int flags, int scope_idx)
- {
- JSParseState s1, *s = &s1;
- int err, js_mode, eval_type;
-@@ -33586,7 +33666,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- JSFunctionDef *fd;
- JSModuleDef *m;
-
-- js_parse_init(ctx, s, input, input_len, filename);
-+ js_parse_init(ctx, s, input, input_len, filename, line);
- skip_shebang(s);
-
- eval_type = flags & JS_EVAL_TYPE_MASK;
-@@ -33620,7 +33700,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- js_mode |= JS_MODE_STRICT;
- }
- }
-- fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1);
-+ fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, line);
- if (!fd)
- goto fail1;
- s->cur_func = fd;
-@@ -33686,12 +33766,12 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- /* the indirection is needed to make 'eval' optional */
- static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int flags, int scope_idx)
-+ const char *filename, int line, int flags, int scope_idx)
- {
- if (unlikely(!ctx->eval_internal)) {
- return JS_ThrowTypeError(ctx, "eval is not supported");
- }
-- return ctx->eval_internal(ctx, this_obj, input, input_len, filename,
-+ return ctx->eval_internal(ctx, this_obj, input, input_len, filename, line,
- flags, scope_idx);
- }
-
-@@ -33707,7 +33787,7 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
- str = JS_ToCStringLen(ctx, &len, val);
- if (!str)
- return JS_EXCEPTION;
-- ret = JS_EvalInternal(ctx, this_obj, str, len, "<input>", flags, scope_idx);
-+ ret = JS_EvalInternal(ctx, this_obj, str, len, "<input>", 1, flags, scope_idx);
- JS_FreeCString(ctx, str);
- return ret;
-
-@@ -33715,14 +33795,14 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
-
- JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int eval_flags)
-+ const char *filename, int line, int eval_flags)
- {
- int eval_type = eval_flags & JS_EVAL_TYPE_MASK;
- JSValue ret;
-
- assert(eval_type == JS_EVAL_TYPE_GLOBAL ||
- eval_type == JS_EVAL_TYPE_MODULE);
-- ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename,
-+ ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename, line,
- eval_flags, -1);
- return ret;
- }
-@@ -33730,7 +33810,7 @@ JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
- JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
- const char *filename, int eval_flags)
- {
-- return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename,
-+ return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename, 1,
- eval_flags);
- }
-
-@@ -33948,7 +34028,7 @@ static void bc_put_u16(BCWriterState *s, uint16_t v)
- dbuf_put_u16(&s->dbuf, v);
- }
-
--static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v)
-+static maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v)
- {
- if (s->byte_swap)
- v = bswap32(v);
-@@ -33982,7 +34062,7 @@ static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom)
- {
- uint32_t v;
-
-- if (atom < s->first_atom || __JS_AtomIsTaggedInt(atom)) {
-+ if (atom < s->first_atom || JS_AtomIsTaggedInt(atom)) {
- *pres = atom;
- return 0;
- }
-@@ -34022,8 +34102,8 @@ static int bc_put_atom(BCWriterState *s, JSAtom atom)
- {
- uint32_t v;
-
-- if (__JS_AtomIsTaggedInt(atom)) {
-- v = (__JS_AtomToUInt32(atom) << 1) | 1;
-+ if (JS_AtomIsTaggedInt(atom)) {
-+ v = (JS_AtomToUInt32(atom) << 1) | 1;
- } else {
- if (bc_atom_to_idx(s, &v, atom))
- return -1;
-@@ -34142,7 +34222,7 @@ static int JS_WriteFunctionBytecode(BCWriterState *s,
- static void JS_WriteString(BCWriterState *s, JSString *p)
- {
- int i;
-- bc_put_leb128(s, ((uint32_t)p->len << 1) | p->is_wide_char);
-+ bc_put_leb128(s, (p->len << 1) | p->is_wide_char);
- if (p->is_wide_char) {
- for(i = 0; i < p->len; i++)
- bc_put_u16(s, p->u.str16[i]);
-@@ -34800,7 +34880,7 @@ typedef struct BCReaderState {
- } BCReaderState;
-
- #ifdef DUMP_READ_OBJECT
--static void __attribute__((format(printf, 2, 3))) bc_read_trace(BCReaderState *s, const char *fmt, ...) {
-+static void FORMAT_ATTR(2, 3) bc_read_trace(BCReaderState *s, const char *fmt, ...) {
- va_list ap;
- int i, n, n0;
-
-@@ -34863,7 +34943,7 @@ static int bc_get_u16(BCReaderState *s, uint16_t *pval)
- return 0;
- }
-
--static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
-+static maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
- {
- if (unlikely(s->buf_end - s->ptr < 4)) {
- *pval = 0; /* avoid warning */
-@@ -34937,7 +35017,7 @@ static int bc_idx_to_atom(BCReaderState *s, JSAtom *patom, uint32_t idx)
- {
- JSAtom atom;
-
-- if (__JS_AtomIsTaggedInt(idx)) {
-+ if (JS_AtomIsTaggedInt(idx)) {
- atom = idx;
- } else if (idx < s->first_atom) {
- atom = JS_DupAtom(s->ctx, idx);
-@@ -34961,7 +35041,7 @@ static int bc_get_atom(BCReaderState *s, JSAtom *patom)
- if (bc_get_leb128(s, &v))
- return -1;
- if (v & 1) {
-- *patom = __JS_AtomFromUInt32(v >> 1);
-+ *patom = JS_AtomFromUInt32(v >> 1);
- return 0;
- } else {
- return bc_idx_to_atom(s, patom, v >> 1);
-@@ -35776,7 +35856,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
- if (bc_get_u64(s, &u.u64))
- return JS_EXCEPTION;
- bc_read_trace(s, "%g\n", u.d);
-- obj = __JS_NewFloat64(ctx, u.d);
-+ obj = JS_NewFloat64Impl(ctx, u.d);
- }
- break;
- case BC_TAG_STRING:
-@@ -36084,7 +36164,7 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
- val = JS_NewInt64(ctx, e->u.i64);
- break;
- case JS_DEF_PROP_DOUBLE:
-- val = __JS_NewFloat64(ctx, e->u.f64);
-+ val = JS_NewFloat64Impl(ctx, e->u.f64);
- break;
- case JS_DEF_PROP_UNDEFINED:
- val = JS_UNDEFINED;
-@@ -36148,7 +36228,7 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
- val = JS_NewInt64(ctx, e->u.i64);
- break;
- case JS_DEF_PROP_DOUBLE:
-- val = __JS_NewFloat64(ctx, e->u.f64);
-+ val = JS_NewFloat64Impl(ctx, e->u.f64);
- break;
- case JS_DEF_OBJECT:
- val = JS_NewObject(ctx);
-@@ -36381,7 +36461,7 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
- return -1;
- }
-
--static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
-+static warn_unused int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
- JSAtom prop, JSValueConst desc,
- int flags)
- {
-@@ -36397,7 +36477,7 @@ static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
- return ret;
- }
-
--static __exception int JS_ObjectDefineProperties(JSContext *ctx,
-+static warn_unused int JS_ObjectDefineProperties(JSContext *ctx,
- JSValueConst obj,
- JSValueConst properties)
- {
-@@ -36882,32 +36962,6 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val,
- return JS_NewBool(ctx, ret);
- }
-
--static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
-- int argc, JSValueConst *argv)
--{
-- JSValue obj;
-- JSAtom atom;
-- JSObject *p;
-- BOOL ret;
--
-- obj = JS_ToObject(ctx, argv[0]);
-- if (JS_IsException(obj))
-- return obj;
-- atom = JS_ValueToAtom(ctx, argv[1]);
-- if (unlikely(atom == JS_ATOM_NULL)) {
-- JS_FreeValue(ctx, obj);
-- return JS_EXCEPTION;
-- }
-- p = JS_VALUE_GET_OBJ(obj);
-- ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);
-- JS_FreeAtom(ctx, atom);
-- JS_FreeValue(ctx, obj);
-- if (ret < 0)
-- return JS_EXCEPTION;
-- else
-- return JS_NewBool(ctx, ret);
--}
--
- static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
- {
-@@ -37447,6 +37501,32 @@ exception:
- return res;
- }
-
-+static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
-+ int argc, JSValueConst *argv)
-+{
-+ JSValue obj;
-+ JSAtom atom;
-+ JSObject *p;
-+ BOOL ret;
-+
-+ obj = JS_ToObject(ctx, argv[0]);
-+ if (JS_IsException(obj))
-+ return obj;
-+ atom = JS_ValueToAtom(ctx, argv[1]);
-+ if (unlikely(atom == JS_ATOM_NULL)) {
-+ JS_FreeValue(ctx, obj);
-+ return JS_EXCEPTION;
-+ }
-+ p = JS_VALUE_GET_OBJ(obj);
-+ ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);
-+ JS_FreeAtom(ctx, atom);
-+ JS_FreeValue(ctx, obj);
-+ if (ret < 0)
-+ return JS_EXCEPTION;
-+ else
-+ return JS_NewBool(ctx, ret);
-+}
-+
- static const JSCFunctionListEntry js_object_funcs[] = {
- JS_CFUNC_DEF("create", 2, js_object_create ),
- JS_CFUNC_MAGIC_DEF("getPrototypeOf", 1, js_object_getPrototypeOf, 0 ),
-@@ -37576,7 +37656,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
- return JS_EXCEPTION;
- }
-
--static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
-+static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
- JSValueConst obj)
- {
- JSValue len_val;
-@@ -37588,7 +37668,7 @@ static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
- return JS_ToUint32Free(ctx, pres, len_val);
- }
-
--static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
-+static warn_unused int js_get_length64(JSContext *ctx, int64_t *pres,
- JSValueConst obj)
- {
- JSValue len_val;
-@@ -37673,9 +37753,9 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
- if (!tab)
- return JS_EXCEPTION;
- if (magic & 1) {
-- ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab);
-+ ret = JS_CallConstructor2(ctx, this_val, this_arg, len, tab);
- } else {
-- ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab);
-+ ret = JS_Call(ctx, this_val, this_arg, len, tab);
- }
- free_arg_list(ctx, tab, len);
- return ret;
-@@ -38889,8 +38969,7 @@ static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val,
- method = JS_GetProperty(ctx, obj, JS_ATOM_join);
- if (JS_IsException(method)) {
- ret = JS_EXCEPTION;
-- } else
-- if (!JS_IsFunction(ctx, method)) {
-+ } else if (!JS_IsFunction(ctx, method)) {
- /* Use intrinsic Object.prototype.toString */
- JS_FreeValue(ctx, method);
- ret = js_object_toString(ctx, obj, 0, NULL);
-@@ -39138,8 +39217,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
- if (argc == 0) {
- item_count = 0;
- del_count = 0;
-- } else
-- if (argc == 1) {
-+ } else if (argc == 1) {
- item_count = 0;
- del_count = len - start;
- } else {
-@@ -39283,8 +39361,8 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target,
- if (!JS_IsUndefined(mapperFunction)) {
- JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex), source };
- element = JS_Call(ctx, mapperFunction, thisArg, 3, args);
-- JS_FreeValue(ctx, (JSValue)args[0]);
-- JS_FreeValue(ctx, (JSValue)args[1]);
-+ JS_FreeValue(ctx, args[0]);
-+ JS_FreeValue(ctx, args[1]);
- if (JS_IsException(element))
- return -1;
- }
-@@ -39915,7 +39993,7 @@ static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val,
- if (f < 0 || f > 100)
- return JS_ThrowRangeError(ctx, "invalid number of digits");
- if (fabs(d) >= 1e21) {
-- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
-+ return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
- } else {
- return js_dtoa(ctx, d, 10, f, JS_DTOA_FRAC_FORMAT);
- }
-@@ -39936,7 +40014,7 @@ static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val,
- if (JS_ToInt32Sat(ctx, &f, argv[0]))
- return JS_EXCEPTION;
- if (!isfinite(d)) {
-- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
-+ return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
- }
- if (JS_IsUndefined(argv[0])) {
- flags = 0;
-@@ -39968,7 +40046,7 @@ static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val,
- return JS_EXCEPTION;
- if (!isfinite(d)) {
- to_string:
-- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
-+ return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
- }
- if (p < 1 || p > 100)
- return JS_ThrowRangeError(ctx, "invalid number of digits");
-@@ -40089,11 +40167,11 @@ static int js_string_get_own_property(JSContext *ctx,
- uint32_t idx, ch;
-
- /* This is a class exotic method: obj class_id is JS_CLASS_STRING */
-- if (__JS_AtomIsTaggedInt(prop)) {
-+ if (JS_AtomIsTaggedInt(prop)) {
- p = JS_VALUE_GET_OBJ(obj);
- if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {
- p1 = JS_VALUE_GET_STRING(p->u.object_data);
-- idx = __JS_AtomToUInt32(prop);
-+ idx = JS_AtomToUInt32(prop);
- if (idx < p1->len) {
- if (desc) {
- if (p1->is_wide_char)
-@@ -40122,8 +40200,8 @@ static int js_string_define_own_property(JSContext *ctx,
- JSObject *p;
- JSString *p1, *p2;
-
-- if (__JS_AtomIsTaggedInt(prop)) {
-- idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ idx = JS_AtomToUInt32(prop);
- p = JS_VALUE_GET_OBJ(this_obj);
- if (JS_VALUE_GET_TAG(p->u.object_data) != JS_TAG_STRING)
- goto def;
-@@ -40157,8 +40235,8 @@ static int js_string_delete_property(JSContext *ctx,
- {
- uint32_t idx;
-
-- if (__JS_AtomIsTaggedInt(prop)) {
-- idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ idx = JS_AtomToUInt32(prop);
- if (idx < js_string_obj_get_length(ctx, obj)) {
- return FALSE;
- }
-@@ -40701,7 +40779,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
- str = JS_NewString(ctx, "g");
- if (JS_IsException(str))
- goto fail;
-- args[args_len++] = (JSValueConst)str;
-+ args[args_len++] = str;
- }
- rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args);
- JS_FreeValue(ctx, str);
-@@ -40710,7 +40788,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
- JS_FreeValue(ctx, S);
- return JS_EXCEPTION;
- }
-- result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S);
-+ result = JS_InvokeFree(ctx, rx, atom, 1, &S);
- JS_FreeValue(ctx, S);
- return result;
- }
-@@ -41759,7 +41837,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,
- uint32_t tag;
-
- if (unlikely(argc == 0)) {
-- return __JS_NewFloat64(ctx, is_max ? -1.0 / 0.0 : 1.0 / 0.0);
-+ return JS_NewFloat64Impl(ctx, is_max ? INFINITY : -INFINITY);
- }
-
- tag = JS_VALUE_GET_TAG(argv[0]);
-@@ -41911,9 +41989,13 @@ static uint64_t xorshift64star(uint64_t *pstate)
-
- static void js_random_init(JSContext *ctx)
- {
-+#ifdef _MSC_VER
-+ ctx->random_state = time(NULL);
-+#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
-+#endif
- /* the state must be non zero */
- if (ctx->random_state == 0)
- ctx->random_state = 1;
-@@ -41928,15 +42010,21 @@ static JSValue js_math_random(JSContext *ctx, JSValueConst this_val,
- v = xorshift64star(&ctx->random_state);
- /* 1.0 <= u.d < 2 */
- u.u64 = ((uint64_t)0x3ff << 52) | (v >> 12);
-- return __JS_NewFloat64(ctx, u.d - 1.0);
-+ return JS_NewFloat64Impl(ctx, u.d - 1.0);
- }
-
-+// MSVC inexplicably refuses to initialize the array below with
-+// these functions, so use wrappers.
-+static double floorWrapper(double x) { return floor(x); }
-+static double ceilWrapper(double x) { return ceil(x); }
-+static double log2Wrapper(double x) { return log2(x); }
-+
- static const JSCFunctionListEntry js_math_funcs[] = {
- JS_CFUNC_MAGIC_DEF("min", 2, js_math_min_max, 0 ),
- JS_CFUNC_MAGIC_DEF("max", 2, js_math_min_max, 1 ),
- JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, fabs ),
-- JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floor ),
-- JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceil ),
-+ JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floorWrapper ),
-+ JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceilWrapper ),
- JS_CFUNC_SPECIAL_DEF("round", 1, f_f, js_math_round ),
- JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, sqrt ),
-
-@@ -41961,7 +42049,7 @@ static const JSCFunctionListEntry js_math_funcs[] = {
- JS_CFUNC_SPECIAL_DEF("atanh", 1, f_f, atanh ),
- JS_CFUNC_SPECIAL_DEF("expm1", 1, f_f, expm1 ),
- JS_CFUNC_SPECIAL_DEF("log1p", 1, f_f, log1p ),
-- JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, log2 ),
-+ JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, log2Wrapper ),
- JS_CFUNC_SPECIAL_DEF("log10", 1, f_f, log10 ),
- JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, cbrt ),
- JS_CFUNC_DEF("hypot", 2, js_math_hypot ),
-@@ -42004,9 +42092,16 @@ static JSValue js___date_clock(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
- {
- int64_t d;
-+#ifdef _MSC_VER
-+ SYSTEMTIME st;
-+ GetSystemTime(&st);
-+ SystemTimeToFileTime(&st, (FILETIME *) &d);
-+ d /= 10;
-+#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- d = (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
-+#endif
- return JS_NewInt64(ctx, d);
- }
-
-@@ -43686,7 +43781,7 @@ JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
- JSParseState s1, *s = &s1;
- JSValue val = JS_UNDEFINED;
-
-- js_parse_init(ctx, s, buf, buf_len, filename);
-+ js_parse_init(ctx, s, buf, buf_len, filename, 1);
- s->ext_json = ((flags & JS_PARSE_JSON_EXT) != 0);
- if (json_next_token(s))
- goto fail;
-@@ -43937,7 +44032,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
- goto exception;
- }
- #endif
-- v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);
-+ v = js_array_includes(ctx, jsc->stack, 1, &val);
- if (JS_IsException(v))
- goto exception;
- if (JS_ToBoolFree(ctx, v)) {
-@@ -43958,7 +44053,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
- sep = JS_DupValue(ctx, jsc->empty);
- sep1 = JS_DupValue(ctx, jsc->empty);
- }
-- v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0);
-+ v = js_array_push(ctx, jsc->stack, 1, &val, 0);
- if (check_exception_free(ctx, v))
- goto exception;
- ret = JS_IsArray(ctx, val);
-@@ -43998,7 +44093,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
- if (!JS_IsUndefined(jsc->property_list))
- tab = JS_DupValue(ctx, jsc->property_list);
- else
-- tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);
-+ tab = js_object_keys(ctx, JS_UNDEFINED, 1, &val, JS_ITERATOR_KIND_KEY);
- if (JS_IsException(tab))
- goto exception;
- if (js_get_length64(ctx, &len, tab))
-@@ -44146,7 +44241,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
- continue;
- }
- present = js_array_includes(ctx, jsc->property_list,
-- 1, (JSValueConst *)&v);
-+ 1, &v);
- if (JS_IsException(present)) {
- JS_FreeValue(ctx, v);
- goto exception;
-@@ -44270,7 +44365,7 @@ static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
- tab = build_arg_list(ctx, &len, array_arg);
- if (!tab)
- return JS_EXCEPTION;
-- ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab);
-+ ret = JS_CallConstructor2(ctx, func, new_target, len, tab);
- free_arg_list(ctx, tab, len);
- return ret;
- }
-@@ -44475,7 +44570,7 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)
- return JS_EXCEPTION;
- if (JS_IsUndefined(method))
- return JS_GetPrototype(ctx, s->target);
-- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
-+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
- if (JS_IsException(ret))
- return ret;
- if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL &&
-@@ -44562,7 +44657,7 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)
- return -1;
- if (JS_IsUndefined(method))
- return JS_IsExtensible(ctx, s->target);
-- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
-+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
- if (JS_IsException(ret))
- return -1;
- res = JS_ToBoolFree(ctx, ret);
-@@ -44588,7 +44683,7 @@ static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)
- return -1;
- if (JS_IsUndefined(method))
- return JS_PreventExtensions(ctx, s->target);
-- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
-+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
- if (JS_IsException(ret))
- return -1;
- res = JS_ToBoolFree(ctx, ret);
-@@ -45072,7 +45167,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
- JS_VALUE_GET_OBJ(s->target),
- JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK);
- }
-- prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
-+ prop_array = JS_CallFree(ctx, method, s->handler, 1, &s->target);
- if (JS_IsException(prop_array))
- return -1;
- tab = NULL;
-@@ -45408,7 +45503,7 @@ static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val,
- if (JS_IsException(val))
- return val;
- /* XXX: use JS_ToStringInternal() with a flags */
-- ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val);
-+ ret = js_string_constructor(ctx, JS_UNDEFINED, 1, &val);
- JS_FreeValue(ctx, val);
- return ret;
- }
-@@ -45558,7 +45653,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
- break;
- }
- if (is_set) {
-- ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item);
-+ ret = JS_Call(ctx, adder, obj, 1, &item);
- if (JS_IsException(ret)) {
- JS_FreeValue(ctx, item);
- goto fail;
-@@ -45729,7 +45824,7 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
- } else {
- JS_DupValue(ctx, key);
- }
-- mr->key = (JSValue)key;
-+ mr->key = key;
- h = map_hash_key(ctx, key) & (s->hash_size - 1);
- list_add_tail(&mr->hash_link, &s->hash_table[h]);
- list_add_tail(&mr->link, &s->records);
-@@ -45951,7 +46046,7 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,
- args[0] = args[1];
- else
- args[0] = JS_DupValue(ctx, mr->value);
-- args[2] = (JSValue)this_val;
-+ args[2] = this_val;
- ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args);
- JS_FreeValue(ctx, args[0]);
- if (!magic)
-@@ -46343,7 +46438,7 @@ static JSValue promise_reaction_job(JSContext *ctx, int argc,
- functions */
- if (!JS_IsUndefined(func)) {
- res2 = JS_Call(ctx, func, JS_UNDEFINED,
-- 1, (JSValueConst *)&res);
-+ 1, &res);
- } else {
- res2 = JS_UNDEFINED;
- }
-@@ -46426,7 +46521,7 @@ static JSValue js_promise_resolve_thenable_job(JSContext *ctx,
- res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args);
- if (JS_IsException(res)) {
- JSValue error = JS_GetException(ctx);
-- res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
-+ res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
- JS_FreeValue(ctx, error);
- }
- JS_FreeValue(ctx, args[0]);
-@@ -46626,7 +46721,7 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,
- if (JS_IsException(ret)) {
- JSValue ret2, error;
- error = JS_GetException(ctx);
-- ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
-+ ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
- JS_FreeValue(ctx, error);
- if (JS_IsException(ret2))
- goto fail1;
-@@ -46683,10 +46778,10 @@ static JSValue js_new_promise_capability(JSContext *ctx,
-
- if (JS_IsUndefined(ctor)) {
- result_promise = js_promise_constructor(ctx, ctor, 1,
-- (JSValueConst *)&executor);
-+ &executor);
- } else {
- result_promise = JS_CallConstructor(ctx, ctor, 1,
-- (JSValueConst *)&executor);
-+ &executor);
- }
- if (JS_IsException(result_promise))
- goto fail;
-@@ -46770,7 +46865,7 @@ static JSValue js_promise___newPromiseCapability(JSContext *ctx,
- }
- #endif
-
--static __exception int remainingElementsCount_add(JSContext *ctx,
-+static warn_unused int remainingElementsCount_add(JSContext *ctx,
- JSValueConst resolve_element_env,
- int addend)
- {
-@@ -46851,10 +46946,10 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
- error = js_aggregate_error_constructor(ctx, values);
- if (JS_IsException(error))
- return JS_EXCEPTION;
-- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error);
-+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &error);
- JS_FreeValue(ctx, error);
- } else {
-- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);
-+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &values);
- }
- if (JS_IsException(ret))
- return ret;
-@@ -46890,7 +46985,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- fail_reject:
- error = JS_GetException(ctx);
- ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
-- (JSValueConst *)&error);
-+ &error);
- JS_FreeValue(ctx, error);
- if (JS_IsException(ret))
- goto fail;
-@@ -46921,7 +47016,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- if (done)
- break;
- next_promise = JS_Call(ctx, promise_resolve,
-- this_val, 1, (JSValueConst *)&item);
-+ this_val, 1, &item);
- JS_FreeValue(ctx, item);
- if (JS_IsException(next_promise)) {
- fail_reject1:
-@@ -46929,7 +47024,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- goto fail_reject;
- }
- resolve_element_data[0] = JS_NewBool(ctx, FALSE);
-- resolve_element_data[1] = (JSValueConst)JS_NewInt32(ctx, index);
-+ resolve_element_data[1] = JS_NewInt32(ctx, index);
- resolve_element_data[2] = values;
- resolve_element_data[3] = resolving_funcs[is_promise_any];
- resolve_element_data[4] = resolve_element_env;
-@@ -46989,7 +47084,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- values = error;
- }
- ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED,
-- 1, (JSValueConst *)&values);
-+ 1, &values);
- if (check_exception_free(ctx, ret))
- goto fail_reject;
- }
-@@ -47032,7 +47127,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
- fail_reject:
- error = JS_GetException(ctx);
- ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
-- (JSValueConst *)&error);
-+ &error);
- JS_FreeValue(ctx, error);
- if (JS_IsException(ret))
- goto fail;
-@@ -47051,7 +47146,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
- if (done)
- break;
- next_promise = JS_Call(ctx, promise_resolve,
-- this_val, 1, (JSValueConst *)&item);
-+ this_val, 1, &item);
- JS_FreeValue(ctx, item);
- if (JS_IsException(next_promise)) {
- fail_reject1:
-@@ -47078,7 +47173,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
- goto done;
- }
-
--static __exception int perform_promise_then(JSContext *ctx,
-+static warn_unused int perform_promise_then(JSContext *ctx,
- JSValueConst promise,
- JSValueConst *resolve_reject,
- JSValueConst *cap_resolving_funcs)
-@@ -47196,7 +47291,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
- res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL);
- if (JS_IsException(res))
- return res;
-- promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0);
-+ promise = js_promise_resolve(ctx, ctor, 1, &res, 0);
- JS_FreeValue(ctx, res);
- if (JS_IsException(promise))
- return promise;
-@@ -47211,7 +47306,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
- JS_FreeValue(ctx, promise);
- return then_func;
- }
-- ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, (JSValueConst *)&then_func);
-+ ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, &then_func);
- JS_FreeValue(ctx, then_func);
- return ret;
- }
-@@ -47288,7 +47383,7 @@ static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx,
- {
- JSValueConst func_data[1];
-
-- func_data[0] = (JSValueConst)JS_NewBool(ctx, done);
-+ func_data[0] = JS_NewBool(ctx, done);
- return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap,
- 1, 0, 1, func_data);
- }
-@@ -47411,7 +47506,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
- is_reject = 1;
- done_resolve:
- res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED,
-- 1, (JSValueConst *)&err);
-+ 1, &err);
- JS_FreeValue(ctx, err);
- JS_FreeValue(ctx, res2);
- JS_FreeValue(ctx, resolving_funcs[0]);
-@@ -47423,7 +47518,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
- int res;
-
- value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor,
-- 1, (JSValueConst *)&value, 0);
-+ 1, &value, 0);
- if (JS_IsException(value_wrapper_promise)) {
- JS_FreeValue(ctx, value);
- goto reject;
-@@ -47593,7 +47688,7 @@ static int isURIReserved(int c) {
- return c < 0x100 && memchr(";/?:@&=+$,#", c, sizeof(";/?:@&=+$,#") - 1) != NULL;
- }
-
--static int __attribute__((format(printf, 2, 3))) js_throw_URIError(JSContext *ctx, const char *fmt, ...)
-+static int FORMAT_ATTR(2, 3) js_throw_URIError(JSContext *ctx, const char *fmt, ...)
- {
- va_list ap;
-
-@@ -47894,7 +47989,7 @@ static int64_t floor_div(int64_t a, int64_t b) {
- static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv);
-
--static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
-+static warn_unused int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
- {
- if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
- JSObject *p = JS_VALUE_GET_OBJ(this_val);
-@@ -47954,7 +48049,7 @@ static int const month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
- static char const day_names[] = "SunMonTueWedThuFriSat";
-
--static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
-+static warn_unused int get_date_fields(JSContext *ctx, JSValueConst obj,
- double fields[9], int is_local, int force)
- {
- double dval;
-@@ -48016,7 +48111,7 @@ static double time_clip(double t) {
-
- /* The spec mandates the use of 'double' and it fixes the order
- of the operations */
--static double set_date_fields(double fields[], int is_local) {
-+static double set_date_fields(const double fields[], int is_local) {
- int64_t y;
- double days, d, h, m1;
- int i, m, md;
-@@ -48213,9 +48308,17 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
-
- /* OS dependent: return the UTC time in ms since 1970. */
- static int64_t date_now(void) {
-+#ifdef _MSC_VER
-+ SYSTEMTIME st;
-+ GetSystemTime(&st);
-+ int64_t d;
-+ SystemTimeToFileTime(&st, (FILETIME *) &d);
-+ return d /= 10000;
-+#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
-+#endif
- }
-
- static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
-@@ -48246,7 +48349,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
- }
- v = JS_ToPrimitive(ctx, argv[0], HINT_NONE);
- if (JS_IsString(v)) {
-- dv = js_Date_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&v);
-+ dv = js_Date_parse(ctx, JS_UNDEFINED, 1, &v);
- JS_FreeValue(ctx, v);
- if (JS_IsException(dv))
- return JS_EXCEPTION;
-@@ -48814,7 +48917,7 @@ void JS_AddIntrinsicDate(JSContext *ctx)
-
- void JS_AddIntrinsicEval(JSContext *ctx)
- {
-- ctx->eval_internal = __JS_EvalInternal;
-+ ctx->eval_internal = JS_EvalInternalImpl;
- }
-
- #ifdef CONFIG_BIGNUM
-@@ -50934,7 +51037,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
- JS_PROP_HAS_GET | JS_PROP_HAS_SET |
- JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);
- JS_FreeValue(ctx, obj1);
-- JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1));
-+ JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, &ctx->throw_type_error, 1));
-
- ctx->global_obj = JS_NewObject(ctx);
- ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL);
-@@ -52090,7 +52193,7 @@ exception:
-
- #define special_indexOf 0
- #define special_lastIndexOf 1
--#define special_includes -1
-+#define special_includes (-1)
-
- static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int special)
-@@ -52157,8 +52260,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
- is_int = 1;
- v64 = JS_VALUE_GET_INT(argv[0]);
- d = v64;
-- } else
-- if (tag == JS_TAG_FLOAT64) {
-+ } else if (tag == JS_TAG_FLOAT64) {
- d = JS_VALUE_GET_FLOAT64(argv[0]);
- v64 = d;
- is_int = (v64 == d);
-@@ -52659,11 +52761,11 @@ static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) {
- #endif
-
- static JSValue js_TA_get_float32(JSContext *ctx, const void *a) {
-- return __JS_NewFloat64(ctx, *(const float *)a);
-+ return JS_NewFloat64Impl(ctx, *(const float *)a);
- }
-
- static JSValue js_TA_get_float64(JSContext *ctx, const void *a) {
-- return __JS_NewFloat64(ctx, *(const double *)a);
-+ return JS_NewFloat64Impl(ctx, *(const double *)a);
- }
-
- struct TA_sort_context {
-@@ -52717,8 +52819,8 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
- psc->exception = 1;
- }
- done:
-- JS_FreeValue(ctx, (JSValue)argv[0]);
-- JS_FreeValue(ctx, (JSValue)argv[1]);
-+ JS_FreeValue(ctx, argv[0]);
-+ JS_FreeValue(ctx, argv[1]);
- }
- return cmp;
- }
-@@ -53285,7 +53387,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
- case JS_CLASS_INT8_ARRAY:
- return JS_NewInt32(ctx, *(int8_t *)ptr);
- case JS_CLASS_UINT8_ARRAY:
-- return JS_NewInt32(ctx, *(uint8_t *)ptr);
-+ return JS_NewInt32(ctx, *ptr);
- case JS_CLASS_INT16_ARRAY:
- v = get_u16(ptr);
- if (is_swap)
-@@ -53336,7 +53438,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
- if (is_swap)
- v = bswap32(v);
- u.i = v;
-- return __JS_NewFloat64(ctx, u.f);
-+ return JS_NewFloat64Impl(ctx, u.f);
- }
- case JS_CLASS_FLOAT64_ARRAY:
- {
-@@ -53347,7 +53449,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
- u.i = get_u64(ptr);
- if (is_swap)
- u.i = bswap64(u.i);
-- return __JS_NewFloat64(ctx, u.f);
-+ return JS_NewFloat64Impl(ctx, u.f);
- }
- default:
- abort();
-@@ -54059,3 +54161,155 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
- JS_AddIntrinsicAtomics(ctx);
- #endif
- }
-+
-+#ifndef NDEBUG
-+static void *watchedRefCount = NULL;
-+
-+void notifyRefCountIncrease(JSRefCountHeader *p)
-+{
-+ if (p == watchedRefCount)
-+ fprintf(stderr, "increasing ref count %d for %p\n", p->ref_count, watchedRefCount);
-+}
-+
-+void notifyRefCountDecrease(JSRefCountHeader *p)
-+{
-+ if (p == watchedRefCount)
-+ fprintf(stderr, "decreasing ref count %d for %p\n", p->ref_count, watchedRefCount);
-+}
-+
-+void watchRefCount(void *p)
-+{
-+ watchedRefCount = p;
-+}
-+#endif
-+
-+void setScopeLookup(JSContext *ctx, ScopeLookup *scopeLookup)
-+{
-+ ctx->scopeLookup = scopeLookup;
-+}
-+
-+void setFoundUndefinedHandler(JSContext *ctx, FoundUndefinedHandler *handler)
-+{
-+ ctx->handleUndefined = handler;
-+}
-+
-+void setFunctionEnteredHandler(JSContext *ctx, FunctionEnteredHandler *handler)
-+{
-+ ctx->handleFunctionEntered = handler;
-+}
-+
-+void setFunctionExitedHandler(JSContext *ctx, FunctionExitedHandler *handler)
-+{
-+ ctx->handleFunctionExited = handler;
-+}
-+
-+int isSimpleValue(JSValue v)
-+{
-+ JSObject *p;
-+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
-+ return 1;
-+ p = JS_VALUE_GET_OBJ(v);
-+ return p->class_id >= JS_CLASS_OBJECT && p->class_id <= JS_CLASS_BOOLEAN;
-+}
-+
-+JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
-+ const char *name, int length,
-+ JSCFunctionEnum cproto, int magic)
-+{
-+ return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto,
-+ magic);
-+}
-+
-+JSValue mkVal(int32_t tag, int32_t val)
-+{
-+ return (JSValue){ (JSValueUnion){ .int32 = val }, tag };
-+}
-+
-+JSValue mkPtr(int32_t tag, void *p)
-+{
-+ return (JSValue){ (JSValueUnion){ .ptr = p }, tag };
-+}
-+
-+void JS_FreeValue(JSContext *ctx, JSValue v) {
-+ if (JS_VALUE_HAS_REF_COUNT(v)) {
-+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-+#ifndef NDEBUG
-+ notifyRefCountDecrease(p);
-+#endif
-+ if (--p->ref_count <= 0) {
-+ JS_FreeValueImpl(ctx, v);
-+ }
-+ }
-+}
-+void JS_FreeValueRT(JSRuntime *rt, JSValue v) {
-+ if (JS_VALUE_HAS_REF_COUNT(v)) {
-+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-+#ifndef NDEBUG
-+ notifyRefCountDecrease(p);
-+#endif
-+ if (--p->ref_count <= 0) {
-+ JS_FreeValueRTImpl(rt, v);
-+ }
-+ }
-+}
-+JSValue JS_NewBool(JSContext *ctx, JS_BOOL val) {
-+ (void)ctx;
-+ return JS_MKVAL(JS_TAG_BOOL, (val != 0));
-+}
-+JSValue JS_NewInt32(JSContext *ctx, int32_t val) {
-+ (void)ctx;
-+ return JS_MKVAL(JS_TAG_INT, val);
-+}
-+JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) {
-+ (void)ctx;
-+ return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
-+}
-+JSValue JS_NewInt64(JSContext *ctx, int64_t val) {
-+ JSValue v;
-+ if (val == (int32_t)val) {
-+ v = JS_NewInt32(ctx, (int32_t)val);
-+ } else {
-+ v = JS_NewFloat64Impl(ctx, (double)val);
-+ }
-+ return v;
-+}
-+JSValue JS_NewUint32(JSContext *ctx, uint32_t val) {
-+ JSValue v;
-+ if (val <= 0x7fffffff) {
-+ v = JS_NewInt32(ctx, val);
-+ } else {
-+ v = JS_NewFloat64Impl(ctx, val);
-+ }
-+ return v;
-+}
-+JSValue JS_NewFloat64(JSContext *ctx, double d) {
-+ JSValue v;
-+ int32_t val;
-+ union {
-+ double d;
-+ uint64_t u;
-+ } u, t;
-+ u.d = d;
-+ val = (int32_t)d;
-+ t.d = val;
-+ /* -0 cannot be represented as integer, so we compare the bit
-+ representation */
-+ if (u.u == t.u) {
-+ v = JS_MKVAL(JS_TAG_INT, val);
-+ } else {
-+ v = JS_NewFloat64Impl(ctx, d);
-+ }
-+ return v;
-+}
-+JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
-+ int length) {
-+ return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
-+}
-+
-+JS_BOOL JS_IsRegExp(JSContext *ctx, JSValue val)
-+{
-+ JSObject *p;
-+ if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
-+ return FALSE;
-+ return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_REGEXP;
-+}
-diff --git a/quickjs.h b/quickjs.h
-index d4a5cd3..a5adf0c 100644
---- a/quickjs.h
-+++ b/quickjs.h
-@@ -215,15 +215,19 @@ typedef struct JSValue {
- #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64)
- #define JS_VALUE_GET_PTR(v) ((v).u.ptr)
-
--#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag }
--#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag }
-+JSValue mkVal(int32_t tag, int32_t val);
-+JSValue mkPtr(int32_t tag, void *p);
-+
-+#define JS_MKVAL(tag, val) mkVal(tag, val)
-+#define JS_MKPTR(tag, p) mkPtr(tag, p)
-
- #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
-
- #define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
-
--static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
-+static inline JSValue JS_NewFloat64Impl(JSContext *ctx, double d)
- {
-+ (void) ctx;
- JSValue v;
- v.tag = JS_TAG_FLOAT64;
- v.u.float64 = d;
-@@ -502,66 +506,14 @@ int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
-
- /* value handling */
-
--static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val)
--{
-- return JS_MKVAL(JS_TAG_BOOL, (val != 0));
--}
--
--static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)
--{
-- return JS_MKVAL(JS_TAG_INT, val);
--}
--
--static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val)
--{
-- return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
--}
--
--static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val)
--{
-- JSValue v;
-- if (val == (int32_t)val) {
-- v = JS_NewInt32(ctx, val);
-- } else {
-- v = __JS_NewFloat64(ctx, val);
-- }
-- return v;
--}
--
--static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val)
--{
-- JSValue v;
-- if (val <= 0x7fffffff) {
-- v = JS_NewInt32(ctx, val);
-- } else {
-- v = __JS_NewFloat64(ctx, val);
-- }
-- return v;
--}
--
-+JSValue JS_NewBool(JSContext *ctx, JS_BOOL val);
-+JSValue JS_NewInt32(JSContext *ctx, int32_t val);
-+JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val);
-+JSValue JS_NewInt64(JSContext *ctx, int64_t val);
-+JSValue JS_NewUint32(JSContext *ctx, uint32_t val);
- JSValue JS_NewBigInt64(JSContext *ctx, int64_t v);
- JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v);
--
--static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d)
--{
-- JSValue v;
-- int32_t val;
-- union {
-- double d;
-- uint64_t u;
-- } u, t;
-- u.d = d;
-- val = (int32_t)d;
-- t.d = val;
-- /* -0 cannot be represented as integer, so we compare the bit
-- representation */
-- if (u.u == t.u) {
-- v = JS_MKVAL(JS_TAG_INT, val);
-- } else {
-- v = __JS_NewFloat64(ctx, d);
-- }
-- return v;
--}
-+JSValue JS_NewFloat64(JSContext *ctx, double d);
-
- static inline JS_BOOL JS_IsNumber(JSValueConst v)
- {
-@@ -571,6 +523,7 @@ static inline JS_BOOL JS_IsNumber(JSValueConst v)
-
- static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v)
- {
-+ (void) ctx;
- int tag = JS_VALUE_GET_TAG(v);
- return tag == JS_TAG_BIG_INT;
- }
-@@ -639,43 +592,38 @@ JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fm
- JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
- JSValue JS_ThrowOutOfMemory(JSContext *ctx);
-
--void __JS_FreeValue(JSContext *ctx, JSValue v);
--static inline void JS_FreeValue(JSContext *ctx, JSValue v)
--{
-- if (JS_VALUE_HAS_REF_COUNT(v)) {
-- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-- if (--p->ref_count <= 0) {
-- __JS_FreeValue(ctx, v);
-- }
-- }
--}
--void __JS_FreeValueRT(JSRuntime *rt, JSValue v);
--static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v)
--{
-- if (JS_VALUE_HAS_REF_COUNT(v)) {
-- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-- if (--p->ref_count <= 0) {
-- __JS_FreeValueRT(rt, v);
-- }
-- }
--}
-+#ifndef NDEBUG
-+void notifyRefCountIncrease(JSRefCountHeader *p);
-+void notifyRefCountDecrease(JSRefCountHeader *p);
-+#endif
-+
-+void JS_FreeValue(JSContext *ctx, JSValue v);
-+void JS_FreeValueRT(JSRuntime *rt, JSValue v);
-
- static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v)
- {
-+ (void) ctx;
- if (JS_VALUE_HAS_REF_COUNT(v)) {
- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-+#ifndef NDEBUG
-+ notifyRefCountIncrease(p);
-+#endif
- p->ref_count++;
- }
-- return (JSValue)v;
-+ return v;
- }
-
- static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
- {
-+ (void) rt;
- if (JS_VALUE_HAS_REF_COUNT(v)) {
- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-+#ifndef NDEBUG
-+ notifyRefCountIncrease(p);
-+#endif
- p->ref_count++;
- }
-- return (JSValue)v;
-+ return v;
- }
-
- int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
-@@ -714,6 +662,7 @@ JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto);
- JSValue JS_NewObject(JSContext *ctx);
-
- JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
-+JS_BOOL JS_IsRegExp(JSContext* ctx, JSValueConst val);
- JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val);
- JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val);
-
-@@ -783,7 +732,7 @@ JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
- /* same as JS_Eval() but with an explicit 'this_obj' parameter */
- JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int eval_flags);
-+ const char *filename, int line, int eval_flags);
- JSValue JS_GetGlobalObject(JSContext *ctx);
- int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj);
- int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
-@@ -945,18 +894,11 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
- int length, int magic, int data_len,
- JSValueConst *data);
-
--static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
-- int length)
--{
-- return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
--}
-+JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
-+ int length);
-
--static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
-- const char *name,
-- int length, JSCFunctionEnum cproto, int magic)
--{
-- return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);
--}
-+JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
-+ const char *name, int length, JSCFunctionEnum cproto, int magic);
- void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
- JSValueConst proto);
-
-@@ -1039,6 +981,35 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
- int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
- const JSCFunctionListEntry *tab, int len);
-
-+
-+/* Qbs extensions */
-+struct LookupResult
-+{
-+ JSValue value;
-+ JSValue scope;
-+ int useResult;
-+};
-+typedef struct LookupResult ScopeLookup(JSContext *ctx, JSAtom prop);
-+void setScopeLookup(JSContext *ctx, ScopeLookup *scopeLookup);
-+
-+// Alternative: Request with throw in script engine
-+typedef void FoundUndefinedHandler(JSContext *ctx);
-+void setFoundUndefinedHandler(JSContext *ctx, FoundUndefinedHandler *handler);
-+
-+typedef void FunctionEnteredHandler(JSContext *ctx, JSValue this_val);
-+typedef void FunctionExitedHandler(JSContext *ctx);
-+void setFunctionEnteredHandler(JSContext *ctx, FunctionEnteredHandler *handler);
-+void setFunctionExitedHandler(JSContext *ctx, FunctionExitedHandler *handler);
-+int isSimpleValue(JSValue v);
-+
-+#ifndef NDEBUG
-+void watchRefCount(void *p);
-+#endif
-+
-+void build_backtrace(JSContext *ctx, JSValueConst error_obj,
-+ const char *filename, int line_num,
-+ int backtrace_flags);
-+
- #undef js_unlikely
- #undef js_force_inline
-
diff --git a/src/shared/quickjs/quickjs.h b/src/shared/quickjs/quickjs.h
index aa4a74c9c..3a22f5b7b 100644
--- a/src/shared/quickjs/quickjs.h
+++ b/src/shared/quickjs/quickjs.h
@@ -156,7 +156,7 @@ static inline double JS_VALUE_GET_FLOAT64(JSValue v)
#define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32))
-static inline JSValue JS_NewFloat64Impl(JSContext *ctx, double d)
+static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
{
(void) ctx;
union {
@@ -226,7 +226,7 @@ JSValue mkPtr(int32_t tag, void *p);
#define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
-static inline JSValue JS_NewFloat64Impl(JSContext *ctx, double d)
+static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
{
(void) ctx;
JSValue v;
@@ -312,6 +312,9 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
/* don't include the stack frames before this eval in the Error() backtraces */
#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)
+/* allow top-level await in normal script. JS_Eval() returns a
+ promise. Only allowed with JS_EVAL_TYPE_GLOBAL */
+#define JS_EVAL_FLAG_ASYNC (1 << 7)
typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
@@ -501,7 +504,10 @@ typedef struct JSClassDef {
JSClassExoticMethods *exotic;
} JSClassDef;
+#define JS_INVALID_CLASS_ID 0
JSClassID JS_NewClassID(JSClassID *pclass_id);
+/* Returns the class ID if `v` is an object, otherwise returns JS_INVALID_CLASS_ID. */
+JSClassID JS_GetClassID(JSValue v);
int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def);
int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
@@ -514,6 +520,7 @@ JSValue JS_NewInt64(JSContext *ctx, int64_t val);
JSValue JS_NewUint32(JSContext *ctx, uint32_t val);
JSValue JS_NewBigInt64(JSContext *ctx, int64_t v);
JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v);
+
JSValue JS_NewFloat64(JSContext *ctx, double d);
static inline JS_BOOL JS_IsNumber(JSValueConst v)
@@ -583,7 +590,9 @@ static inline JS_BOOL JS_IsObject(JSValueConst v)
JSValue JS_Throw(JSContext *ctx, JSValue obj);
JSValue JS_GetException(JSContext *ctx);
+JS_BOOL JS_HasException(JSContext *ctx);
JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
+void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, JS_BOOL flag);
void JS_ResetUncatchableError(JSContext *ctx);
JSValue JS_NewError(JSContext *ctx);
JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
@@ -627,6 +636,10 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
return v;
}
+JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
+JS_BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2);
+JS_BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
+
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
@@ -668,12 +681,12 @@ JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val);
JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val);
JS_BOOL JS_IsArrayBuffer(JSValueConst v);
-JSValue JS_NewDate(JSContext *ctx, const char *s);
-JS_BOOL JS_IsDate(JSValueConst v);
-
JSValue JS_NewArray(JSContext *ctx);
int JS_IsArray(JSContext *ctx, JSValueConst val);
+JSValue JS_NewDate(JSContext *ctx, double epoch_ms);
+JS_BOOL JS_IsDate(JSValueConst v);
+
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
JSAtom prop, JSValueConst receiver,
JS_BOOL throw_ref_error);
@@ -687,13 +700,13 @@ JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
uint32_t idx);
-int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValue val,
+int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
+ JSAtom prop, JSValue val, JSValueConst this_obj,
int flags);
static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj,
JSAtom prop, JSValue val)
{
- return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW);
+ return JS_SetPropertyInternal(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW);
}
int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
uint32_t idx, JSValue val);
@@ -774,6 +787,23 @@ JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
+
+typedef enum JSTypedArrayEnum {
+ JS_TYPED_ARRAY_UINT8C = 0,
+ JS_TYPED_ARRAY_INT8,
+ JS_TYPED_ARRAY_UINT8,
+ JS_TYPED_ARRAY_INT16,
+ JS_TYPED_ARRAY_UINT16,
+ JS_TYPED_ARRAY_INT32,
+ JS_TYPED_ARRAY_UINT32,
+ JS_TYPED_ARRAY_BIG_INT64,
+ JS_TYPED_ARRAY_BIG_UINT64,
+ JS_TYPED_ARRAY_FLOAT32,
+ JS_TYPED_ARRAY_FLOAT64,
+} JSTypedArrayEnum;
+
+JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
+ JSTypedArrayEnum array_type);
JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
size_t *pbyte_offset,
size_t *pbyte_length,
@@ -787,7 +817,15 @@ typedef struct {
void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
const JSSharedArrayBufferFunctions *sf);
+typedef enum JSPromiseStateEnum {
+ JS_PROMISE_PENDING,
+ JS_PROMISE_FULFILLED,
+ JS_PROMISE_REJECTED,
+} JSPromiseStateEnum;
+
JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
+JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise);
+JSValue JS_PromiseResult(JSContext *ctx, JSValue promise);
/* is_handled = TRUE means that the rejection is handled */
typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise,
@@ -821,6 +859,7 @@ void JS_SetModuleLoaderFunc(JSRuntime *rt,
/* return the import.meta object of a module */
JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);
JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m);
+JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m);
/* JS Job support */
@@ -858,8 +897,8 @@ int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
/* only exported for os.Worker() */
JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
/* only exported for os.Worker() */
-JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
- const char *filename);
+JSValue JS_LoadModule(JSContext *ctx, const char *basename,
+ const char *filename);
/* C function definition */
typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
diff --git a/src/shared/quickjs/quickjs.qbs b/src/shared/quickjs/quickjs.qbs
index 4c8112ac9..bdce37979 100644
--- a/src/shared/quickjs/quickjs.qbs
+++ b/src/shared/quickjs/quickjs.qbs
@@ -12,6 +12,8 @@ StaticLibrary {
files: [
"cutils.c",
"cutils.h",
+ "libbf.c",
+ "libbf.h",
"libregexp-opcode.h",
"libregexp.c",
"libregexp.h",
@@ -22,12 +24,11 @@ StaticLibrary {
"quickjs-atom.h",
"quickjs-opcode.h",
"quickjs.c",
- "quickjs.diff",
"quickjs.h",
]
Export {
Depends { name: "cpp" }
- cpp.includePaths: [exportingProduct.sourceDirectory]
+ cpp.systemIncludePaths: [exportingProduct.sourceDirectory]
}
}
diff --git a/src/shared/span/.clang-format b/src/shared/span/.clang-format
new file mode 100644
index 000000000..47a38a93f
--- /dev/null
+++ b/src/shared/span/.clang-format
@@ -0,0 +1,2 @@
+DisableFormat: true
+SortIncludes: Never
diff --git a/src/shared/span/CMakeLists.txt b/src/shared/span/CMakeLists.txt
new file mode 100644
index 000000000..5fbbc5e46
--- /dev/null
+++ b/src/shared/span/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_library(span INTERFACE)
+target_include_directories(
+ span
+ INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
diff --git a/src/shared/variant/LICENSE.md b/src/shared/span/LICENSE_1_0.txt
index 36b7cd93c..36b7cd93c 100644
--- a/src/shared/variant/LICENSE.md
+++ b/src/shared/span/LICENSE_1_0.txt
diff --git a/src/shared/span/README.md b/src/shared/span/README.md
new file mode 100644
index 000000000..dcc95ab6c
--- /dev/null
+++ b/src/shared/span/README.md
@@ -0,0 +1,557 @@
+<a id="top"></a>
+# span lite: A single-file header-only version of a C++20-like span for C++98, C++11 and later
+
+[![Language](https://img.shields.io/badge/C%2B%2B-98/11/14/17/20-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-BSL-blue.svg)](https://opensource.org/licenses/BSL-1.0) [![Build Status](https://github.com/martinmoene/span-lite/actions/workflows/ci.yml/badge.svg)](https://github.com/martinmoene/span-lite/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/1ha3wnxtam547m8p?svg=true)](https://ci.appveyor.com/project/martinmoene/span-lite) [![Version](https://badge.fury.io/gh/martinmoene%2Fspan-lite.svg)](https://github.com/martinmoene/span-lite/releases) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://github.com/martinmoene/span-lite/blob/master/include/nonstd/span.hpp) [![Conan](https://img.shields.io/badge/on-conan-blue.svg)](https://conan.io/center/span-lite) [![Try it on wandbox](https://img.shields.io/badge/on-wandbox-blue.svg)](https://wandbox.org/permlink/venR3Ko2Q4tlvcVk) [![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](https://godbolt.org/z/htwpnb)
+
+**Contents**
+
+- [Example usage](#example-usage)
+- [In a nutshell](#in-a-nutshell)
+- [License](#license)
+- [Dependencies](#dependencies)
+- [Installation and use](#installation-and-use)
+- [Synopsis](#synopsis)
+- [Reported to work with](#reported-to-work-with)
+- [Building the tests](#building-the-tests)
+- [Other implementations of span](#other-implementations-of-span)
+- [Notes and references](#notes-and-references)
+- [Appendix](#appendix)
+
+## Example usage
+
+```cpp
+#include "nonstd/span.hpp"
+#include <array>
+#include <vector>
+#include <iostream>
+
+std::ptrdiff_t size( nonstd::span<const int> spn )
+{
+ return spn.size();
+}
+
+int main()
+{
+ int arr[] = { 1, };
+
+ std::cout <<
+ "C-array:" << size( arr ) <<
+ " array:" << size( std::array <int, 2>{ 1, 2, } ) <<
+ " vector:" << size( std::vector<int >{ 1, 2, 3, } );
+}
+```
+
+### Compile and run
+
+```bash
+prompt> g++ -std=c++11 -Wall -I../include -o 01-basic.exe 01-basic.cpp && 01-basic.exe
+C-array:1 array:2 vector:3
+```
+
+## In a nutshell
+
+**span lite** is a single-file header-only library to provide a bounds-safe view for sequences of objects. The library provides a [C++20-like span](http://en.cppreference.com/w/cpp/container/span) for use with C++98 and later. If available, `std::span` is used, unless [configured otherwise](#configuration). *span-lite* can detect the presence of [*byte-lite*](https://github.com/martinmoene/byte-lite) and if present, it provides `as_bytes()` and `as_writable_bytes()` also for C++14 and earlier.
+
+**Features and properties of span lite** are ease of installation (single header), freedom of dependencies other than the standard library. To compensate for the class template argument deduction that is missing from pre-C++17 compilers, `nonstd::span` can provide `make_span` functions. See [configuration](#configuration).
+
+## License
+
+*span lite* is distributed under the [Boost Software License](https://github.com/martinmoene/span-lite/blob/master/LICENSE.txt).
+
+## Dependencies
+
+*span lite* has no other dependencies than the [C++ standard library](http://en.cppreference.com/w/cpp/header).
+
+## Installation and use
+
+*span lite* is a single-file header-only library. Put `span.hpp` in the [include](include) folder directly into the project source tree or somewhere reachable from your project.
+
+## Synopsis
+
+**Contents**
+[Documentation of `std::span`](#documentation-of-stdspan)
+[Later additions](#later-additions)
+[Non-standard extensions](#non-standard-extensions)
+[Configuration](#configuration)
+
+## Documentation of `std::span`
+
+Depending on the compiler and C++-standard used, `nonstd::span` behaves less or more like `std::span`. To get an idea of the capabilities of `nonstd::span` with your configuration, look at the output of the [tests](test/span.t.cpp), issuing `span-main.t --pass @`. For `std::span`, see its [documentation at cppreference](http://en.cppreference.com/w/cpp/container/span).
+
+## Later additions
+
+### `back()` and `front()`
+
+*span lite* can provide `back()` and `front()` member functions for element access. See the table below and section [configuration](#configuration).
+
+## Non-standard extensions
+
+### Construct from std::initializer_list (p2447)
+
+*span lite* can provide construction from a std::initializer_list<> as a constant set of values as proposed in [p2447](https://wg21.link/p2447). See the table below and section [configuration](#configuration).
+
+### Construct from container
+
+To construct a span from a container with compilers that cannot constrain such a single-parameter constructor to containers, *span lite* provides a constructor that takes an additional parameter of type `with_container_t`. Use `with_container` as value for this parameter. See the table below and section [configuration](#configuration).
+
+### Construct from `std::array` with const data
+
+*span lite* can provide construction of a span from a `std::array` with const data. See the table below and section [configuration](#configuration).
+
+### `operator()`
+
+*span lite* can provide member function call `operator()` for element access. It is equivalent to `operator[]` and has been marked `[[deprecated]]`. Its main purpose is to provide a migration path.
+
+### `at()`
+
+*span lite* can provide member function `at()` for element access. Unless exceptions have been disabled, `at()` throws std::out_of_range if the index falls outside the span. With exceptions disabled, `at(index_t)` delegates bounds checking to `operator[](index_t)`. See the table below and sections [configuration](#configuration) and [disable exceptions](#disable-exceptions).
+
+### `swap()`
+
+*span lite* can provide a `swap()`member function. See the table below and section [configuration](#configuration).
+
+### `operator==()` and other comparison functions
+
+*span lite* can provide functions to compare the content of two spans. However, C++20's span will not provide comparison and _span lite_ will omit comparison at default in the near future. See the table below and section [configuration](#configuration). See also [Revisiting Regular Types](#regtyp).
+
+### `same()`
+
+*span lite* can provide function `same()` to determine if two spans refer as identical spans to the same data via the same type. If `same()` is enabled, `operator==()` incorporates it in its comparison. See the table below and section [configuration](#configuration).
+
+### `first()`, `last()` and `subspan()`
+
+*span lite* can provide functions `first()`, `last()` and `subspan()` to avoid having to use the *dot template* syntax when the span is a dependent type. See the table below and section [configuration](#configuration).
+
+### `make_span()`
+
+*span lite* can provide `make_span()` creator functions to compensate for the class template argument deduction that is missing from pre-C++17 compilers. See the table below and section [configuration](#configuration).
+
+### `byte_span()`
+
+*span lite* can provide `byte_span()` creator functions to represent an object as a span of bytes. This requires the C++17 type `std::byte` to be available. See the table below and section [configuration](#configuration).
+
+| Kind | std | Function or method |
+|--------------------|------|--------------------|
+| **Macro** |&nbsp;| macro **`span_FEATURE_WITH_INITIALIZER_LIST_P2447`** |
+| **Constructor**<br>&nbsp; |&nbsp;| constexpr explicit **span**( std::initializer_list&lt;value_type> il ) noexcept<br>explicit for non-dynamic extent |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Macro**<br>&nbsp;|&nbsp;| macro **`span_FEATURE_WITH_CONTAINER`**<br>macro **`span_FEATURE_WITH_CONTAINER_TO_STD`** |
+| **Types** |&nbsp;| **with_container_t** type to disambiguate below constructors |
+| **Objects** |&nbsp;| **with_container** value to disambiguate below constructors |
+| **Constructors** |&nbsp;| macro **`span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE`**|
+| &nbsp; |&nbsp;| template&lt;class Container><br>constexpr **span**(with_container_t, Container & cont) |
+| &nbsp; |&nbsp;| template&lt;class Container><br>constexpr **span**(with_container_t, Container const & cont) |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Methods** |&nbsp;| macro **`span_FEATURE_MEMBER_CALL_OPERATOR`** |
+| &nbsp; |&nbsp;| constexpr reference **operator()**(index_t idx) const<br>Equivalent to **operator[]**(), marked `[[deprecated]]` |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Methods** |&nbsp;| macro **`span_FEATURE_MEMBER_AT`** |
+| &nbsp; |&nbsp;| constexpr reference **at**(index_t idx) const<br>May throw std::out_of_range exception |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Methods** |&nbsp;| macro **`span_FEATURE_MEMBER_BACK_FRONT`** (on since v0.5.0) |
+| &nbsp; |&nbsp;| constexpr reference **back()** const noexcept |
+| &nbsp; |&nbsp;| constexpr reference **front()** const noexcept |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Method** |&nbsp;| macro **`span_FEATURE_MEMBER_SWAP`** |
+| &nbsp; |&nbsp;| constexpr void **swap**(span & other) noexcept |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Free functions** |&nbsp;| macro **`span_FEATURE_COMPARISON`** |
+|<br><br>== != < > <= >= |&nbsp;| template&lt;class T1, index_t E1, class T2, index_t E2><br>constexpr bool<br>**operator==**( span<T1,E1> const & l, span<T2,E2> const & r) noexcept |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Free function** |&nbsp;| macro **`span_FEATURE_SAME`** |
+| &nbsp; |&nbsp;| template&lt;class T1, index_t E1, class T2, index_t E2><br>constexpr bool<br>**same**( span<T1,E1> const & l, span<T2,E2> const & r) noexcept |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Free functions**<br>&nbsp;<br>&nbsp; |&nbsp;| macros **`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB`**,<br>**`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN`**,<br>**`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER`** |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Free functions** |&nbsp;| macro **`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN`** |
+| &nbsp; | &nbsp; | template&lt;extent_t Count, class T, extent_t Extent><br>constexpr span&lt;T,Count><br>**first**(span&lt;T,Extent> spn) |
+| &nbsp; | &nbsp; | template&lt;class T, extent_t Extent ><br>constexpr span&lt;T><br>**first**(span&lt;T,Extent> spn, size_t count) |
+| &nbsp; | &nbsp; | template&lt;extent_t Count, class T, extent_t Extent><br>constexpr span&lt;T,Count><br>**last**(span&lt;T,Extent> spn) |
+| &nbsp; | &nbsp; | template&lt;class T, extent_t Extent ><br>constexpr span&lt;T><br>**last**(span&lt;T,Extent> spn, size_t count) |
+| &nbsp; | &nbsp; | template&lt;size_t Offset, extent_t Count, class T, extent_t Extent><br>constexpr span&lt;T, Count><br>**subspan**(span&lt;T, Extent> spn) |
+| &nbsp; | &nbsp; | template&lt;class T, extent_t Extent><br>constexpr span&lt;T><br>**subspan**( span&lt;T, Extent> spn, size_t offset, extent_t count = dynamic_extent) |
+| &nbsp; |&nbsp;| &nbsp; |
+| **Free functions** |&nbsp;| macro **`span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER`** |
+| &nbsp; | >= C++11 | template&lt;extent_t Count, class T><br>constexpr auto<br>**first**(T & t) ->... |
+| &nbsp; | >= C++11 | template&lt;class T><br>constexpr auto<br>**first**(T & t, index_t count) ->... |
+| &nbsp; | >= C++11 | template&lt;extent_t Count, class T><br>constexpr auto<br>**last**(T & t) ->... |
+| &nbsp; | >= C++11 | template&lt;class T><br>constexpr auto<br>**last**(T & t, extent_t count) ->... |
+| &nbsp; | >= C++11 | template&lt;index_t Offset, extent_t Count = dynamic_extent, class T><br>constexpr auto<br>**subspan**(T & t) ->... |
+| &nbsp; | >= C++11 | template&lt;class T><br>constexpr auto<br>**subspan**(T & t, index_t offset, extent_t count = dynamic_extent) ->... |
+| &nbsp; | &nbsp; | &nbsp; |
+| **Free functions**<br>&nbsp; |&nbsp;| macro **`span_FEATURE_MAKE_SPAN`**<br>macro **`span_FEATURE_MAKE_SPAN_TO_STD`** |
+| &nbsp; | &nbsp; | template&lt;class T><br>constexpr span&lt;T><br>**make_span**(T \* first, T \* last) noexcept |
+| &nbsp; | &nbsp; | template&lt;class T><br>constexpr span&lt;T><br>**make_span**(T \* ptr, index_t count) noexcept |
+| &nbsp; | &nbsp; | template&lt;class T, size_t N><br>constexpr span&lt;T,N><br>**make_span**(T (&arr)[N]) noexcept |
+| &nbsp; | >= C++11 | template&lt;class T, size_t N><br>constexpr span&lt;T,N><br>**make_span**(std::array&lt;T,N> & arr) noexcept |
+| &nbsp; | >= C++11 | template&lt;class T, size_t N><br>constexpr span&lt;const T,N><br>**make_span**(std::array&lt;T,N > const & arr) noexcept |
+| &nbsp; | >= C++11 | template&lt;class T><br>constexpr span&lt;T><br>**make_span**(std::initializer_list&lt;T> il) noexcept |
+| &nbsp; | >= C++11 | template&lt;class Container><br>constexpr auto<br>**make_span**(Container & cont) -><br>&emsp;span&lt;typename Container::value_type> noexcept |
+| &nbsp; | >= C++11 | template&lt;class Container><br>constexpr auto<br>**make_span**(Container const & cont) -><br>&emsp;span&lt;const typename Container::value_type> noexcept |
+| &nbsp; | &nbsp; | template&lt;class Container><br>span&lt;typename Container::value_type><br>**make_span**( with_container_t, Container & cont ) |
+| &nbsp; | &nbsp; | template&lt;class Container><br>span&lt;const typename Container::value_type><br>**make_span**( with_container_t, Container const & cont ) |
+| &nbsp; | < C++11 | template&lt;class T, Allocator><br>span&lt;T><br>**make_span**(std::vector&lt;T, Allocator> & cont) |
+| &nbsp; | < C++11 | template&lt;class T, Allocator><br>span&lt;const T><br>**make_span**(std::vector&lt;T, Allocator> const & cont) |
+| &nbsp; | &nbsp; | &nbsp; |
+| **Free functions** |&nbsp;| macro **`span_FEATURE_BYTE_SPAN`** |
+| &nbsp; | >= C++11 | template&lt;class T><br>span&lt;T, sizeof(T)><br>**byte_span**(T & t) |
+| &nbsp; | >= C++11 | template&lt;class T><br>span&lt;const T, sizeof(T)><br>**byte_span**(T const & t) |
+
+## Configuration
+
+### Tweak header
+
+If the compiler supports [`__has_include()`](https://en.cppreference.com/w/cpp/preprocessor/include), *span lite* supports the [tweak header](https://vector-of-bool.github.io/2020/10/04/lib-configuration.html) mechanism. Provide your *tweak header* as `nonstd/span.tweak.hpp` in a folder in the include-search-path. In the tweak header, provide definitions as documented below, like `#define span_CONFIG_NO_EXCEPTIONS 1`.
+
+### Standard selection macro
+
+\-D<b>span\_CPLUSPLUS</b>=199711L
+Define this macro to override the auto-detection of the supported C++ standard, if your compiler does not set the `__cplusplus` macro correctly.
+
+### Select `std::span` or `nonstd::span`
+
+At default, *span lite* uses `std::span` if it is available and lets you use it via namespace `nonstd`. You can however override this default and explicitly request to use `std::span` or span lite's `nonstd::span` as `nonstd::span` via the following macros.
+
+-D<b>span\_CONFIG\_SELECT\_SPAN</b>=span_SPAN_DEFAULT
+Define this to `span_SPAN_STD` to select `std::span` as `nonstd::span`. Define this to `span_SPAN_NONSTD` to select `nonstd::span` as `nonstd::span`. Default is undefined, which has the same effect as defining to `span_SPAN_DEFAULT`.
+
+### Select extent type
+
+-D<b>span_CONFIG_EXTENT_TYPE</b>=std::size_t
+Define this to `std::ptrdiff_t` to use the signed type. The default is `std::size_t`, as in C++20 (since v0.7.0).
+
+### Select size type
+
+-D<b>span_CONFIG_SIZE_TYPE</b>=std::size_t
+Define this to `std::ptrdiff_t` to use the signed type. The default is `std::size_t`, as in C++20 (since v0.7.0). Note `span_CONFIG_SIZE_TYPE` replaces `span_CONFIG_INDEX_TYPE` which is deprecated.
+
+### Disable exceptions
+
+-D<b>span_CONFIG_NO_EXCEPTIONS</b>=0
+Define this to 1 if you want to compile without exceptions. If not defined, the header tries and detect if exceptions have been disabled (e.g. via `-fno-exceptions`). Disabling exceptions will force contract violation to use termination, see [contract violation macros](#contract-violation-response-macros). Default is undefined.
+
+### Provide construction from std::initializer_list (p2447)
+
+-D<b>span_FEATURE_WITH_INITIALIZER_LIST_P2447</b>=0
+Define this to 1 to enable constructing a span from a std::initializer_list<> as a constant set of values. See proposal [p2447](https://wg21.link/p2447). Default is undefined.
+
+### Provide construction using `with_container_t`
+
+-D<b>span_FEATURE_WITH_CONTAINER</b>=0
+Define this to 1 to enable constructing a span using `with_container_t`. Note that `span_FEATURE_WITH_CONTAINER` takes precedence over `span_FEATURE_WITH_CONTAINER_TO_STD`. Default is undefined.
+
+-D<b>span_FEATURE_WITH_CONTAINER_TO_STD</b>=*n*
+Define this to the highest C++ language version for which to enable constructing a span using `with_container_t`, like 98, 03, 11, 14, 17, 20. You can use 99 for inclusion with any standard, but prefer to use `span_FEATURE_WITH_CONTAINER` for this. Note that `span_FEATURE_WITH_CONTAINER` takes precedence over `span_FEATURE_WITH_CONTAINER_TO_STD`. Default is undefined.
+
+### Provide construction from `std::array` with const data
+
+-D<b>span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE</b>=0
+Define this to 1 to enable constructing a span from a std::array with const data. Default is undefined.
+
+### Provide `operator()` member function
+
+-D<b>span_FEATURE_MEMBER_CALL_OPERATOR</b>=0
+Define this to 1 to provide member function `operator()`for element access. It is equivalent to `operator[]` and has been marked `[[deprecated]]`. Its main purpose is to provide a migration path. Default is undefined.
+
+### Provide `at()` member function
+
+-D<b>span_FEATURE_MEMBER_AT</b>=0
+Define this to 1 to provide member function `at()`. Define this to 2 to include index and size in message of std::out_of_range exception. Default is undefined.
+
+### Provide `back()` and `front()` member functions
+
+-D<b>span_FEATURE_MEMBER_BACK_FRONT</b>=1 _(on since v0.5.0)_
+Define this to 0 to omit member functions `back()` and `front()`. Default is undefined.
+
+### Provide `swap()` member function
+
+-D<b>span_FEATURE_MEMBER_SWAP</b>=0
+Define this to 1 to provide member function `swap()`. Default is undefined.
+
+### Provide `operator==()` and other comparison functions
+
+-D<b>span_FEATURE_COMPARISON</b>=0
+Define this to 1 to include the comparison functions to compare the content of two spans. C++20's span does not provide comparison and _span lite_ omits comparison from v0.7.0. Default is undefined.
+
+### Provide `same()` function
+
+-D<b>span_FEATURE_SAME</b>=0
+Define this to 1 to provide function `same()` to test if two spans refer as identical spans to the same data via the same type. If `same()` is enabled, `operator==()` incorporates it in its comparison. Default is undefined.
+
+### Provide `first()`, `last()` and `subspan()` functions
+
+-D<b>span_FEATURE_NON_MEMBER_FIRST_LAST_SUB</b>=0
+Define this to 1 to enable both `span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN` and `span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER`. Default is undefined.
+
+-D<b>span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN</b>=0
+Define this to 1 to provide functions `first()`, `last()` and `subspan()` that take a `span<>` (work with C++98). This implies `span_FEATURE_MAKE_SPAN` to provide functions `make_span()` that are required for this feature. Default is undefined.
+
+-D<b>span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER</b>=0
+Define this to 1 to provide functions `first()`, `last()` and `subspan()` that take a compatible container (requires C++11). This implies `span_FEATURE_MAKE_SPAN` to provide functions `make_span()` that are required for this feature. Default is undefined.
+
+### Provide `make_span()` functions
+
+-D<b>span_FEATURE_MAKE_SPAN</b>=0
+Define this to 1 to provide creator functions `nonstd::make_span()`. This feature is implied by using `span_FEATURE_NON_MEMBER_FIRST_LAST_SUB=1`. Note that `span_FEATURE_MAKE_SPAN` takes precedence over `span_FEATURE_MAKE_SPAN_TO_STD`. Default is undefined.
+
+-D<b>span_FEATURE_MAKE_SPAN_TO_STD</b>=*n*
+Define this to the highest C++ language version for which to provide creator functions `nonstd::make_span()`, like 98, 03, 11, 14, 17, 20. You can use 99 for inclusion with any standard, but prefer to use `span_FEATURE_MAKE_SPAN` for this. Note that `span_FEATURE_MAKE_SPAN` takes precedence over `span_FEATURE_MAKE_SPAN_TO_STD`. Default is undefined.
+
+### Provide `byte_span()` functions
+
+-D<b>span_FEATURE_BYTE_SPAN</b>=0
+Define this to 1 to provide creator functions `nonstd::byte_span()`. Default is undefined.
+
+### Contract violation response macros
+
+*span-lite* provides contract violation response control as suggested in proposal [N4415](http://wg21.link/n4415).
+
+\-D<b>span\_CONFIG\_CONTRACT\_LEVEL\_ON</b> (*default*)
+Define this macro to include both `span_EXPECTS` and `span_ENSURES` in the code. This is the default case.
+
+\-D<b>span\_CONFIG\_CONTRACT\_LEVEL\_OFF</b>
+Define this macro to exclude both `span_EXPECTS` and `span_ENSURES` from the code.
+
+\-D<b>span\_CONFIG_CONTRACT\_LEVEL\_EXPECTS\_ONLY</b>
+Define this macro to include `span_EXPECTS` in the code and exclude `span_ENSURES` from the code.
+
+\-D<b>span\_CONFIG\_CONTRACT\_LEVEL\_ENSURES\_ONLY</b>
+Define this macro to exclude `span_EXPECTS` from the code and include `span_ENSURES` in the code.
+
+\-D<b>span\_CONFIG\_CONTRACT\_VIOLATION\_TERMINATES</b> (*default*)
+Define this macro to call `std::terminate()` on a contract violation in `span_EXPECTS`, `span_ENSURES`. This is the default case.
+
+\-D<b>span\_CONFIG\_CONTRACT\_VIOLATION\_THROWS</b>
+Define this macro to throw an exception of implementation-defined type that is derived from `std::runtime_exception` instead of calling `std::terminate()` on a contract violation in `span_EXPECTS` and `span_ENSURES`. See also [disable exceptions](#disable-exceptions).
+
+Reported to work with
+--------------------
+The table below mentions the compiler versions *span lite* is reported to work with.
+
+OS | Compiler | Where | Versions |
+------------:|:-----------|:--------|:---------|
+**GNU/Linux**| Clang/LLVM | Travis | 3.5.0, 3.6.2, 3.7.1, 3.8.0, 3.9.1, 4.0.1 |
+ &nbsp; | GCC | Travis | 5.5.0, 6.4.0, 7.3.0 |
+**OS X** | ? | Local | ? |
+**Windows** | Clang/LLVM | Local | 6.0.0 |
+&nbsp; | GCC | Local | 7.2.0 |
+&nbsp; | Visual C++<br>(Visual Studio)| Local | 8 (2005), 10 (2010), 11 (2012),<br>12 (2013), 14 (2015), 15 (2017) |
+&nbsp; | Visual C++<br>(Visual Studio)| AppVeyor | 10 (2010), 11 (2012),<br>12 (2013), 14 (2015), 15 (2017) |
+
+## Building the tests
+
+To build the tests you need:
+
+- [CMake](http://cmake.org), version 3.0 or later to be installed and in your PATH.
+- A [suitable compiler](#reported-to-work-with).
+
+The [*lest* test framework](https://github.com/martinmoene/lest) is included in the [test folder](test).
+
+The following steps assume that the [*span lite* source code](https://github.com/martinmoene/span-lite) has been cloned into a directory named `./span-lite`.
+
+1. Create a directory for the build outputs.
+
+ cd ./span-lite
+ md build && cd build
+
+2. Configure CMake to use the compiler of your choice (run `cmake --help` for a list).
+
+ cmake -G "Unix Makefiles" -DSPAN_LITE_OPT_BUILD_TESTS=ON ..
+
+3. Optional. You can control above configuration through the following options:
+
+ `-DSPAN_LITE_OPT_BUILD_TESTS=ON`: build the tests for span, default off
+ `-DSPAN_LITE_OPT_BUILD_EXAMPLES=OFF`: build the examples, default off
+
+4. Build the test suite.
+
+ cmake --build .
+
+5. Run the test suite.
+
+ ctest -V
+
+All tests should pass, indicating your platform is supported and you are ready to use *span lite*.
+
+## Other implementations of span
+
+- *gsl-lite* [span](https://github.com/martinmoene/gsl-lite/blob/73c4f16f2b35fc174fc2f09d44d5ab13e5c638c3/include/gsl/gsl-lite.hpp#L1221).
+- Microsoft GSL [span](https://github.com/Microsoft/GSL/blob/master/include/gsl/span).
+- Google Abseil [span](https://github.com/abseil/abseil-cpp/blob/master/absl/types/span.h).
+- Marshall Clow's [libc++ span snippet](https://github.com/mclow/snippets/blob/master/span.cpp).
+- Tristan Brindle's [Implementation of C++20's std::span for older compilers](https://github.com/tcbrindle/span).
+- [Search _span c++_ on GitHub](https://github.com/search?l=C%2B%2B&q=span+c%2B%2B&type=Repositories&utf8=%E2%9C%93).
+
+## Notes and references
+
+*Interface and specification*
+
+- [span on cppreference](https://en.cppreference.com/w/cpp/container/span).
+- [p0122 - C++20 Proposal](http://wg21.link/p0122).
+- [span in C++20 Working Draft](http://eel.is/c++draft/views).
+
+*Presentations*
+
+- TBD
+
+*Proposals*
+
+- [p0122 - span: bounds-safe views for sequences of objects](http://wg21.link/p0122).
+- [p1024 - Usability Enhancements for std::span](http://wg21.link/p1024).
+- [p1419 - A SFINAE-friendly trait to determine the extent of statically sized containers](http://wg21.link/p1419).
+- [p0805 - Comparing Containers](http://wg21.link/p0805).
+- [p1085 - Should Span be Regular?](http://wg21.link/p0805).
+- [p0091 - Template argument deduction for class templates](http://wg21.link/p0091).
+- [p0856 - Restrict Access Property for mdspan and span](http://wg21.link/p0856).
+- [p1428 - Subscripts and sizes should be signed](http://wg21.link/p1428).
+- [p1089 - Sizes Should Only span Unsigned](http://wg21.link/p1089).
+- [p1227 - Signed size() functions](http://wg21.link/p1227).
+- [p1872 - span should have size_type, not index_type](http://wg21.link/p1872).
+- [p2447 - std::span and the missing constructor](https://wg21.link/p2447).
+- [lwg 3101 - span's Container constructors need another constraint](https://cplusplus.github.io/LWG/issue3101).
+- [Reddit - 2018-06 Rapperswil ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/8prqzm/2018_rapperswil_iso_c_committee_trip_report/)
+- [Reddit - 2018-11 San Diego ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/9vwvbz/2018_san_diego_iso_c_committee_trip_report_ranges/).
+- [Reddit - 2019-02 Kona ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/au0c4x/201902_kona_iso_c_committee_trip_report_c20/).
+- [Reddit - 2019-07 Cologne ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/cfk9de/201907_cologne_iso_c_committee_trip_report_the/)
+- [Reddit - 2019-11 Belfast ISO C++ Committee Trip Report](https://www.reddit.com/r/cpp/comments/dtuov8/201911_belfast_iso_c_committee_trip_report/)
+- <a id="regtyp"></a>Titus Winters. [Revisiting Regular Types](https://abseil.io/blog/20180531-regular-types). Abseil Blog. 31 May 2018.
+
+## Appendix
+
+### A.1 Compile-time information
+
+The version of *span lite* is available via tag `[.version]`. The following tags are available for information on the compiler and on the C++ standard library used: `[.compiler]`, `[.stdc++]`, `[.stdlanguage]` and `[.stdlibrary]`.
+
+### A.2 Span lite test specification
+
+<details>
+<summary>click to expand</summary>
+<p>
+
+```Text
+span<>: Terminates construction from a nullptr and a non-zero size (C++11)
+span<>: Terminates construction from two pointers in the wrong order
+span<>: Terminates construction from a null pointer and a non-zero size
+span<>: Terminates creation of a sub span of the first n elements for n exceeding the span
+span<>: Terminates creation of a sub span of the last n elements for n exceeding the span
+span<>: Terminates creation of a sub span outside the span
+span<>: Terminates access outside the span
+span<>: Throws on access outside the span via at(): std::out_of_range [span_FEATURE_MEMBER_AT>0][span_CONFIG_NO_EXCEPTIONS=0]
+span<>: Termination throws std::logic_error-derived exception [span_CONFIG_CONTRACT_VIOLATION_THROWS=1]
+span<>: Allows to default-construct
+span<>: Allows to construct from a nullptr and a zero size (C++11)
+span<>: Allows to construct from two pointers
+span<>: Allows to construct from two iterators
+span<>: Allows to construct from two iterators - empty range
+span<>: Allows to construct from two iterators - move-only element
+span<>: Allows to construct from an iterator and a size
+span<>: Allows to construct from an iterator and a size - empty range
+span<>: Allows to construct from an iterator and a size - move-only element
+span<>: Allows to construct from two pointers to const
+span<>: Allows to construct from a non-null pointer and a size
+span<>: Allows to construct from a non-null pointer to const and a size
+span<>: Allows to construct from a temporary pointer and a size
+span<>: Allows to construct from a temporary pointer to const and a size
+span<>: Allows to construct from any pointer and a zero size (C++98)
+span<>: Allows to construct from a pointer and a size via a deduction guide (C++17)
+span<>: Allows to construct from an iterator and a size via a deduction guide (C++17)
+span<>: Allows to construct from two iterators via a deduction guide (C++17)
+span<>: Allows to construct from a C-array
+span<>: Allows to construct from a C-array via a deduction guide (C++17)
+span<>: Allows to construct from a const C-array
+span<>: Allows to construct from a C-array with size via decay to pointer (potentially dangerous)
+span<>: Allows to construct from a const C-array with size via decay to pointer (potentially dangerous)
+span<>: Allows to construct from a std::initializer_list<> (C++11)
+span<>: Allows to construct from a std::initializer_list<> as a constant set of values (C++11, p2447)
+span<>: Allows to construct from a std::array<> (C++11)
+span<>: Allows to construct from a std::array via a deduction guide (C++17)
+span<>: Allows to construct from a std::array<> with const data (C++11, span_FEATURE_CONSTR..._ELEMENT_TYPE=1)
+span<>: Allows to construct from an empty std::array<> (C++11)
+span<>: Allows to construct from a container (std::vector<>)
+span<>: Allows to construct from a container via a deduction guide (std::vector<>, C++17)
+span<>: Allows to tag-construct from a container (std::vector<>)
+span<>: Allows to tag-construct from a const container (std::vector<>)
+span<>: Allows to copy-construct from another span of the same type
+span<>: Allows to copy-construct from another span of a compatible type
+span<>: Allows to copy-construct from a temporary span of the same type (C++11)
+span<>: Allows to copy-assign from another span of the same type
+span<>: Allows to copy-assign from a temporary span of the same type (C++11)
+span<>: Allows to create a sub span of the first n elements
+span<>: Allows to create a sub span of the last n elements
+span<>: Allows to create a sub span starting at a given offset
+span<>: Allows to create a sub span starting at a given offset with a given length
+span<>: Allows to observe an element via array indexing
+span<>: Allows to observe an element via call indexing
+span<>: Allows to observe an element via at() [span_FEATURE_MEMBER_AT>0]
+span<>: Allows to observe an element via data()
+span<>: Allows to observe the first element via front() [span_FEATURE_MEMBER_BACK_FRONT=1]
+span<>: Allows to observe the last element via back() [span_FEATURE_MEMBER_BACK_FRONT=1]
+span<>: Allows to change an element via array indexing
+span<>: Allows to change an element via call indexing
+span<>: Allows to change an element via at() [span_FEATURE_MEMBER_AT>0]
+span<>: Allows to change an element via data()
+span<>: Allows to change the first element via front() [span_FEATURE_MEMBER_BACK_FRONT=1]
+span<>: Allows to change the last element via back() [span_FEATURE_MEMBER_BACK_FRONT=1]
+span<>: Allows to swap with another span [span_FEATURE_MEMBER_SWAP=1]
+span<>: Allows forward iteration
+span<>: Allows const forward iteration
+span<>: Allows reverse iteration
+span<>: Allows const reverse iteration
+span<>: Allows to identify if a span is the same as another span [span_FEATURE_SAME=1]
+span<>: Allows to compare equal to another span of the same type [span_FEATURE_COMPARISON=1]
+span<>: Allows to compare unequal to another span of the same type [span_FEATURE_COMPARISON=1]
+span<>: Allows to compare less than another span of the same type [span_FEATURE_COMPARISON=1]
+span<>: Allows to compare less than or equal to another span of the same type [span_FEATURE_COMPARISON=1]
+span<>: Allows to compare greater than another span of the same type [span_FEATURE_COMPARISON=1]
+span<>: Allows to compare greater than or equal to another span of the same type [span_FEATURE_COMPARISON=1]
+span<>: Allows to compare to another span of the same type and different cv-ness [span_FEATURE_SAME=0]
+span<>: Allows to compare empty spans as equal [span_FEATURE_COMPARISON=1]
+span<>: Allows to test for empty span via empty(), empty case
+span<>: Allows to test for empty span via empty(), non-empty case
+span<>: Allows to obtain the number of elements via size()
+span<>: Allows to obtain the number of elements via ssize()
+span<>: Allows to obtain the number of bytes via size_bytes()
+span<>: Allows to view the elements as read-only bytes
+span<>: Allows to view and change the elements as writable bytes
+make_span() [span_FEATURE_MAKE_SPAN_TO_STD=99]
+make_span(): Allows building from two pointers
+make_span(): Allows building from two const pointers
+make_span(): Allows building from a non-null pointer and a size
+make_span(): Allows building from a non-null const pointer and a size
+make_span(): Allows building from a C-array
+make_span(): Allows building from a const C-array
+make_span(): Allows building from a std::initializer_list<> (C++11)
+make_span(): Allows building from a std::initializer_list<> as a constant set of values (C++11)
+make_span(): Allows building from a std::array<> (C++11)
+make_span(): Allows building from a const std::array<> (C++11)
+make_span(): Allows building from a container (std::vector<>)
+make_span(): Allows building from a const container (std::vector<>)
+make_span(): Allows building from a container (with_container_t, std::vector<>)
+make_span(): Allows building from a const container (with_container_t, std::vector<>)
+byte_span() [span_FEATURE_BYTE_SPAN=1]
+byte_span(): Allows building a span of std::byte from a single object (C++17, byte-lite)
+byte_span(): Allows building a span of const std::byte from a single const object (C++17, byte-lite)
+first(), last(), subspan() [span_FEATURE_NON_MEMBER_FIRST_LAST_SUB=1]
+first(): Allows to create a sub span of the first n elements (span, template parameter)
+first(): Allows to create a sub span of the first n elements (span, function parameter)
+first(): Allows to create a sub span of the first n elements (compatible container, template parameter)
+first(): Allows to create a sub span of the first n elements (compatible container, function parameter)
+last(): Allows to create a sub span of the last n elements (span, template parameter)
+last(): Allows to create a sub span of the last n elements (span, function parameter)
+last(): Allows to create a sub span of the last n elements (compatible container, template parameter)
+last(): Allows to create a sub span of the last n elements (compatible container, function parameter)
+subspan(): Allows to create a sub span starting at a given offset (span, template parameter)
+subspan(): Allows to create a sub span starting at a given offset (span, function parameter)
+subspan(): Allows to create a sub span starting at a given offset (compatible container, template parameter)
+subspan(): Allows to create a sub span starting at a given offset (compatible container, function parameter)
+size(): Allows to obtain the number of elements via size()
+ssize(): Allows to obtain the number of elements via ssize()
+tuple_size<>: Allows to obtain the number of elements via std::tuple_size<> (C++11)
+tuple_element<>: Allows to obtain an element via std::tuple_element<> (C++11)
+tuple_element<>: Allows to obtain an element via std::tuple_element_t<> (C++11)
+get<I>(spn): Allows to access an element via std::get<>()
+tweak header: reads tweak header if supported [tweak]
+```
+
+</p>
+</details>
diff --git a/src/shared/span/span.hpp b/src/shared/span/span.hpp
new file mode 100644
index 000000000..9a7182f5b
--- /dev/null
+++ b/src/shared/span/span.hpp
@@ -0,0 +1,1947 @@
+//
+// span for C++98 and later.
+// Based on http://wg21.link/p0122r7
+// For more information see https://github.com/martinmoene/span-lite
+//
+// Copyright 2018-2021 Martin Moene
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef NONSTD_SPAN_HPP_INCLUDED
+#define NONSTD_SPAN_HPP_INCLUDED
+
+#define span_lite_MAJOR 0
+#define span_lite_MINOR 11
+#define span_lite_PATCH 0
+
+#define span_lite_VERSION span_STRINGIFY(span_lite_MAJOR) "." span_STRINGIFY(span_lite_MINOR) "." span_STRINGIFY(span_lite_PATCH)
+
+#define span_STRINGIFY( x ) span_STRINGIFY_( x )
+#define span_STRINGIFY_( x ) #x
+
+// span configuration:
+
+#define span_SPAN_DEFAULT 0
+#define span_SPAN_NONSTD 1
+#define span_SPAN_STD 2
+
+// tweak header support:
+
+#ifdef __has_include
+# if __has_include(<nonstd/span.tweak.hpp>)
+# include <nonstd/span.tweak.hpp>
+# endif
+#define span_HAVE_TWEAK_HEADER 1
+#else
+#define span_HAVE_TWEAK_HEADER 0
+//# pragma message("span.hpp: Note: Tweak header not supported.")
+#endif
+
+// span selection and configuration:
+
+#define span_HAVE( feature ) ( span_HAVE_##feature )
+
+#ifndef span_CONFIG_SELECT_SPAN
+# define span_CONFIG_SELECT_SPAN ( span_HAVE_STD_SPAN ? span_SPAN_STD : span_SPAN_NONSTD )
+#endif
+
+#ifndef span_CONFIG_EXTENT_TYPE
+# define span_CONFIG_EXTENT_TYPE std::size_t
+#endif
+
+#ifndef span_CONFIG_SIZE_TYPE
+# define span_CONFIG_SIZE_TYPE std::size_t
+#endif
+
+#ifdef span_CONFIG_INDEX_TYPE
+# error `span_CONFIG_INDEX_TYPE` is deprecated since v0.7.0; it is replaced by `span_CONFIG_SIZE_TYPE`.
+#endif
+
+// span configuration (features):
+
+#ifndef span_FEATURE_WITH_INITIALIZER_LIST_P2447
+# define span_FEATURE_WITH_INITIALIZER_LIST_P2447 0
+#endif
+
+#ifndef span_FEATURE_WITH_CONTAINER
+#ifdef span_FEATURE_WITH_CONTAINER_TO_STD
+# define span_FEATURE_WITH_CONTAINER span_IN_STD( span_FEATURE_WITH_CONTAINER_TO_STD )
+#else
+# define span_FEATURE_WITH_CONTAINER 0
+# define span_FEATURE_WITH_CONTAINER_TO_STD 0
+#endif
+#endif
+
+#ifndef span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE
+# define span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE 0
+#endif
+
+#ifndef span_FEATURE_MEMBER_AT
+# define span_FEATURE_MEMBER_AT 0
+#endif
+
+#ifndef span_FEATURE_MEMBER_BACK_FRONT
+# define span_FEATURE_MEMBER_BACK_FRONT 1
+#endif
+
+#ifndef span_FEATURE_MEMBER_CALL_OPERATOR
+# define span_FEATURE_MEMBER_CALL_OPERATOR 0
+#endif
+
+#ifndef span_FEATURE_MEMBER_SWAP
+# define span_FEATURE_MEMBER_SWAP 0
+#endif
+
+#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB 0
+#elif span_FEATURE_NON_MEMBER_FIRST_LAST_SUB
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 1
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 1
+#endif
+
+#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 0
+#endif
+
+#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER
+# define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 0
+#endif
+
+#ifndef span_FEATURE_COMPARISON
+# define span_FEATURE_COMPARISON 0 // Note: C++20 does not provide comparison
+#endif
+
+#ifndef span_FEATURE_SAME
+# define span_FEATURE_SAME 0
+#endif
+
+#if span_FEATURE_SAME && !span_FEATURE_COMPARISON
+# error `span_FEATURE_SAME` requires `span_FEATURE_COMPARISON`
+#endif
+
+#ifndef span_FEATURE_MAKE_SPAN
+#ifdef span_FEATURE_MAKE_SPAN_TO_STD
+# define span_FEATURE_MAKE_SPAN span_IN_STD( span_FEATURE_MAKE_SPAN_TO_STD )
+#else
+# define span_FEATURE_MAKE_SPAN 0
+# define span_FEATURE_MAKE_SPAN_TO_STD 0
+#endif
+#endif
+
+#ifndef span_FEATURE_BYTE_SPAN
+# define span_FEATURE_BYTE_SPAN 0
+#endif
+
+// Control presence of exception handling (try and auto discover):
+
+#ifndef span_CONFIG_NO_EXCEPTIONS
+# if defined(_MSC_VER)
+# include <cstddef> // for _HAS_EXCEPTIONS
+# endif
+# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
+# define span_CONFIG_NO_EXCEPTIONS 0
+# else
+# define span_CONFIG_NO_EXCEPTIONS 1
+# undef span_CONFIG_CONTRACT_VIOLATION_THROWS
+# undef span_CONFIG_CONTRACT_VIOLATION_TERMINATES
+# define span_CONFIG_CONTRACT_VIOLATION_THROWS 0
+# define span_CONFIG_CONTRACT_VIOLATION_TERMINATES 1
+# endif
+#endif
+
+// Control pre- and postcondition violation behaviour:
+
+#if defined( span_CONFIG_CONTRACT_LEVEL_ON )
+# define span_CONFIG_CONTRACT_LEVEL_MASK 0x11
+#elif defined( span_CONFIG_CONTRACT_LEVEL_OFF )
+# define span_CONFIG_CONTRACT_LEVEL_MASK 0x00
+#elif defined( span_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY )
+# define span_CONFIG_CONTRACT_LEVEL_MASK 0x01
+#elif defined( span_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY )
+# define span_CONFIG_CONTRACT_LEVEL_MASK 0x10
+#else
+# define span_CONFIG_CONTRACT_LEVEL_MASK 0x11
+#endif
+
+#if defined( span_CONFIG_CONTRACT_VIOLATION_THROWS )
+# define span_CONFIG_CONTRACT_VIOLATION_THROWS_V span_CONFIG_CONTRACT_VIOLATION_THROWS
+#else
+# define span_CONFIG_CONTRACT_VIOLATION_THROWS_V 0
+#endif
+
+#if defined( span_CONFIG_CONTRACT_VIOLATION_THROWS ) && span_CONFIG_CONTRACT_VIOLATION_THROWS && \
+ defined( span_CONFIG_CONTRACT_VIOLATION_TERMINATES ) && span_CONFIG_CONTRACT_VIOLATION_TERMINATES
+# error Please define none or one of span_CONFIG_CONTRACT_VIOLATION_THROWS and span_CONFIG_CONTRACT_VIOLATION_TERMINATES to 1, but not both.
+#endif
+
+// C++ language version detection (C++23 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef span_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+# define span_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+# define span_CPLUSPLUS __cplusplus
+# endif
+#endif
+
+#define span_CPP98_OR_GREATER ( span_CPLUSPLUS >= 199711L )
+#define span_CPP11_OR_GREATER ( span_CPLUSPLUS >= 201103L )
+#define span_CPP14_OR_GREATER ( span_CPLUSPLUS >= 201402L )
+#define span_CPP17_OR_GREATER ( span_CPLUSPLUS >= 201703L )
+#define span_CPP20_OR_GREATER ( span_CPLUSPLUS >= 202002L )
+#define span_CPP23_OR_GREATER ( span_CPLUSPLUS >= 202300L )
+
+// C++ language version (represent 98 as 3):
+
+#define span_CPLUSPLUS_V ( span_CPLUSPLUS / 100 - (span_CPLUSPLUS > 200000 ? 2000 : 1994) )
+
+#define span_IN_STD( v ) ( ((v) == 98 ? 3 : (v)) >= span_CPLUSPLUS_V )
+
+#define span_CONFIG( feature ) ( span_CONFIG_##feature )
+#define span_FEATURE( feature ) ( span_FEATURE_##feature )
+#define span_FEATURE_TO_STD( feature ) ( span_IN_STD( span_FEATURE( feature##_TO_STD ) ) )
+
+// Use C++20 std::span if available and requested:
+
+#if span_CPP20_OR_GREATER && defined(__has_include )
+# if __has_include( <span> )
+# define span_HAVE_STD_SPAN 1
+# else
+# define span_HAVE_STD_SPAN 0
+# endif
+#else
+# define span_HAVE_STD_SPAN 0
+#endif
+
+#define span_USES_STD_SPAN ( (span_CONFIG_SELECT_SPAN == span_SPAN_STD) || ((span_CONFIG_SELECT_SPAN == span_SPAN_DEFAULT) && span_HAVE_STD_SPAN) )
+
+//
+// Use C++20 std::span:
+//
+
+#if span_USES_STD_SPAN
+
+#include <span>
+
+namespace nonstd {
+
+using std::span;
+using std::dynamic_extent;
+
+// Note: C++20 does not provide comparison
+// using std::operator==;
+// using std::operator!=;
+// using std::operator<;
+// using std::operator<=;
+// using std::operator>;
+// using std::operator>=;
+} // namespace nonstd
+
+#else // span_USES_STD_SPAN
+
+#include <algorithm>
+
+// Compiler versions:
+//
+// MSVC++ 6.0 _MSC_VER == 1200 span_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
+// MSVC++ 7.0 _MSC_VER == 1300 span_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
+// MSVC++ 7.1 _MSC_VER == 1310 span_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
+// MSVC++ 8.0 _MSC_VER == 1400 span_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
+// MSVC++ 9.0 _MSC_VER == 1500 span_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
+// MSVC++ 10.0 _MSC_VER == 1600 span_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
+// MSVC++ 11.0 _MSC_VER == 1700 span_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
+// MSVC++ 12.0 _MSC_VER == 1800 span_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
+// MSVC++ 14.0 _MSC_VER == 1900 span_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
+// MSVC++ 14.1 _MSC_VER >= 1910 span_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
+// MSVC++ 14.2 _MSC_VER >= 1920 span_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
+
+#if defined(_MSC_VER ) && !defined(__clang__)
+# define span_COMPILER_MSVC_VER (_MSC_VER )
+# define span_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
+#else
+# define span_COMPILER_MSVC_VER 0
+# define span_COMPILER_MSVC_VERSION 0
+#endif
+
+#define span_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
+
+#if defined(__clang__)
+# define span_COMPILER_CLANG_VERSION span_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#else
+# define span_COMPILER_CLANG_VERSION 0
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+# define span_COMPILER_GNUC_VERSION span_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define span_COMPILER_GNUC_VERSION 0
+#endif
+
+// half-open range [lo..hi):
+#define span_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
+
+// Compiler warning suppression:
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wundef"
+# pragma clang diagnostic ignored "-Wmismatched-tags"
+# define span_RESTORE_WARNINGS() _Pragma( "clang diagnostic pop" )
+
+#elif defined __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wundef"
+# define span_RESTORE_WARNINGS() _Pragma( "GCC diagnostic pop" )
+
+#elif span_COMPILER_MSVC_VER >= 1900
+# define span_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
+# define span_RESTORE_WARNINGS() __pragma(warning(pop ))
+
+// Suppress the following MSVC GSL warnings:
+// - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept'
+// - C26440, gsl::f.6 : function 'function' can be declared 'noexcept'
+// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
+// use brace initialization, gsl::narrow_cast or gsl::narrow
+// - C26473: gsl::t.1 : don't cast between pointer types where the source type and the target type are the same
+// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
+// - C26490: gsl::t.1 : don't use reinterpret_cast
+
+span_DISABLE_MSVC_WARNINGS( 26439 26440 26472 26473 26481 26490 )
+
+#else
+# define span_RESTORE_WARNINGS() /*empty*/
+#endif
+
+// Presence of language and library features:
+
+#ifdef _HAS_CPP0X
+# define span_HAS_CPP0X _HAS_CPP0X
+#else
+# define span_HAS_CPP0X 0
+#endif
+
+#define span_CPP11_80 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1400)
+#define span_CPP11_90 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1500)
+#define span_CPP11_100 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1600)
+#define span_CPP11_110 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1700)
+#define span_CPP11_120 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1800)
+#define span_CPP11_140 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1900)
+
+#define span_CPP14_000 (span_CPP14_OR_GREATER)
+#define span_CPP14_120 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1800)
+#define span_CPP14_140 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1900)
+
+#define span_CPP17_000 (span_CPP17_OR_GREATER)
+
+// Presence of C++11 language features:
+
+#define span_HAVE_ALIAS_TEMPLATE span_CPP11_140
+#define span_HAVE_AUTO span_CPP11_100
+#define span_HAVE_CONSTEXPR_11 span_CPP11_140
+#define span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG span_CPP11_120
+#define span_HAVE_EXPLICIT_CONVERSION span_CPP11_140
+#define span_HAVE_INITIALIZER_LIST span_CPP11_120
+#define span_HAVE_IS_DEFAULT span_CPP11_140
+#define span_HAVE_IS_DELETE span_CPP11_140
+#define span_HAVE_NOEXCEPT span_CPP11_140
+#define span_HAVE_NORETURN ( span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 480 ) )
+#define span_HAVE_NULLPTR span_CPP11_100
+#define span_HAVE_STATIC_ASSERT span_CPP11_100
+
+// Presence of C++14 language features:
+
+#define span_HAVE_CONSTEXPR_14 span_CPP14_000
+
+// Presence of C++17 language features:
+
+#define span_HAVE_DEPRECATED span_CPP17_000
+#define span_HAVE_NODISCARD span_CPP17_000
+
+// MSVC: template parameter deduction guides since Visual Studio 2017 v15.7
+
+#if defined(__cpp_deduction_guides)
+# define span_HAVE_DEDUCTION_GUIDES 1
+#else
+# define span_HAVE_DEDUCTION_GUIDES (span_CPP17_OR_GREATER && ! span_BETWEEN( span_COMPILER_MSVC_VER, 1, 1913 ))
+#endif
+
+// Presence of C++ library features:
+
+#define span_HAVE_ADDRESSOF span_CPP17_000
+#define span_HAVE_ARRAY span_CPP11_110
+#define span_HAVE_BYTE span_CPP17_000
+#define span_HAVE_CONDITIONAL span_CPP11_120
+#define span_HAVE_CONTAINER_DATA_METHOD (span_CPP11_140 || ( span_COMPILER_MSVC_VER >= 1500 && span_HAS_CPP0X ))
+#define span_HAVE_DATA span_CPP17_000
+#define span_HAVE_LONGLONG span_CPP11_80
+#define span_HAVE_REMOVE_CONST span_CPP11_110
+#define span_HAVE_SNPRINTF span_CPP11_140
+#define span_HAVE_STRUCT_BINDING span_CPP11_120
+#define span_HAVE_TYPE_TRAITS span_CPP11_90
+
+// Presence of byte-lite:
+
+#ifdef NONSTD_BYTE_LITE_HPP
+# define span_HAVE_NONSTD_BYTE 1
+#else
+# define span_HAVE_NONSTD_BYTE 0
+#endif
+
+// C++ feature usage:
+
+#if span_HAVE_ADDRESSOF
+# define span_ADDRESSOF(x) std::addressof(x)
+#else
+# define span_ADDRESSOF(x) (&x)
+#endif
+
+#if span_HAVE_CONSTEXPR_11
+# define span_constexpr constexpr
+#else
+# define span_constexpr /*span_constexpr*/
+#endif
+
+#if span_HAVE_CONSTEXPR_14
+# define span_constexpr14 constexpr
+#else
+# define span_constexpr14 /*span_constexpr*/
+#endif
+
+#if span_HAVE_EXPLICIT_CONVERSION
+# define span_explicit explicit
+#else
+# define span_explicit /*explicit*/
+#endif
+
+#if span_HAVE_IS_DELETE
+# define span_is_delete = delete
+#else
+# define span_is_delete
+#endif
+
+#if span_HAVE_IS_DELETE
+# define span_is_delete_access public
+#else
+# define span_is_delete_access private
+#endif
+
+#if span_HAVE_NOEXCEPT && ! span_CONFIG_CONTRACT_VIOLATION_THROWS_V
+# define span_noexcept noexcept
+#else
+# define span_noexcept /*noexcept*/
+#endif
+
+#if span_HAVE_NULLPTR
+# define span_nullptr nullptr
+#else
+# define span_nullptr NULL
+#endif
+
+#if span_HAVE_DEPRECATED
+# define span_deprecated(msg) [[deprecated(msg)]]
+#else
+# define span_deprecated(msg) /*[[deprecated]]*/
+#endif
+
+#if span_HAVE_NODISCARD
+# define span_nodiscard [[nodiscard]]
+#else
+# define span_nodiscard /*[[nodiscard]]*/
+#endif
+
+#if span_HAVE_NORETURN
+# define span_noreturn [[noreturn]]
+#else
+# define span_noreturn /*[[noreturn]]*/
+#endif
+
+// Other features:
+
+#define span_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+#define span_HAVE_ITERATOR_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
+
+// Additional includes:
+
+#if span_HAVE( ADDRESSOF )
+# include <memory>
+#endif
+
+#if span_HAVE( ARRAY )
+# include <array>
+#endif
+
+#if span_HAVE( BYTE )
+# include <cstddef>
+#endif
+
+#if span_HAVE( DATA )
+# include <iterator> // for std::data(), std::size()
+#endif
+
+#if span_HAVE( TYPE_TRAITS )
+# include <type_traits>
+#endif
+
+#if ! span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+# include <vector>
+#endif
+
+#if span_FEATURE( MEMBER_AT ) > 1
+# include <cstdio>
+#endif
+
+#if ! span_CONFIG( NO_EXCEPTIONS )
+# include <stdexcept>
+#endif
+
+// Contract violation
+
+#define span_ELIDE_CONTRACT_EXPECTS ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x01 ) )
+#define span_ELIDE_CONTRACT_ENSURES ( 0 == ( span_CONFIG_CONTRACT_LEVEL_MASK & 0x10 ) )
+
+#if span_ELIDE_CONTRACT_EXPECTS
+# define span_constexpr_exp span_constexpr
+# define span_EXPECTS( cond ) /* Expect elided */
+#else
+# define span_constexpr_exp span_constexpr14
+# define span_EXPECTS( cond ) span_CONTRACT_CHECK( "Precondition", cond )
+#endif
+
+#if span_ELIDE_CONTRACT_ENSURES
+# define span_constexpr_ens span_constexpr
+# define span_ENSURES( cond ) /* Ensures elided */
+#else
+# define span_constexpr_ens span_constexpr14
+# define span_ENSURES( cond ) span_CONTRACT_CHECK( "Postcondition", cond )
+#endif
+
+#define span_CONTRACT_CHECK( type, cond ) \
+ cond ? static_cast< void >( 0 ) \
+ : nonstd::span_lite::detail::report_contract_violation( span_LOCATION( __FILE__, __LINE__ ) ": " type " violation." )
+
+#ifdef __GNUG__
+# define span_LOCATION( file, line ) file ":" span_STRINGIFY( line )
+#else
+# define span_LOCATION( file, line ) file "(" span_STRINGIFY( line ) ")"
+#endif
+
+// Method enabling
+
+#if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+
+#define span_REQUIRES_0(VA) \
+ template< bool B = (VA), typename std::enable_if<B, int>::type = 0 >
+
+# if span_BETWEEN( span_COMPILER_MSVC_VERSION, 1, 140 )
+// VS 2013 and earlier seem to have trouble with SFINAE for default non-type arguments
+# define span_REQUIRES_T(VA) \
+ , typename = typename std::enable_if< ( VA ), nonstd::span_lite::detail::enabler >::type
+# else
+# define span_REQUIRES_T(VA) \
+ , typename std::enable_if< (VA), int >::type = 0
+# endif
+
+#define span_REQUIRES_R(R, VA) \
+ typename std::enable_if< (VA), R>::type
+
+#define span_REQUIRES_A(VA) \
+ , typename std::enable_if< (VA), void*>::type = nullptr
+
+#else
+
+# define span_REQUIRES_0(VA) /*empty*/
+# define span_REQUIRES_T(VA) /*empty*/
+# define span_REQUIRES_R(R, VA) R
+# define span_REQUIRES_A(VA) /*empty*/
+
+#endif
+
+namespace nonstd {
+namespace span_lite {
+
+// [views.constants], constants
+
+typedef span_CONFIG_EXTENT_TYPE extent_t;
+typedef span_CONFIG_SIZE_TYPE size_t;
+
+span_constexpr const extent_t dynamic_extent = static_cast<extent_t>( -1 );
+
+template< class T, extent_t Extent = dynamic_extent >
+class span;
+
+// Tag to select span constructor taking a container (prevent ms-gsl warning C26426):
+
+struct with_container_t { span_constexpr with_container_t() span_noexcept {} };
+const span_constexpr with_container_t with_container;
+
+// C++11 emulation:
+
+namespace std11 {
+
+#if span_HAVE( REMOVE_CONST )
+
+using std::remove_cv;
+using std::remove_const;
+using std::remove_volatile;
+
+#else
+
+template< class T > struct remove_const { typedef T type; };
+template< class T > struct remove_const< T const > { typedef T type; };
+
+template< class T > struct remove_volatile { typedef T type; };
+template< class T > struct remove_volatile< T volatile > { typedef T type; };
+
+template< class T >
+struct remove_cv
+{
+ typedef typename std11::remove_volatile< typename std11::remove_const< T >::type >::type type;
+};
+
+#endif // span_HAVE( REMOVE_CONST )
+
+#if span_HAVE( TYPE_TRAITS )
+
+using std::is_same;
+using std::is_signed;
+using std::integral_constant;
+using std::true_type;
+using std::false_type;
+using std::remove_reference;
+
+#else
+
+template< class T, T v > struct integral_constant { enum { value = v }; };
+typedef integral_constant< bool, true > true_type;
+typedef integral_constant< bool, false > false_type;
+
+template< class T, class U > struct is_same : false_type{};
+template< class T > struct is_same<T, T> : true_type{};
+
+template< typename T > struct is_signed : false_type {};
+template<> struct is_signed<signed char> : true_type {};
+template<> struct is_signed<signed int > : true_type {};
+template<> struct is_signed<signed long> : true_type {};
+
+#endif
+
+} // namespace std11
+
+// C++17 emulation:
+
+namespace std17 {
+
+template< bool v > struct bool_constant : std11::integral_constant<bool, v>{};
+
+#if span_CPP11_120
+
+template< class...>
+using void_t = void;
+
+#endif
+
+#if span_HAVE( DATA )
+
+using std::data;
+using std::size;
+
+#elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+template< typename T, std::size_t N >
+inline span_constexpr auto size( const T(&)[N] ) span_noexcept -> size_t
+{
+ return N;
+}
+
+template< typename C >
+inline span_constexpr auto size( C const & cont ) -> decltype( cont.size() )
+{
+ return cont.size();
+}
+
+template< typename T, std::size_t N >
+inline span_constexpr auto data( T(&arr)[N] ) span_noexcept -> T*
+{
+ return &arr[0];
+}
+
+template< typename C >
+inline span_constexpr auto data( C & cont ) -> decltype( cont.data() )
+{
+ return cont.data();
+}
+
+template< typename C >
+inline span_constexpr auto data( C const & cont ) -> decltype( cont.data() )
+{
+ return cont.data();
+}
+
+template< typename E >
+inline span_constexpr auto data( std::initializer_list<E> il ) span_noexcept -> E const *
+{
+ return il.begin();
+}
+
+#endif // span_HAVE( DATA )
+
+#if span_HAVE( BYTE )
+using std::byte;
+#elif span_HAVE( NONSTD_BYTE )
+using nonstd::byte;
+#endif
+
+} // namespace std17
+
+// C++20 emulation:
+
+namespace std20 {
+
+#if span_HAVE( DEDUCTION_GUIDES )
+template< class T >
+using iter_reference_t = decltype( *std::declval<T&>() );
+#endif
+
+} // namespace std20
+
+// Implementation details:
+
+namespace detail {
+
+/*enum*/ struct enabler{};
+
+template< typename T >
+span_constexpr bool is_positive( T x )
+{
+ return std11::is_signed<T>::value ? x >= 0 : true;
+}
+
+#if span_HAVE( TYPE_TRAITS )
+
+template< class Q >
+struct is_span_oracle : std::false_type{};
+
+template< class T, span_CONFIG_EXTENT_TYPE Extent >
+struct is_span_oracle< span<T, Extent> > : std::true_type{};
+
+template< class Q >
+struct is_span : is_span_oracle< typename std::remove_cv<Q>::type >{};
+
+template< class Q >
+struct is_std_array_oracle : std::false_type{};
+
+#if span_HAVE( ARRAY )
+
+template< class T, std::size_t Extent >
+struct is_std_array_oracle< std::array<T, Extent> > : std::true_type{};
+
+#endif
+
+template< class Q >
+struct is_std_array : is_std_array_oracle< typename std::remove_cv<Q>::type >{};
+
+template< class Q >
+struct is_array : std::false_type {};
+
+template< class T >
+struct is_array<T[]> : std::true_type {};
+
+template< class T, std::size_t N >
+struct is_array<T[N]> : std::true_type {};
+
+#if span_CPP11_140 && ! span_BETWEEN( span_COMPILER_GNUC_VERSION, 1, 500 )
+
+template< class, class = void >
+struct has_size_and_data : std::false_type{};
+
+template< class C >
+struct has_size_and_data
+<
+ C, std17::void_t<
+ decltype( std17::size(std::declval<C>()) ),
+ decltype( std17::data(std::declval<C>()) ) >
+> : std::true_type{};
+
+template< class, class, class = void >
+struct is_compatible_element : std::false_type {};
+
+template< class C, class E >
+struct is_compatible_element
+<
+ C, E, std17::void_t<
+ decltype( std17::data(std::declval<C>()) ) >
+> : std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >{};
+
+template< class C >
+struct is_container : std17::bool_constant
+<
+ ! is_span< C >::value
+ && ! is_array< C >::value
+ && ! is_std_array< C >::value
+ && has_size_and_data< C >::value
+>{};
+
+template< class C, class E >
+struct is_compatible_container : std17::bool_constant
+<
+ is_container<C>::value
+ && is_compatible_element<C,E>::value
+>{};
+
+#else // span_CPP11_140
+
+template<
+ class C, class E
+ span_REQUIRES_T((
+ ! is_span< C >::value
+ && ! is_array< C >::value
+ && ! is_std_array< C >::value
+ && ( std::is_convertible< typename std::remove_pointer<decltype( std17::data( std::declval<C&>() ) )>::type(*)[], E(*)[] >::value)
+ // && has_size_and_data< C >::value
+ ))
+ , class = decltype( std17::size(std::declval<C>()) )
+ , class = decltype( std17::data(std::declval<C>()) )
+>
+struct is_compatible_container : std::true_type{};
+
+#endif // span_CPP11_140
+
+#endif // span_HAVE( TYPE_TRAITS )
+
+#if ! span_CONFIG( NO_EXCEPTIONS )
+#if span_FEATURE( MEMBER_AT ) > 1
+
+// format index and size:
+
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wlong-long"
+#elif defined __GNUC__
+# pragma GCC diagnostic ignored "-Wformat=ll"
+# pragma GCC diagnostic ignored "-Wlong-long"
+#endif
+
+span_noreturn inline void throw_out_of_range( size_t idx, size_t size )
+{
+ const char fmt[] = "span::at(): index '%lli' is out of range [0..%lli)";
+ char buffer[ 2 * 20 + sizeof fmt ];
+ sprintf( buffer, fmt, static_cast<long long>(idx), static_cast<long long>(size) );
+
+ throw std::out_of_range( buffer );
+}
+
+#else // MEMBER_AT
+
+span_noreturn inline void throw_out_of_range( size_t /*idx*/, size_t /*size*/ )
+{
+ throw std::out_of_range( "span::at(): index outside span" );
+}
+#endif // MEMBER_AT
+#endif // NO_EXCEPTIONS
+
+#if span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
+
+struct contract_violation : std::logic_error
+{
+ explicit contract_violation( char const * const message )
+ : std::logic_error( message )
+ {}
+};
+
+inline void report_contract_violation( char const * msg )
+{
+ throw contract_violation( msg );
+}
+
+#else // span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
+
+span_noreturn inline void report_contract_violation( char const * /*msg*/ ) span_noexcept
+{
+ std::terminate();
+}
+
+#endif // span_CONFIG( CONTRACT_VIOLATION_THROWS_V )
+
+} // namespace detail
+
+// Prevent signed-unsigned mismatch:
+
+#define span_sizeof(T) static_cast<extent_t>( sizeof(T) )
+
+template< class T >
+inline span_constexpr size_t to_size( T size )
+{
+ return static_cast<size_t>( size );
+}
+
+//
+// [views.span] - A view over a contiguous, single-dimension sequence of objects
+//
+template< class T, extent_t Extent /*= dynamic_extent*/ >
+class span
+{
+public:
+ // constants and types
+
+ typedef T element_type;
+ typedef typename std11::remove_cv< T >::type value_type;
+
+ typedef T & reference;
+ typedef T * pointer;
+ typedef T const * const_pointer;
+ typedef T const & const_reference;
+
+ typedef size_t size_type;
+ typedef extent_t extent_type;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+
+ typedef std::ptrdiff_t difference_type;
+
+ typedef std::reverse_iterator< iterator > reverse_iterator;
+ typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
+
+// static constexpr extent_type extent = Extent;
+ enum { extent = Extent };
+
+ // 26.7.3.2 Constructors, copy, and assignment [span.cons]
+
+ span_REQUIRES_0(
+ ( Extent == 0 ) ||
+ ( Extent == dynamic_extent )
+ )
+ span_constexpr span() span_noexcept
+ : data_( span_nullptr )
+ , size_( 0 )
+ {
+ // span_EXPECTS( data() == span_nullptr );
+ // span_EXPECTS( size() == 0 );
+ }
+
+#if span_HAVE( ITERATOR_CTOR )
+ // Didn't yet succeed in combining the next two constructors:
+
+ span_constexpr_exp span( std::nullptr_t, size_type count )
+ : data_( span_nullptr )
+ , size_( count )
+ {
+ span_EXPECTS( data_ == span_nullptr && count == 0 );
+ }
+
+ template< typename It
+ span_REQUIRES_T((
+ std::is_convertible<decltype(*std::declval<It&>()), element_type &>::value
+ ))
+ >
+ span_constexpr_exp span( It first, size_type count )
+ : data_( to_address( first ) )
+ , size_( count )
+ {
+ span_EXPECTS(
+ ( data_ == span_nullptr && count == 0 ) ||
+ ( data_ != span_nullptr && detail::is_positive( count ) )
+ );
+ }
+#else
+ span_constexpr_exp span( pointer ptr, size_type count )
+ : data_( ptr )
+ , size_( count )
+ {
+ span_EXPECTS(
+ ( ptr == span_nullptr && count == 0 ) ||
+ ( ptr != span_nullptr && detail::is_positive( count ) )
+ );
+ }
+#endif
+
+#if span_HAVE( ITERATOR_CTOR )
+ template< typename It, typename End
+ span_REQUIRES_T((
+ std::is_convertible<decltype(&*std::declval<It&>()), element_type *>::value
+ && ! std::is_convertible<End, std::size_t>::value
+ ))
+ >
+ span_constexpr_exp span( It first, End last )
+ : data_( to_address( first ) )
+ , size_( to_size( last - first ) )
+ {
+ span_EXPECTS(
+ last - first >= 0
+ );
+ }
+#else
+ span_constexpr_exp span( pointer first, pointer last )
+ : data_( first )
+ , size_( to_size( last - first ) )
+ {
+ span_EXPECTS(
+ last - first >= 0
+ );
+ }
+#endif
+
+ template< std::size_t N
+ span_REQUIRES_T((
+ (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
+ && std::is_convertible< value_type(*)[], element_type(*)[] >::value
+ ))
+ >
+ span_constexpr span( element_type ( &arr )[ N ] ) span_noexcept
+ : data_( span_ADDRESSOF( arr[0] ) )
+ , size_( N )
+ {}
+
+#if span_HAVE( ARRAY )
+
+ template< std::size_t N
+ span_REQUIRES_T((
+ (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
+ && std::is_convertible< value_type(*)[], element_type(*)[] >::value
+ ))
+ >
+# if span_FEATURE( CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE )
+ span_constexpr span( std::array< element_type, N > & arr ) span_noexcept
+# else
+ span_constexpr span( std::array< value_type, N > & arr ) span_noexcept
+# endif
+ : data_( arr.data() )
+ , size_( to_size( arr.size() ) )
+ {}
+
+ template< std::size_t N
+# if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+ span_REQUIRES_T((
+ (Extent == dynamic_extent || Extent == static_cast<extent_t>(N))
+ && std::is_convertible< value_type(*)[], element_type(*)[] >::value
+ ))
+# endif
+ >
+ span_constexpr span( std::array< value_type, N> const & arr ) span_noexcept
+ : data_( arr.data() )
+ , size_( to_size( arr.size() ) )
+ {}
+
+#endif // span_HAVE( ARRAY )
+
+#if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+ template< class Container
+ span_REQUIRES_T((
+ detail::is_compatible_container< Container, element_type >::value
+ ))
+ >
+ span_constexpr span( Container & cont )
+ : data_( std17::data( cont ) )
+ , size_( to_size( std17::size( cont ) ) )
+ {}
+
+ template< class Container
+ span_REQUIRES_T((
+ std::is_const< element_type >::value
+ && detail::is_compatible_container< Container, element_type >::value
+ ))
+ >
+ span_constexpr span( Container const & cont )
+ : data_( std17::data( cont ) )
+ , size_( to_size( std17::size( cont ) ) )
+ {}
+
+#endif // span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+#if span_FEATURE( WITH_CONTAINER )
+
+ template< class Container >
+ span_constexpr span( with_container_t, Container & cont )
+ : data_( cont.size() == 0 ? span_nullptr : span_ADDRESSOF( cont[0] ) )
+ , size_( to_size( cont.size() ) )
+ {}
+
+ template< class Container >
+ span_constexpr span( with_container_t, Container const & cont )
+ : data_( cont.size() == 0 ? span_nullptr : const_cast<pointer>( span_ADDRESSOF( cont[0] ) ) )
+ , size_( to_size( cont.size() ) )
+ {}
+#endif
+
+#if span_FEATURE( WITH_INITIALIZER_LIST_P2447 ) && span_HAVE( INITIALIZER_LIST )
+
+ // constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il) noexcept;
+
+#if !span_BETWEEN( span_COMPILER_MSVC_VERSION, 120, 130 )
+
+ template< extent_t U = Extent
+ span_REQUIRES_T((
+ U != dynamic_extent
+ ))
+ >
+#if span_COMPILER_GNUC_VERSION >= 900 // prevent GCC's "-Winit-list-lifetime"
+ span_constexpr14 explicit span( std::initializer_list<value_type> il ) span_noexcept
+ {
+ data_ = il.begin();
+ size_ = il.size();
+ }
+#else
+ span_constexpr explicit span( std::initializer_list<value_type> il ) span_noexcept
+ : data_( il.begin() )
+ , size_( il.size() )
+ {}
+#endif
+
+#endif // MSVC 120 (VS2013)
+
+ template< extent_t U = Extent
+ span_REQUIRES_T((
+ U == dynamic_extent
+ ))
+ >
+#if span_COMPILER_GNUC_VERSION >= 900 // prevent GCC's "-Winit-list-lifetime"
+ span_constexpr14 /*explicit*/ span( std::initializer_list<value_type> il ) span_noexcept
+ {
+ data_ = il.begin();
+ size_ = il.size();
+ }
+#else
+ span_constexpr /*explicit*/ span( std::initializer_list<value_type> il ) span_noexcept
+ : data_( il.begin() )
+ , size_( il.size() )
+ {}
+#endif
+
+#endif // P2447
+
+#if span_HAVE( IS_DEFAULT )
+ span_constexpr span( span const & other ) span_noexcept = default;
+
+ ~span() span_noexcept = default;
+
+ span_constexpr14 span & operator=( span const & other ) span_noexcept = default;
+#else
+ span_constexpr span( span const & other ) span_noexcept
+ : data_( other.data_ )
+ , size_( other.size_ )
+ {}
+
+ ~span() span_noexcept
+ {}
+
+ span_constexpr14 span & operator=( span const & other ) span_noexcept
+ {
+ data_ = other.data_;
+ size_ = other.size_;
+
+ return *this;
+ }
+#endif
+
+ template< class OtherElementType, extent_type OtherExtent
+ span_REQUIRES_T((
+ (Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent)
+ && std::is_convertible<OtherElementType(*)[], element_type(*)[]>::value
+ ))
+ >
+ span_constexpr_exp span( span<OtherElementType, OtherExtent> const & other ) span_noexcept
+ : data_( other.data() )
+ , size_( other.size() )
+ {
+ span_EXPECTS( OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent) );
+ }
+
+ // 26.7.3.3 Subviews [span.sub]
+
+ template< extent_type Count >
+ span_constexpr_exp span< element_type, Count >
+ first() const
+ {
+ span_EXPECTS( detail::is_positive( Count ) && Count <= size() );
+
+ return span< element_type, Count >( data(), Count );
+ }
+
+ template< extent_type Count >
+ span_constexpr_exp span< element_type, Count >
+ last() const
+ {
+ span_EXPECTS( detail::is_positive( Count ) && Count <= size() );
+
+ return span< element_type, Count >( data() + (size() - Count), Count );
+ }
+
+#if span_HAVE( DEFAULT_FUNCTION_TEMPLATE_ARG )
+ template< size_type Offset, extent_type Count = dynamic_extent >
+#else
+ template< size_type Offset, extent_type Count /*= dynamic_extent*/ >
+#endif
+ span_constexpr_exp span< element_type, Count >
+ subspan() const
+ {
+ span_EXPECTS(
+ ( detail::is_positive( Offset ) && Offset <= size() ) &&
+ ( Count == dynamic_extent || (detail::is_positive( Count ) && Count + Offset <= size()) )
+ );
+
+ return span< element_type, Count >(
+ data() + Offset, Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : size() - Offset) );
+ }
+
+ span_constexpr_exp span< element_type, dynamic_extent >
+ first( size_type count ) const
+ {
+ span_EXPECTS( detail::is_positive( count ) && count <= size() );
+
+ return span< element_type, dynamic_extent >( data(), count );
+ }
+
+ span_constexpr_exp span< element_type, dynamic_extent >
+ last( size_type count ) const
+ {
+ span_EXPECTS( detail::is_positive( count ) && count <= size() );
+
+ return span< element_type, dynamic_extent >( data() + ( size() - count ), count );
+ }
+
+ span_constexpr_exp span< element_type, dynamic_extent >
+ subspan( size_type offset, size_type count = static_cast<size_type>(dynamic_extent) ) const
+ {
+ span_EXPECTS(
+ ( ( detail::is_positive( offset ) && offset <= size() ) ) &&
+ ( count == static_cast<size_type>(dynamic_extent) || ( detail::is_positive( count ) && offset + count <= size() ) )
+ );
+
+ return span< element_type, dynamic_extent >(
+ data() + offset, count == static_cast<size_type>(dynamic_extent) ? size() - offset : count );
+ }
+
+ // 26.7.3.4 Observers [span.obs]
+
+ span_constexpr size_type size() const span_noexcept
+ {
+ return size_;
+ }
+
+ span_constexpr std::ptrdiff_t ssize() const span_noexcept
+ {
+ return static_cast<std::ptrdiff_t>( size_ );
+ }
+
+ span_constexpr size_type size_bytes() const span_noexcept
+ {
+ return size() * to_size( sizeof( element_type ) );
+ }
+
+ span_nodiscard span_constexpr bool empty() const span_noexcept
+ {
+ return size() == 0;
+ }
+
+ // 26.7.3.5 Element access [span.elem]
+
+ span_constexpr_exp reference operator[]( size_type idx ) const
+ {
+ span_EXPECTS( detail::is_positive( idx ) && idx < size() );
+
+ return *( data() + idx );
+ }
+
+#if span_FEATURE( MEMBER_CALL_OPERATOR )
+ span_deprecated("replace operator() with operator[]")
+
+ span_constexpr_exp reference operator()( size_type idx ) const
+ {
+ span_EXPECTS( detail::is_positive( idx ) && idx < size() );
+
+ return *( data() + idx );
+ }
+#endif
+
+#if span_FEATURE( MEMBER_AT )
+ span_constexpr14 reference at( size_type idx ) const
+ {
+#if span_CONFIG( NO_EXCEPTIONS )
+ return this->operator[]( idx );
+#else
+ if ( !detail::is_positive( idx ) || size() <= idx )
+ {
+ detail::throw_out_of_range( idx, size() );
+ }
+ return *( data() + idx );
+#endif
+ }
+#endif
+
+ span_constexpr pointer data() const span_noexcept
+ {
+ return data_;
+ }
+
+#if span_FEATURE( MEMBER_BACK_FRONT )
+
+ span_constexpr_exp reference front() const span_noexcept
+ {
+ span_EXPECTS( ! empty() );
+
+ return *data();
+ }
+
+ span_constexpr_exp reference back() const span_noexcept
+ {
+ span_EXPECTS( ! empty() );
+
+ return *( data() + size() - 1 );
+ }
+
+#endif
+
+ // xx.x.x.x Modifiers [span.modifiers]
+
+#if span_FEATURE( MEMBER_SWAP )
+
+ span_constexpr14 void swap( span & other ) span_noexcept
+ {
+ using std::swap;
+ swap( data_, other.data_ );
+ swap( size_, other.size_ );
+ }
+#endif
+
+ // 26.7.3.6 Iterator support [span.iterators]
+
+ span_constexpr iterator begin() const span_noexcept
+ {
+#if span_CPP11_OR_GREATER
+ return { data() };
+#else
+ return iterator( data() );
+#endif
+ }
+
+ span_constexpr iterator end() const span_noexcept
+ {
+#if span_CPP11_OR_GREATER
+ return { data() + size() };
+#else
+ return iterator( data() + size() );
+#endif
+ }
+
+ span_constexpr const_iterator cbegin() const span_noexcept
+ {
+#if span_CPP11_OR_GREATER
+ return { data() };
+#else
+ return const_iterator( data() );
+#endif
+ }
+
+ span_constexpr const_iterator cend() const span_noexcept
+ {
+#if span_CPP11_OR_GREATER
+ return { data() + size() };
+#else
+ return const_iterator( data() + size() );
+#endif
+ }
+
+ span_constexpr reverse_iterator rbegin() const span_noexcept
+ {
+ return reverse_iterator( end() );
+ }
+
+ span_constexpr reverse_iterator rend() const span_noexcept
+ {
+ return reverse_iterator( begin() );
+ }
+
+ span_constexpr const_reverse_iterator crbegin() const span_noexcept
+ {
+ return const_reverse_iterator ( cend() );
+ }
+
+ span_constexpr const_reverse_iterator crend() const span_noexcept
+ {
+ return const_reverse_iterator( cbegin() );
+ }
+
+private:
+
+ // Note: C++20 has std::pointer_traits<Ptr>::to_address( it );
+
+#if span_HAVE( ITERATOR_CTOR )
+ static inline span_constexpr pointer to_address( std::nullptr_t ) span_noexcept
+ {
+ return nullptr;
+ }
+
+ template< typename U >
+ static inline span_constexpr U * to_address( U * p ) span_noexcept
+ {
+ return p;
+ }
+
+ template< typename Ptr
+ span_REQUIRES_T(( ! std::is_pointer<Ptr>::value ))
+ >
+ static inline span_constexpr pointer to_address( Ptr const & it ) span_noexcept
+ {
+ return to_address( it.operator->() );
+ }
+#endif // span_HAVE( ITERATOR_CTOR )
+
+private:
+ pointer data_;
+ size_type size_;
+};
+
+// class template argument deduction guides:
+
+#if span_HAVE( DEDUCTION_GUIDES )
+
+template< class T, size_t N >
+span( T (&)[N] ) -> span<T, static_cast<extent_t>(N)>;
+
+template< class T, size_t N >
+span( std::array<T, N> & ) -> span<T, static_cast<extent_t>(N)>;
+
+template< class T, size_t N >
+span( std::array<T, N> const & ) -> span<const T, static_cast<extent_t>(N)>;
+
+#if span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR )
+
+template< class Container >
+span( Container& ) -> span<typename Container::value_type>;
+
+template< class Container >
+span( Container const & ) -> span<const typename Container::value_type>;
+
+#endif
+
+// iterator: constraints: It satisfies contiguous_­iterator.
+
+template< class It, class EndOrSize >
+span( It, EndOrSize ) -> span< typename std11::remove_reference< typename std20::iter_reference_t<It> >::type >;
+
+#endif // span_HAVE( DEDUCTION_GUIDES )
+
+// 26.7.3.7 Comparison operators [span.comparison]
+
+#if span_FEATURE( COMPARISON )
+#if span_FEATURE( SAME )
+
+template< class T1, extent_t E1, class T2, extent_t E2 >
+inline span_constexpr bool same( span<T1,E1> const & l, span<T2,E2> const & r ) span_noexcept
+{
+ return std11::is_same<T1, T2>::value
+ && l.size() == r.size()
+ && static_cast<void const*>( l.data() ) == r.data();
+}
+
+#endif
+
+template< class T1, extent_t E1, class T2, extent_t E2 >
+inline span_constexpr bool operator==( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+ return
+#if span_FEATURE( SAME )
+ same( l, r ) ||
+#endif
+ ( l.size() == r.size() && std::equal( l.begin(), l.end(), r.begin() ) );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2 >
+inline span_constexpr bool operator<( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+ return std::lexicographical_compare( l.begin(), l.end(), r.begin(), r.end() );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2 >
+inline span_constexpr bool operator!=( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+ return !( l == r );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2 >
+inline span_constexpr bool operator<=( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+ return !( r < l );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2 >
+inline span_constexpr bool operator>( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+ return ( r < l );
+}
+
+template< class T1, extent_t E1, class T2, extent_t E2 >
+inline span_constexpr bool operator>=( span<T1,E1> const & l, span<T2,E2> const & r )
+{
+ return !( l < r );
+}
+
+#endif // span_FEATURE( COMPARISON )
+
+// 26.7.2.6 views of object representation [span.objectrep]
+
+#if span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE )
+
+// Avoid MSVC 14.1 (1910), VS 2017: warning C4307: '*': integral constant overflow:
+
+template< typename T, extent_t Extent >
+struct BytesExtent
+{
+#if span_CPP11_OR_GREATER
+ enum ET : extent_t { value = span_sizeof(T) * Extent };
+#else
+ enum ET { value = span_sizeof(T) * Extent };
+#endif
+};
+
+template< typename T >
+struct BytesExtent< T, dynamic_extent >
+{
+#if span_CPP11_OR_GREATER
+ enum ET : extent_t { value = dynamic_extent };
+#else
+ enum ET { value = dynamic_extent };
+#endif
+};
+
+template< class T, extent_t Extent >
+inline span_constexpr span< const std17::byte, BytesExtent<T, Extent>::value >
+as_bytes( span<T,Extent> spn ) span_noexcept
+{
+#if 0
+ return { reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() };
+#else
+ return span< const std17::byte, BytesExtent<T, Extent>::value >(
+ reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() ); // NOLINT
+#endif
+}
+
+template< class T, extent_t Extent >
+inline span_constexpr span< std17::byte, BytesExtent<T, Extent>::value >
+as_writable_bytes( span<T,Extent> spn ) span_noexcept
+{
+#if 0
+ return { reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() };
+#else
+ return span< std17::byte, BytesExtent<T, Extent>::value >(
+ reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() ); // NOLINT
+#endif
+}
+
+#endif // span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE )
+
+// 27.8 Container and view access [iterator.container]
+
+template< class T, extent_t Extent /*= dynamic_extent*/ >
+span_constexpr std::size_t size( span<T,Extent> const & spn )
+{
+ return static_cast<std::size_t>( spn.size() );
+}
+
+template< class T, extent_t Extent /*= dynamic_extent*/ >
+span_constexpr std::ptrdiff_t ssize( span<T,Extent> const & spn )
+{
+ return static_cast<std::ptrdiff_t>( spn.size() );
+}
+
+} // namespace span_lite
+} // namespace nonstd
+
+// make available in nonstd:
+
+namespace nonstd {
+
+using span_lite::dynamic_extent;
+
+using span_lite::span;
+
+using span_lite::with_container;
+
+#if span_FEATURE( COMPARISON )
+#if span_FEATURE( SAME )
+using span_lite::same;
+#endif
+
+using span_lite::operator==;
+using span_lite::operator!=;
+using span_lite::operator<;
+using span_lite::operator<=;
+using span_lite::operator>;
+using span_lite::operator>=;
+#endif
+
+#if span_HAVE( BYTE )
+using span_lite::as_bytes;
+using span_lite::as_writable_bytes;
+#endif
+
+using span_lite::size;
+using span_lite::ssize;
+
+} // namespace nonstd
+
+#endif // span_USES_STD_SPAN
+
+// make_span() [span-lite extension]:
+
+#if span_FEATURE( MAKE_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER )
+
+#if span_USES_STD_SPAN
+# define span_constexpr constexpr
+# define span_noexcept noexcept
+# define span_nullptr nullptr
+# ifndef span_CONFIG_EXTENT_TYPE
+# define span_CONFIG_EXTENT_TYPE std::size_t
+# endif
+using extent_t = span_CONFIG_EXTENT_TYPE;
+#endif // span_USES_STD_SPAN
+
+namespace nonstd {
+namespace span_lite {
+
+template< class T >
+inline span_constexpr span<T>
+make_span( T * ptr, size_t count ) span_noexcept
+{
+ return span<T>( ptr, count );
+}
+
+template< class T >
+inline span_constexpr span<T>
+make_span( T * first, T * last ) span_noexcept
+{
+ return span<T>( first, last );
+}
+
+template< class T, std::size_t N >
+inline span_constexpr span<T, static_cast<extent_t>(N)>
+make_span( T ( &arr )[ N ] ) span_noexcept
+{
+ return span<T, static_cast<extent_t>(N)>( &arr[ 0 ], N );
+}
+
+#if span_USES_STD_SPAN || span_HAVE( ARRAY )
+
+template< class T, std::size_t N >
+inline span_constexpr span<T, static_cast<extent_t>(N)>
+make_span( std::array< T, N > & arr ) span_noexcept
+{
+ return span<T, static_cast<extent_t>(N)>( arr );
+}
+
+template< class T, std::size_t N >
+inline span_constexpr span< const T, static_cast<extent_t>(N) >
+make_span( std::array< T, N > const & arr ) span_noexcept
+{
+ return span<const T, static_cast<extent_t>(N)>( arr );
+}
+
+#endif // span_HAVE( ARRAY )
+
+#if span_USES_STD_SPAN || span_HAVE( INITIALIZER_LIST )
+
+template< class T >
+inline span_constexpr span< const T >
+make_span( std::initializer_list<T> il ) span_noexcept
+{
+ return span<const T>( il.begin(), il.size() );
+}
+
+#endif // span_HAVE( INITIALIZER_LIST )
+
+#if span_USES_STD_SPAN
+
+template< class Container, class EP = decltype( std::data(std::declval<Container&>())) >
+inline span_constexpr auto
+make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer<EP>::type >
+{
+ return span< typename std::remove_pointer<EP>::type >( cont );
+}
+
+template< class Container, class EP = decltype( std::data(std::declval<Container&>())) >
+inline span_constexpr auto
+make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer<EP>::type >
+{
+ return span< const typename std::remove_pointer<EP>::type >( cont );
+}
+
+#elif span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) && span_HAVE( AUTO )
+
+template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
+inline span_constexpr auto
+make_span( Container & cont ) span_noexcept -> span< typename std::remove_pointer<EP>::type >
+{
+ return span< typename std::remove_pointer<EP>::type >( cont );
+}
+
+template< class Container, class EP = decltype( std17::data(std::declval<Container&>())) >
+inline span_constexpr auto
+make_span( Container const & cont ) span_noexcept -> span< const typename std::remove_pointer<EP>::type >
+{
+ return span< const typename std::remove_pointer<EP>::type >( cont );
+}
+
+#else
+
+template< class T >
+inline span_constexpr span<T>
+make_span( span<T> spn ) span_noexcept
+{
+ return spn;
+}
+
+template< class T, class Allocator >
+inline span_constexpr span<T>
+make_span( std::vector<T, Allocator> & cont ) span_noexcept
+{
+ return span<T>( with_container, cont );
+}
+
+template< class T, class Allocator >
+inline span_constexpr span<const T>
+make_span( std::vector<T, Allocator> const & cont ) span_noexcept
+{
+ return span<const T>( with_container, cont );
+}
+
+#endif // span_USES_STD_SPAN || ( ... )
+
+#if ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER )
+
+template< class Container >
+inline span_constexpr span<typename Container::value_type>
+make_span( with_container_t, Container & cont ) span_noexcept
+{
+ return span< typename Container::value_type >( with_container, cont );
+}
+
+template< class Container >
+inline span_constexpr span<const typename Container::value_type>
+make_span( with_container_t, Container const & cont ) span_noexcept
+{
+ return span< const typename Container::value_type >( with_container, cont );
+}
+
+#endif // ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER )
+
+// extensions: non-member views:
+// this feature implies the presence of make_span()
+
+#if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN )
+
+template< extent_t Count, class T, extent_t Extent >
+span_constexpr span<T, Count>
+first( span<T, Extent> spn )
+{
+ return spn.template first<Count>();
+}
+
+template< class T, extent_t Extent >
+span_constexpr span<T>
+first( span<T, Extent> spn, size_t count )
+{
+ return spn.first( count );
+}
+
+template< extent_t Count, class T, extent_t Extent >
+span_constexpr span<T, Count>
+last( span<T, Extent> spn )
+{
+ return spn.template last<Count>();
+}
+
+template< class T, extent_t Extent >
+span_constexpr span<T>
+last( span<T, Extent> spn, size_t count )
+{
+ return spn.last( count );
+}
+
+template< size_t Offset, extent_t Count, class T, extent_t Extent >
+span_constexpr span<T, Count>
+subspan( span<T, Extent> spn )
+{
+ return spn.template subspan<Offset, Count>();
+}
+
+template< class T, extent_t Extent >
+span_constexpr span<T>
+subspan( span<T, Extent> spn, size_t offset, extent_t count = dynamic_extent )
+{
+ return spn.subspan( offset, count );
+}
+
+#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN )
+
+#if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120
+
+template< extent_t Count, class T >
+span_constexpr auto
+first( T & t ) -> decltype( make_span(t).template first<Count>() )
+{
+ return make_span( t ).template first<Count>();
+}
+
+template< class T >
+span_constexpr auto
+first( T & t, size_t count ) -> decltype( make_span(t).first(count) )
+{
+ return make_span( t ).first( count );
+}
+
+template< extent_t Count, class T >
+span_constexpr auto
+last( T & t ) -> decltype( make_span(t).template last<Count>() )
+{
+ return make_span(t).template last<Count>();
+}
+
+template< class T >
+span_constexpr auto
+last( T & t, extent_t count ) -> decltype( make_span(t).last(count) )
+{
+ return make_span( t ).last( count );
+}
+
+template< size_t Offset, extent_t Count = dynamic_extent, class T >
+span_constexpr auto
+subspan( T & t ) -> decltype( make_span(t).template subspan<Offset, Count>() )
+{
+ return make_span( t ).template subspan<Offset, Count>();
+}
+
+template< class T >
+span_constexpr auto
+subspan( T & t, size_t offset, extent_t count = dynamic_extent ) -> decltype( make_span(t).subspan(offset, count) )
+{
+ return make_span( t ).subspan( offset, count );
+}
+
+#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER )
+
+} // namespace span_lite
+} // namespace nonstd
+
+// make available in nonstd:
+
+namespace nonstd {
+using span_lite::make_span;
+
+#if span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) || ( span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) && span_CPP11_120 )
+
+using span_lite::first;
+using span_lite::last;
+using span_lite::subspan;
+
+#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_[SPAN|CONTAINER] )
+
+} // namespace nonstd
+
+#endif // #if span_FEATURE_TO_STD( MAKE_SPAN )
+
+#if span_CPP11_OR_GREATER && span_FEATURE( BYTE_SPAN ) && ( span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) )
+
+namespace nonstd {
+namespace span_lite {
+
+template< class T >
+inline span_constexpr auto
+byte_span( T & t ) span_noexcept -> span< std17::byte, span_sizeof(T) >
+{
+ return span< std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte * >( &t ), span_sizeof(T) );
+}
+
+template< class T >
+inline span_constexpr auto
+byte_span( T const & t ) span_noexcept -> span< const std17::byte, span_sizeof(T) >
+{
+ return span< const std17::byte, span_sizeof(t) >( reinterpret_cast< std17::byte const * >( &t ), span_sizeof(T) );
+}
+
+} // namespace span_lite
+} // namespace nonstd
+
+// make available in nonstd:
+
+namespace nonstd {
+using span_lite::byte_span;
+} // namespace nonstd
+
+#endif // span_FEATURE( BYTE_SPAN )
+
+#if !span_USES_STD_SPAN && span_HAVE( STRUCT_BINDING )
+
+#if span_CPP14_OR_GREATER
+# include <tuple>
+#elif span_CPP11_OR_GREATER
+# include <tuple>
+namespace std {
+ template< std::size_t I, typename T >
+ using tuple_element_t = typename tuple_element<I, T>::type;
+}
+#else
+namespace std {
+ template< typename T >
+ class tuple_size; /*undefined*/
+
+ template< std::size_t I, typename T >
+ class tuple_element; /* undefined */
+}
+#endif // span_CPP14_OR_GREATER
+
+namespace std {
+
+// 26.7.X Tuple interface
+
+// std::tuple_size<>:
+
+template< typename ElementType, nonstd::span_lite::extent_t Extent >
+class tuple_size< nonstd::span<ElementType, Extent> > : public integral_constant<size_t, static_cast<size_t>(Extent)> {};
+
+// std::tuple_size<>: Leave undefined for dynamic extent:
+
+template< typename ElementType >
+class tuple_size< nonstd::span<ElementType, nonstd::dynamic_extent> >;
+
+// std::tuple_element<>:
+
+template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
+class tuple_element< I, nonstd::span<ElementType, Extent> >
+{
+public:
+#if span_HAVE( STATIC_ASSERT )
+ static_assert( Extent != nonstd::dynamic_extent && I < Extent, "tuple_element<I,span>: dynamic extent or index out of range" );
+#endif
+ using type = ElementType;
+};
+
+// std::get<>(), 2 variants:
+
+template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
+span_constexpr ElementType & get( nonstd::span<ElementType, Extent> & spn ) span_noexcept
+{
+#if span_HAVE( STATIC_ASSERT )
+ static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" );
+#endif
+ return spn[I];
+}
+
+template< size_t I, typename ElementType, nonstd::span_lite::extent_t Extent >
+span_constexpr ElementType const & get( nonstd::span<ElementType, Extent> const & spn ) span_noexcept
+{
+#if span_HAVE( STATIC_ASSERT )
+ static_assert( Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range" );
+#endif
+ return spn[I];
+}
+
+} // end namespace std
+
+#endif // !span_USES_STD_SPAN && span_HAVE( STRUCT_BINDING )
+
+#if ! span_USES_STD_SPAN
+span_RESTORE_WARNINGS()
+#endif // span_USES_STD_SPAN
+
+#endif // NONSTD_SPAN_HPP_INCLUDED
diff --git a/src/shared/variant/variant.qbs b/src/shared/span/span.qbs
index 3a95553b7..321583ef5 100644
--- a/src/shared/variant/variant.qbs
+++ b/src/shared/span/span.qbs
@@ -1,10 +1,9 @@
Product {
- name: "qbsvariant"
+ name: "span"
files: [
- "LICENSE.md",
+ "LICENSE_1_0.txt",
"README.md",
- "variant.h",
- "variant.hpp"
+ "span.hpp",
]
Export {
Depends { name: "cpp" }
diff --git a/src/shared/variant/CMakeLists.txt b/src/shared/variant/CMakeLists.txt
deleted file mode 100644
index ac73231d4..000000000
--- a/src/shared/variant/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-add_library(qbsvariant INTERFACE)
-target_include_directories(
- qbsvariant
- INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/>)
diff --git a/src/shared/variant/README.md b/src/shared/variant/README.md
deleted file mode 100644
index 6644286d2..000000000
--- a/src/shared/variant/README.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# MPark.Variant
-
-> __C++17__ `std::variant` for __C++11__/__14__/__17__
-
-[![release][badge.release]][release]
-[![header][badge.header]][header]
-[![travis][badge.travis]][travis]
-[![appveyor][badge.appveyor]][appveyor]
-[![license][badge.license]][license]
-[![godbolt][badge.godbolt]][godbolt]
-[![wandbox][badge.wandbox]][wandbox]
-
-[badge.release]: https://img.shields.io/github/release/mpark/variant.svg
-[badge.header]: https://img.shields.io/badge/single%20header-master-blue.svg
-[badge.travis]: https://travis-ci.org/mpark/variant.svg?branch=master
-[badge.appveyor]: https://ci.appveyor.com/api/projects/status/github/mpark/variant?branch=master&svg=true
-[badge.license]: https://img.shields.io/badge/license-boost-blue.svg
-[badge.godbolt]: https://img.shields.io/badge/try%20it-on%20godbolt-222266.svg
-[badge.wandbox]: https://img.shields.io/badge/try%20it-on%20wandbox-5cb85c.svg
-
-[release]: https://github.com/mpark/variant/releases/latest
-[header]: https://github.com/mpark/variant/blob/single-header/master/variant.hpp
-[travis]: https://travis-ci.org/mpark/variant
-[appveyor]: https://ci.appveyor.com/project/mpark/variant
-[license]: https://github.com/mpark/variant/blob/master/LICENSE.md
-[godbolt]: https://godbolt.org/g/1qYDAK
-[wandbox]: https://wandbox.org/permlink/QV3gZ2KQQNwgoFIB
-
-## Single Header
-
-This branch provides a standalone `variant.hpp` file for each
-[release](https://github.com/mpark/variant/releases).
-Copy it and `#include` away!
-
-## License
-
-Distributed under the [Boost Software License, Version 1.0](LICENSE.md).
diff --git a/src/shared/variant/variant.h b/src/shared/variant/variant.h
deleted file mode 100644
index ecaf81ca6..000000000
--- a/src/shared/variant/variant.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qbs.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-/*
- See std(::experimental)::variant.
-*/
-
-// std::variant from Apple's Clang supports methods that throw std::bad_optional_access only
-// with deployment target >= macOS 10.14
-// TODO: Use std::variant everywhere when we can require macOS 10.14
-#if !defined(__apple_build_version__)
-#include <variant>
-
-namespace qbs {
-namespace Variant {
-using std::get;
-using std::get_if;
-using std::holds_alternative;
-using std::variant;
-using std::variant_alternative_t;
-using std::visit;
-} // namespace Variant
-} // namespace qbs
-
-#else
-#include "variant.hpp"
-
-namespace qbs {
-namespace Variant {
-using mpark::get;
-using mpark::get_if;
-using mpark::holds_alternative;
-using mpark::variant;
-using mpark::variant_alternative_t;
-using mpark::visit;
-} // namespace Variant
-} // namespace qbs
-
-#endif
diff --git a/src/shared/variant/variant.hpp b/src/shared/variant/variant.hpp
deleted file mode 100644
index dca26986c..000000000
--- a/src/shared/variant/variant.hpp
+++ /dev/null
@@ -1,2465 +0,0 @@
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-#ifndef MPARK_VARIANT_HPP
-#define MPARK_VARIANT_HPP
-
-#if defined(__GNUC__) && __GNUC__ >= 9
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-copy"
-#endif
-
-/*
- variant synopsis
-
-namespace std {
-
- // 20.7.2, class template variant
- template <class... Types>
- class variant {
- public:
-
- // 20.7.2.1, constructors
- constexpr variant() noexcept(see below);
- variant(const variant&);
- variant(variant&&) noexcept(see below);
-
- template <class T> constexpr variant(T&&) noexcept(see below);
-
- template <class T, class... Args>
- constexpr explicit variant(in_place_type_t<T>, Args&&...);
-
- template <class T, class U, class... Args>
- constexpr explicit variant(
- in_place_type_t<T>, initializer_list<U>, Args&&...);
-
- template <size_t I, class... Args>
- constexpr explicit variant(in_place_index_t<I>, Args&&...);
-
- template <size_t I, class U, class... Args>
- constexpr explicit variant(
- in_place_index_t<I>, initializer_list<U>, Args&&...);
-
- // 20.7.2.2, destructor
- ~variant();
-
- // 20.7.2.3, assignment
- variant& operator=(const variant&);
- variant& operator=(variant&&) noexcept(see below);
-
- template <class T> variant& operator=(T&&) noexcept(see below);
-
- // 20.7.2.4, modifiers
- template <class T, class... Args>
- T& emplace(Args&&...);
-
- template <class T, class U, class... Args>
- T& emplace(initializer_list<U>, Args&&...);
-
- template <size_t I, class... Args>
- variant_alternative<I, variant>& emplace(Args&&...);
-
- template <size_t I, class U, class... Args>
- variant_alternative<I, variant>& emplace(initializer_list<U>, Args&&...);
-
- // 20.7.2.5, value status
- constexpr bool valueless_by_exception() const noexcept;
- constexpr size_t index() const noexcept;
-
- // 20.7.2.6, swap
- void swap(variant&) noexcept(see below);
- };
-
- // 20.7.3, variant helper classes
- template <class T> struct variant_size; // undefined
-
- template <class T>
- constexpr size_t variant_size_v = variant_size<T>::value;
-
- template <class T> struct variant_size<const T>;
- template <class T> struct variant_size<volatile T>;
- template <class T> struct variant_size<const volatile T>;
-
- template <class... Types>
- struct variant_size<variant<Types...>>;
-
- template <size_t I, class T> struct variant_alternative; // undefined
-
- template <size_t I, class T>
- using variant_alternative_t = typename variant_alternative<I, T>::type;
-
- template <size_t I, class T> struct variant_alternative<I, const T>;
- template <size_t I, class T> struct variant_alternative<I, volatile T>;
- template <size_t I, class T> struct variant_alternative<I, const volatile T>;
-
- template <size_t I, class... Types>
- struct variant_alternative<I, variant<Types...>>;
-
- constexpr size_t variant_npos = -1;
-
- // 20.7.4, value access
- template <class T, class... Types>
- constexpr bool holds_alternative(const variant<Types...>&) noexcept;
-
- template <size_t I, class... Types>
- constexpr variant_alternative_t<I, variant<Types...>>&
- get(variant<Types...>&);
-
- template <size_t I, class... Types>
- constexpr variant_alternative_t<I, variant<Types...>>&&
- get(variant<Types...>&&);
-
- template <size_t I, class... Types>
- constexpr variant_alternative_t<I, variant<Types...>> const&
- get(const variant<Types...>&);
-
- template <size_t I, class... Types>
- constexpr variant_alternative_t<I, variant<Types...>> const&&
- get(const variant<Types...>&&);
-
- template <class T, class... Types>
- constexpr T& get(variant<Types...>&);
-
- template <class T, class... Types>
- constexpr T&& get(variant<Types...>&&);
-
- template <class T, class... Types>
- constexpr const T& get(const variant<Types...>&);
-
- template <class T, class... Types>
- constexpr const T&& get(const variant<Types...>&&);
-
- template <size_t I, class... Types>
- constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
- get_if(variant<Types...>*) noexcept;
-
- template <size_t I, class... Types>
- constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
- get_if(const variant<Types...>*) noexcept;
-
- template <class T, class... Types>
- constexpr add_pointer_t<T>
- get_if(variant<Types...>*) noexcept;
-
- template <class T, class... Types>
- constexpr add_pointer_t<const T>
- get_if(const variant<Types...>*) noexcept;
-
- // 20.7.5, relational operators
- template <class... Types>
- constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
-
- // 20.7.6, visitation
- template <class Visitor, class... Variants>
- constexpr see below visit(Visitor&&, Variants&&...);
-
- // 20.7.7, class monostate
- struct monostate;
-
- // 20.7.8, monostate relational operators
- constexpr bool operator<(monostate, monostate) noexcept;
- constexpr bool operator>(monostate, monostate) noexcept;
- constexpr bool operator<=(monostate, monostate) noexcept;
- constexpr bool operator>=(monostate, monostate) noexcept;
- constexpr bool operator==(monostate, monostate) noexcept;
- constexpr bool operator!=(monostate, monostate) noexcept;
-
- // 20.7.9, specialized algorithms
- template <class... Types>
- void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);
-
- // 20.7.10, class bad_variant_access
- class bad_variant_access;
-
- // 20.7.11, hash support
- template <class T> struct hash;
- template <class... Types> struct hash<variant<Types...>>;
- template <> struct hash<monostate>;
-
-} // namespace std
-
-*/
-
-#include <cstddef>
-#include <exception>
-#include <functional>
-#include <initializer_list>
-#include <new>
-#include <type_traits>
-#include <utility>
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-#ifndef MPARK_CONFIG_HPP
-#define MPARK_CONFIG_HPP
-
-// MSVC 2015 Update 3.
-#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210)
-#error "MPark.Variant requires C++11 support."
-#endif
-
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#ifndef __has_include
-#define __has_include(x) 0
-#endif
-
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-#if __has_builtin(__builtin_addressof) || \
- (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER)
-#define MPARK_BUILTIN_ADDRESSOF
-#endif
-
-#if __has_builtin(__builtin_unreachable)
-#define MPARK_BUILTIN_UNREACHABLE
-#endif
-
-#if __has_builtin(__type_pack_element)
-#define MPARK_TYPE_PACK_ELEMENT
-#endif
-
-#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
-#if !defined(_MSC_VER) || _MSC_VER < 1915 // compile issue in msvc 2017 update 8
-#define MPARK_CPP14_CONSTEXPR
-#endif
-#endif
-
-#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \
- (defined(_MSC_VER) && defined(_CPPUNWIND))
-#define MPARK_EXCEPTIONS
-#endif
-
-#if defined(__cpp_generic_lambdas) || defined(_MSC_VER)
-#define MPARK_GENERIC_LAMBDAS
-#endif
-
-#if defined(__cpp_lib_integer_sequence)
-#define MPARK_INTEGER_SEQUENCE
-#endif
-
-#if defined(__cpp_return_type_deduction) || defined(_MSC_VER)
-#define MPARK_RETURN_TYPE_DEDUCTION
-#endif
-
-#if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER)
-#define MPARK_TRANSPARENT_OPERATORS
-#endif
-
-#if defined(__cpp_variable_templates) || defined(_MSC_VER)
-#define MPARK_VARIABLE_TEMPLATES
-#endif
-
-#if !defined(__GLIBCXX__) || __has_include(<codecvt>) // >= libstdc++-5
-#define MPARK_TRIVIALITY_TYPE_TRAITS
-#endif
-
-#endif // MPARK_CONFIG_HPP
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-#ifndef MPARK_IN_PLACE_HPP
-#define MPARK_IN_PLACE_HPP
-
-#include <cstddef>
-
-
-namespace mpark {
-
- struct in_place_t { explicit in_place_t() = default; };
-
- template <std::size_t I>
- struct in_place_index_t { explicit in_place_index_t() = default; };
-
- template <typename T>
- struct in_place_type_t { explicit in_place_type_t() = default; };
-
-#ifdef MPARK_VARIABLE_TEMPLATES
- constexpr in_place_t in_place{};
-
- template <std::size_t I> constexpr in_place_index_t<I> in_place_index{};
-
- template <typename T> constexpr in_place_type_t<T> in_place_type{};
-#endif
-
-} // namespace mpark
-
-#endif // MPARK_IN_PLACE_HPP
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-#ifndef MPARK_LIB_HPP
-#define MPARK_LIB_HPP
-
-#include <memory>
-#include <functional>
-#include <type_traits>
-#include <utility>
-
-
-#define RETURN(...) \
- noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { \
- return __VA_ARGS__; \
- }
-
-namespace mpark {
- namespace lib {
- template <typename T>
- struct identity { using type = T; };
-
- inline namespace cpp14 {
- template <typename T, std::size_t N>
- struct array {
- constexpr const T &operator[](std::size_t index) const {
- return data[index];
- }
-
- T data[N == 0 ? 1 : N];
- };
-
- template <typename T>
- using add_pointer_t = typename std::add_pointer<T>::type;
-
- template <typename... Ts>
- using common_type_t = typename std::common_type<Ts...>::type;
-
- template <typename T>
- using decay_t = typename std::decay<T>::type;
-
- template <bool B, typename T = void>
- using enable_if_t = typename std::enable_if<B, T>::type;
-
- template <typename T>
- using remove_const_t = typename std::remove_const<T>::type;
-
- template <typename T>
- using remove_reference_t = typename std::remove_reference<T>::type;
-
- template <typename T>
- inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {
- return static_cast<T &&>(t);
- }
-
- template <typename T>
- inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
- static_assert(!std::is_lvalue_reference<T>::value,
- "can not forward an rvalue as an lvalue");
- return static_cast<T &&>(t);
- }
-
- template <typename T>
- inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {
- return static_cast<remove_reference_t<T> &&>(t);
- }
-
-#ifdef MPARK_INTEGER_SEQUENCE
- using std::integer_sequence;
- using std::index_sequence;
- using std::make_index_sequence;
- using std::index_sequence_for;
-#else
- template <typename T, T... Is>
- struct integer_sequence {
- using value_type = T;
- static constexpr std::size_t size() noexcept { return sizeof...(Is); }
- };
-
- template <std::size_t... Is>
- using index_sequence = integer_sequence<std::size_t, Is...>;
-
- template <typename Lhs, typename Rhs>
- struct make_index_sequence_concat;
-
- template <std::size_t... Lhs, std::size_t... Rhs>
- struct make_index_sequence_concat<index_sequence<Lhs...>,
- index_sequence<Rhs...>>
- : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};
-
- template <std::size_t N>
- struct make_index_sequence_impl;
-
- template <std::size_t N>
- using make_index_sequence = typename make_index_sequence_impl<N>::type;
-
- template <std::size_t N>
- struct make_index_sequence_impl
- : make_index_sequence_concat<make_index_sequence<N / 2>,
- make_index_sequence<N - (N / 2)>> {};
-
- template <>
- struct make_index_sequence_impl<0> : identity<index_sequence<>> {};
-
- template <>
- struct make_index_sequence_impl<1> : identity<index_sequence<0>> {};
-
- template <typename... Ts>
- using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
-#endif
-
- // <functional>
-#ifdef MPARK_TRANSPARENT_OPERATORS
- using equal_to = std::equal_to<>;
-#else
- struct equal_to {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
- };
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
- using not_equal_to = std::not_equal_to<>;
-#else
- struct not_equal_to {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
- };
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
- using less = std::less<>;
-#else
- struct less {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
- };
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
- using greater = std::greater<>;
-#else
- struct greater {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
- };
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
- using less_equal = std::less_equal<>;
-#else
- struct less_equal {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
- };
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
- using greater_equal = std::greater_equal<>;
-#else
- struct greater_equal {
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
- RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
- };
-#endif
- } // namespace cpp14
-
- inline namespace cpp17 {
-
- // <type_traits>
- template <bool B>
- using bool_constant = std::integral_constant<bool, B>;
-
- template <typename...>
- struct voider : identity<void> {};
-
- template <typename... Ts>
- using void_t = typename voider<Ts...>::type;
-
- namespace detail {
- namespace swappable {
-
- using std::swap;
-
- template <typename T>
- struct is_swappable {
- private:
- template <typename U,
- typename = decltype(swap(std::declval<U &>(),
- std::declval<U &>()))>
- inline static std::true_type test(int);
-
- template <typename U>
- inline static std::false_type test(...);
-
- public:
- static constexpr bool value = decltype(test<T>(0))::value;
- };
-
- template <typename T, bool = is_swappable<T>::value>
- struct is_nothrow_swappable {
- static constexpr bool value =
- noexcept(swap(std::declval<T &>(), std::declval<T &>()));
- };
-
- template <typename T>
- struct is_nothrow_swappable<T, false> : std::false_type {};
-
- } // namespace swappable
- } // namespace detail
-
- using detail::swappable::is_swappable;
- using detail::swappable::is_nothrow_swappable;
-
- // <functional>
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4100)
-#endif
- template <typename F, typename... As>
- inline constexpr auto invoke(F &&f, As &&... as)
- RETURN(lib::forward<F>(f)(lib::forward<As>(as)...))
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
- template <typename B, typename T, typename D>
- inline constexpr auto invoke(T B::*pmv, D &&d)
- RETURN(lib::forward<D>(d).*pmv)
-
- template <typename Pmv, typename Ptr>
- inline constexpr auto invoke(Pmv pmv, Ptr &&ptr)
- RETURN((*lib::forward<Ptr>(ptr)).*pmv)
-
- template <typename B, typename T, typename D, typename... As>
- inline constexpr auto invoke(T B::*pmf, D &&d, As &&... as)
- RETURN((lib::forward<D>(d).*pmf)(lib::forward<As>(as)...))
-
- template <typename Pmf, typename Ptr, typename... As>
- inline constexpr auto invoke(Pmf pmf, Ptr &&ptr, As &&... as)
- RETURN(((*lib::forward<Ptr>(ptr)).*pmf)(lib::forward<As>(as)...))
-
- namespace detail {
-
- template <typename Void, typename, typename...>
- struct invoke_result {};
-
- template <typename F, typename... Args>
- struct invoke_result<void_t<decltype(lib::invoke(
- std::declval<F>(), std::declval<Args>()...))>,
- F,
- Args...>
- : identity<decltype(
- lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
-
- } // namespace detail
-
- template <typename F, typename... Args>
- using invoke_result = detail::invoke_result<void, F, Args...>;
-
- template <typename F, typename... Args>
- using invoke_result_t = typename invoke_result<F, Args...>::type;
-
- namespace detail {
-
- template <typename Void, typename, typename...>
- struct is_invocable : std::false_type {};
-
- template <typename F, typename... Args>
- struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
- : std::true_type {};
-
- template <typename Void, typename, typename, typename...>
- struct is_invocable_r : std::false_type {};
-
- template <typename R, typename F, typename... Args>
- struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
- R,
- F,
- Args...>
- : std::is_convertible<invoke_result_t<F, Args...>, R> {};
-
- } // namespace detail
-
- template <typename F, typename... Args>
- using is_invocable = detail::is_invocable<void, F, Args...>;
-
- template <typename R, typename F, typename... Args>
- using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
-
- // <memory>
-#ifdef MPARK_BUILTIN_ADDRESSOF
- template <typename T>
- inline constexpr T *addressof(T &arg) {
- return __builtin_addressof(arg);
- }
-#else
- namespace detail {
-
- namespace has_addressof_impl {
-
- struct fail;
-
- template <typename T>
- inline fail operator&(T &&);
-
- template <typename T>
- inline static constexpr bool impl() {
- return (std::is_class<T>::value || std::is_union<T>::value) &&
- !std::is_same<decltype(&std::declval<T &>()), fail>::value;
- }
-
- } // namespace has_addressof_impl
-
- template <typename T>
- using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
-
- template <typename T>
- inline constexpr T *addressof(T &arg, std::true_type) {
- return std::addressof(arg);
- }
-
- template <typename T>
- inline constexpr T *addressof(T &arg, std::false_type) {
- return &arg;
- }
-
- } // namespace detail
-
- template <typename T>
- inline constexpr T *addressof(T &arg) {
- return detail::addressof(arg, detail::has_addressof<T>{});
- }
-#endif
-
- template <typename T>
- inline constexpr T *addressof(const T &&) = delete;
-
- } // namespace cpp17
-
- template <typename T>
- struct remove_all_extents : identity<T> {};
-
- template <typename T, std::size_t N>
- struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};
-
- template <typename T>
- using remove_all_extents_t = typename remove_all_extents<T>::type;
-
- template <std::size_t N>
- using size_constant = std::integral_constant<std::size_t, N>;
-
- template <std::size_t I, typename T>
- struct indexed_type : size_constant<I>, identity<T> {};
-
- template <bool... Bs>
- using all = std::is_same<integer_sequence<bool, true, Bs...>,
- integer_sequence<bool, Bs..., true>>;
-
-#ifdef MPARK_TYPE_PACK_ELEMENT
- template <std::size_t I, typename... Ts>
- using type_pack_element_t = __type_pack_element<I, Ts...>;
-#else
- template <std::size_t I, typename... Ts>
- struct type_pack_element_impl {
- private:
- template <typename>
- struct set;
-
- template <std::size_t... Is>
- struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};
-
- template <typename T>
- inline static std::enable_if<true, T> impl(indexed_type<I, T>);
-
- inline static std::enable_if<false> impl(...);
-
- public:
- using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
- };
-
- template <std::size_t I, typename... Ts>
- using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
-
- template <std::size_t I, typename... Ts>
- using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
-#endif
-
-#ifdef MPARK_TRIVIALITY_TYPE_TRAITS
- using std::is_trivially_copy_constructible;
- using std::is_trivially_move_constructible;
- using std::is_trivially_copy_assignable;
- using std::is_trivially_move_assignable;
-#else
- template <typename T>
- struct is_trivially_copy_constructible
- : bool_constant<
- std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
-
- template <typename T>
- struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
-
- template <typename T>
- struct is_trivially_copy_assignable
- : bool_constant<
- std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
-
- template <typename T>
- struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
-#endif
-
- template <typename T, bool>
- struct dependent_type : T {};
-
- template <typename Is, std::size_t J>
- struct push_back;
-
- template <typename Is, std::size_t J>
- using push_back_t = typename push_back<Is, J>::type;
-
- template <std::size_t... Is, std::size_t J>
- struct push_back<index_sequence<Is...>, J> {
- using type = index_sequence<Is..., J>;
- };
-
- } // namespace lib
-} // namespace mpark
-
-#undef RETURN
-
-#endif // MPARK_LIB_HPP
-
-
-namespace mpark {
-
-#ifdef MPARK_RETURN_TYPE_DEDUCTION
-
-#define AUTO auto
-#define AUTO_RETURN(...) { return __VA_ARGS__; }
-
-#define AUTO_REFREF auto &&
-#define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }
-
-#define DECLTYPE_AUTO decltype(auto)
-#define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; }
-
-#else
-
-#define AUTO auto
-#define AUTO_RETURN(...) \
- -> lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; }
-
-#define AUTO_REFREF auto
-#define AUTO_REFREF_RETURN(...) \
- -> decltype((__VA_ARGS__)) { \
- static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, ""); \
- return __VA_ARGS__; \
- }
-
-#define DECLTYPE_AUTO auto
-#define DECLTYPE_AUTO_RETURN(...) \
- -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
-
-#endif
-
- class bad_variant_access : public std::exception {
- public:
- virtual const char *what() const noexcept { return "bad_variant_access"; }
- };
-
- [[noreturn]] inline void throw_bad_variant_access() {
-#ifdef MPARK_EXCEPTIONS
- throw bad_variant_access{};
-#else
- std::terminate();
-#ifdef MPARK_BUILTIN_UNREACHABLE
- __builtin_unreachable();
-#endif
-#endif
- }
-
- template <typename... Ts>
- class variant;
-
- template <typename T>
- struct variant_size;
-
-#ifdef MPARK_VARIABLE_TEMPLATES
- template <typename T>
- constexpr std::size_t variant_size_v = variant_size<T>::value;
-#endif
-
- template <typename T>
- struct variant_size<const T> : variant_size<T> {};
-
- template <typename T>
- struct variant_size<volatile T> : variant_size<T> {};
-
- template <typename T>
- struct variant_size<const volatile T> : variant_size<T> {};
-
- template <typename... Ts>
- struct variant_size<variant<Ts...>> : lib::size_constant<sizeof...(Ts)> {};
-
- template <std::size_t I, typename T>
- struct variant_alternative;
-
- template <std::size_t I, typename T>
- using variant_alternative_t = typename variant_alternative<I, T>::type;
-
- template <std::size_t I, typename T>
- struct variant_alternative<I, const T>
- : std::add_const<variant_alternative_t<I, T>> {};
-
- template <std::size_t I, typename T>
- struct variant_alternative<I, volatile T>
- : std::add_volatile<variant_alternative_t<I, T>> {};
-
- template <std::size_t I, typename T>
- struct variant_alternative<I, const volatile T>
- : std::add_cv<variant_alternative_t<I, T>> {};
-
- template <std::size_t I, typename... Ts>
- struct variant_alternative<I, variant<Ts...>> {
- static_assert(I < sizeof...(Ts),
- "Index out of bounds in std::variant_alternative<>");
- using type = lib::type_pack_element_t<I, Ts...>;
- };
-
- constexpr std::size_t variant_npos = static_cast<std::size_t>(-1);
-
- namespace detail {
-
- constexpr std::size_t not_found = static_cast<std::size_t>(-1);
- constexpr std::size_t ambiguous = static_cast<std::size_t>(-2);
-
-#ifdef MPARK_CPP14_CONSTEXPR
- template <typename T, typename... Ts>
- inline constexpr std::size_t find_index() {
- constexpr lib::array<bool, sizeof...(Ts)> matches = {
- {std::is_same<T, Ts>::value...}
- };
- std::size_t result = not_found;
- for (std::size_t i = 0; i < sizeof...(Ts); ++i) {
- if (matches[i]) {
- if (result != not_found) {
- return ambiguous;
- }
- result = i;
- }
- }
- return result;
- }
-#else
- inline constexpr std::size_t find_index_impl(std::size_t result,
- std::size_t) {
- return result;
- }
-
- template <typename... Bs>
- inline constexpr std::size_t find_index_impl(std::size_t result,
- std::size_t idx,
- bool b,
- Bs... bs) {
- return b ? (result != not_found ? ambiguous
- : find_index_impl(idx, idx + 1, bs...))
- : find_index_impl(result, idx + 1, bs...);
- }
-
- template <typename T, typename... Ts>
- inline constexpr std::size_t find_index() {
- return find_index_impl(not_found, 0, std::is_same<T, Ts>::value...);
- }
-#endif
-
- template <std::size_t I>
- using find_index_sfinae_impl =
- lib::enable_if_t<I != not_found && I != ambiguous,
- lib::size_constant<I>>;
-
- template <typename T, typename... Ts>
- using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;
-
- template <std::size_t I>
- struct find_index_checked_impl : lib::size_constant<I> {
- static_assert(I != not_found, "the specified type is not found.");
- static_assert(I != ambiguous, "the specified type is ambiguous.");
- };
-
- template <typename T, typename... Ts>
- using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>;
-
- struct valueless_t {};
-
- enum class Trait { TriviallyAvailable, Available, Unavailable };
-
- template <typename T,
- template <typename> class IsTriviallyAvailable,
- template <typename> class IsAvailable>
- inline constexpr Trait trait() {
- return IsTriviallyAvailable<T>::value
- ? Trait::TriviallyAvailable
- : IsAvailable<T>::value ? Trait::Available
- : Trait::Unavailable;
- }
-
-#ifdef MPARK_CPP14_CONSTEXPR
- template <typename... Traits>
- inline constexpr Trait common_trait(Traits... traits) {
- Trait result = Trait::TriviallyAvailable;
- for (Trait t : {traits...}) {
- if (static_cast<int>(t) > static_cast<int>(result)) {
- result = t;
- }
- }
- return result;
- }
-#else
- inline constexpr Trait common_trait_impl(Trait result) { return result; }
-
- template <typename... Traits>
- inline constexpr Trait common_trait_impl(Trait result,
- Trait t,
- Traits... ts) {
- return static_cast<int>(t) > static_cast<int>(result)
- ? common_trait_impl(t, ts...)
- : common_trait_impl(result, ts...);
- }
-
- template <typename... Traits>
- inline constexpr Trait common_trait(Traits... ts) {
- return common_trait_impl(Trait::TriviallyAvailable, ts...);
- }
-#endif
-
- template <typename... Ts>
- struct traits {
- static constexpr Trait copy_constructible_trait =
- common_trait(trait<Ts,
- lib::is_trivially_copy_constructible,
- std::is_copy_constructible>()...);
-
- static constexpr Trait move_constructible_trait =
- common_trait(trait<Ts,
- lib::is_trivially_move_constructible,
- std::is_move_constructible>()...);
-
- static constexpr Trait copy_assignable_trait =
- common_trait(copy_constructible_trait,
- trait<Ts,
- lib::is_trivially_copy_assignable,
- std::is_copy_assignable>()...);
-
- static constexpr Trait move_assignable_trait =
- common_trait(move_constructible_trait,
- trait<Ts,
- lib::is_trivially_move_assignable,
- std::is_move_assignable>()...);
-
- static constexpr Trait destructible_trait =
- common_trait(trait<Ts,
- std::is_trivially_destructible,
- std::is_destructible>()...);
- };
-
- namespace access {
-
- struct recursive_union {
-#ifdef MPARK_RETURN_TYPE_DEDUCTION
- template <typename V>
- inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) {
- return lib::forward<V>(v).head_;
- }
-
- template <typename V, std::size_t I>
- inline static constexpr auto &&get_alt(V &&v, in_place_index_t<I>) {
- return get_alt(lib::forward<V>(v).tail_, in_place_index_t<I - 1>{});
- }
-#else
- template <std::size_t I, bool Dummy = true>
- struct get_alt_impl {
- template <typename V>
- inline constexpr AUTO_REFREF operator()(V &&v) const
- AUTO_REFREF_RETURN(get_alt_impl<I - 1>{}(lib::forward<V>(v).tail_))
- };
-
- template <bool Dummy>
- struct get_alt_impl<0, Dummy> {
- template <typename V>
- inline constexpr AUTO_REFREF operator()(V &&v) const
- AUTO_REFREF_RETURN(lib::forward<V>(v).head_)
- };
-
- template <typename V, std::size_t I>
- inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t<I>)
- AUTO_REFREF_RETURN(get_alt_impl<I>{}(lib::forward<V>(v)))
-#endif
- };
-
- struct base {
- template <std::size_t I, typename V>
- inline static constexpr AUTO_REFREF get_alt(V &&v)
- AUTO_REFREF_RETURN(recursive_union::get_alt(
- data(lib::forward<V>(v)), in_place_index_t<I>{}))
- };
-
- struct variant {
- template <std::size_t I, typename V>
- inline static constexpr AUTO_REFREF get_alt(V &&v)
- AUTO_REFREF_RETURN(base::get_alt<I>(lib::forward<V>(v).impl_))
- };
-
- } // namespace access
-
- namespace visitation {
-
- struct base {
- template <typename T>
- inline static constexpr const T &at(const T &elem) {
- return elem;
- }
-
- template <typename T, std::size_t N, typename... Is>
- inline static constexpr const lib::remove_all_extents_t<T> &at(
- const lib::array<T, N> &elems, std::size_t i, Is... is) {
- return at(elems[i], is...);
- }
-
- template <typename F, typename... Fs>
- inline static constexpr int visit_visitor_return_type_check() {
- static_assert(lib::all<std::is_same<F, Fs>::value...>::value,
- "`mpark::visit` requires the visitor to have a single "
- "return type.");
- return 0;
- }
-
- template <typename... Fs>
- inline static constexpr lib::array<
- lib::common_type_t<lib::decay_t<Fs>...>,
- sizeof...(Fs)>
- make_farray(Fs &&... fs) {
- using result = lib::array<lib::common_type_t<lib::decay_t<Fs>...>,
- sizeof...(Fs)>;
- return visit_visitor_return_type_check<lib::decay_t<Fs>...>(),
- result{{lib::forward<Fs>(fs)...}};
- }
-
- template <std::size_t... Is>
- struct dispatcher {
- template <typename F, typename... Vs>
- struct impl {
- inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs)
- DECLTYPE_AUTO_RETURN(lib::invoke(
- static_cast<F>(f),
- access::base::get_alt<Is>(static_cast<Vs>(vs))...))
- };
- };
-
- template <typename F, typename... Vs, std::size_t... Is>
- inline static constexpr AUTO make_dispatch(lib::index_sequence<Is...>)
- AUTO_RETURN(&dispatcher<Is...>::template impl<F, Vs...>::dispatch)
-
- template <std::size_t I, typename F, typename... Vs>
- inline static constexpr AUTO make_fdiagonal_impl()
- AUTO_RETURN(make_dispatch<F, Vs...>(
- lib::index_sequence<lib::indexed_type<I, Vs>::value...>{}))
-
- template <typename F, typename... Vs, std::size_t... Is>
- inline static constexpr AUTO make_fdiagonal_impl(
- lib::index_sequence<Is...>)
- AUTO_RETURN(make_farray(make_fdiagonal_impl<Is, F, Vs...>()...))
-
- template <typename F, typename V, typename... Vs>
- inline static constexpr /* auto * */ auto make_fdiagonal()
- -> decltype(make_fdiagonal_impl<F, V, Vs...>(
- lib::make_index_sequence<lib::decay_t<V>::size()>{})) {
- static_assert(lib::all<(lib::decay_t<V>::size() ==
- lib::decay_t<Vs>::size())...>::value,
- "all of the variants must be the same size.");
- return make_fdiagonal_impl<F, V, Vs...>(
- lib::make_index_sequence<lib::decay_t<V>::size()>{});
- }
-
-#ifdef MPARK_RETURN_TYPE_DEDUCTION
- template <typename F, typename... Vs, typename Is>
- inline static constexpr auto make_fmatrix_impl(Is is) {
- return make_dispatch<F, Vs...>(is);
- }
-
- template <typename F,
- typename... Vs,
- typename Is,
- std::size_t... Js,
- typename... Ls>
- inline static constexpr auto make_fmatrix_impl(
- Is, lib::index_sequence<Js...>, Ls... ls) {
- return make_farray(make_fmatrix_impl<F, Vs...>(
- lib::push_back_t<Is, Js>{}, ls...)...);
- }
-
- template <typename F, typename... Vs>
- inline static constexpr auto make_fmatrix() {
- return make_fmatrix_impl<F, Vs...>(
- lib::index_sequence<>{},
- lib::make_index_sequence<lib::decay_t<Vs>::size()>{}...);
- }
-#else
- template <typename F, typename... Vs>
- struct make_fmatrix_impl {
- template <typename...>
- struct impl;
-
- template <typename Is>
- struct impl<Is> {
- inline constexpr AUTO operator()() const
- AUTO_RETURN(make_dispatch<F, Vs...>(Is{}))
- };
-
- template <typename Is, std::size_t... Js, typename... Ls>
- struct impl<Is, lib::index_sequence<Js...>, Ls...> {
- inline constexpr AUTO operator()() const
- AUTO_RETURN(
- make_farray(impl<lib::push_back_t<Is, Js>, Ls...>{}()...))
- };
- };
-
- template <typename F, typename... Vs>
- inline static constexpr AUTO make_fmatrix()
- AUTO_RETURN(
- typename make_fmatrix_impl<F, Vs...>::template impl<
- lib::index_sequence<>,
- lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}())
-#endif
- }; // namespace base
-
- template <typename F, typename... Vs>
- using FDiagonal = decltype(base::make_fdiagonal<F, Vs...>());
-
- template <typename F, typename... Vs>
- struct fdiagonal {
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4268)
-#endif
- static constexpr FDiagonal<F, Vs...> value =
- base::make_fdiagonal<F, Vs...>();
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- };
-
- template <typename F, typename... Vs>
- constexpr FDiagonal<F, Vs...> fdiagonal<F, Vs...>::value;
-
- template <typename F, typename... Vs>
- using FMatrix = decltype(base::make_fmatrix<F, Vs...>());
-
- template <typename F, typename... Vs>
- struct fmatrix {
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4268)
-#endif
- static constexpr FMatrix<F, Vs...> value =
- base::make_fmatrix<F, Vs...>();
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- };
-
- template <typename F, typename... Vs>
- constexpr FMatrix<F, Vs...> fmatrix<F, Vs...>::value;
-
- struct alt {
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
- Visitor &&visitor,
- Vs &&... vs)
- DECLTYPE_AUTO_RETURN(base::at(
- fdiagonal<Visitor &&,
- decltype(as_base(lib::forward<Vs>(vs)))...>::value,
- index)(lib::forward<Visitor>(visitor),
- as_base(lib::forward<Vs>(vs))...))
-
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,
- Vs &&... vs)
- DECLTYPE_AUTO_RETURN(base::at(
- fmatrix<Visitor &&,
- decltype(as_base(lib::forward<Vs>(vs)))...>::value,
- vs.index()...)(lib::forward<Visitor>(visitor),
- as_base(lib::forward<Vs>(vs))...))
- };
-
- struct variant {
- private:
- template <typename Visitor, typename... Values>
- struct visit_exhaustive_visitor_check {
- static_assert(
- lib::is_invocable<Visitor, Values...>::value,
- "`mpark::visit` requires the visitor to be exhaustive.");
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4100)
-#endif
- inline constexpr DECLTYPE_AUTO operator()(Visitor &&visitor,
- Values &&... values) const
- DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),
- lib::forward<Values>(values)...))
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- };
-
- template <typename Visitor>
- struct value_visitor {
- Visitor &&visitor_;
-
- template <typename... Alts>
- inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const
- DECLTYPE_AUTO_RETURN(
- visit_exhaustive_visitor_check<
- Visitor,
- decltype((lib::forward<Alts>(alts).value))...>{}(
- lib::forward<Visitor>(visitor_),
- lib::forward<Alts>(alts).value...))
- };
-
- template <typename Visitor>
- inline static constexpr AUTO make_value_visitor(Visitor &&visitor)
- AUTO_RETURN(value_visitor<Visitor>{lib::forward<Visitor>(visitor)})
-
- public:
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
- Visitor &&visitor,
- Vs &&... vs)
- DECLTYPE_AUTO_RETURN(
- alt::visit_alt_at(index,
- lib::forward<Visitor>(visitor),
- lib::forward<Vs>(vs).impl_...))
-
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,
- Vs &&... vs)
- DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward<Visitor>(visitor),
- lib::forward<Vs>(vs).impl_...))
-
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index,
- Visitor &&visitor,
- Vs &&... vs)
- DECLTYPE_AUTO_RETURN(
- visit_alt_at(index,
- make_value_visitor(lib::forward<Visitor>(visitor)),
- lib::forward<Vs>(vs)...))
-
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor,
- Vs &&... vs)
- DECLTYPE_AUTO_RETURN(
- visit_alt(make_value_visitor(lib::forward<Visitor>(visitor)),
- lib::forward<Vs>(vs)...))
- };
-
- } // namespace visitation
-
- template <std::size_t Index, typename T>
- struct alt {
- using value_type = T;
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4244)
-#endif
- template <typename... Args>
- inline explicit constexpr alt(in_place_t, Args &&... args)
- : value(lib::forward<Args>(args)...) {}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
- T value;
- };
-
- template <Trait DestructibleTrait, std::size_t Index, typename... Ts>
- union recursive_union;
-
- template <Trait DestructibleTrait, std::size_t Index>
- union recursive_union<DestructibleTrait, Index> {};
-
-#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \
- template <std::size_t Index, typename T, typename... Ts> \
- union recursive_union<destructible_trait, Index, T, Ts...> { \
- public: \
- inline explicit constexpr recursive_union(valueless_t) noexcept \
- : dummy_{} {} \
- \
- template <typename... Args> \
- inline explicit constexpr recursive_union(in_place_index_t<0>, \
- Args &&... args) \
- : head_(in_place_t{}, lib::forward<Args>(args)...) {} \
- \
- template <std::size_t I, typename... Args> \
- inline explicit constexpr recursive_union(in_place_index_t<I>, \
- Args &&... args) \
- : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) {} \
- \
- recursive_union(const recursive_union &) = default; \
- recursive_union(recursive_union &&) = default; \
- \
- destructor \
- \
- recursive_union &operator=(const recursive_union &) = default; \
- recursive_union &operator=(recursive_union &&) = default; \
- \
- private: \
- char dummy_; \
- alt<Index, T> head_; \
- recursive_union<destructible_trait, Index + 1, Ts...> tail_; \
- \
- friend struct access::recursive_union; \
- }
-
- MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable,
- ~recursive_union() = default;);
- MPARK_VARIANT_RECURSIVE_UNION(Trait::Available,
- ~recursive_union() {});
- MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable,
- ~recursive_union() = delete;);
-
-#undef MPARK_VARIANT_RECURSIVE_UNION
-
- using index_t = unsigned int;
-
- template <Trait DestructibleTrait, typename... Ts>
- class base {
- public:
- inline explicit constexpr base(valueless_t tag) noexcept
- : data_(tag), index_(static_cast<index_t>(-1)) {}
-
- template <std::size_t I, typename... Args>
- inline explicit constexpr base(in_place_index_t<I>, Args &&... args)
- : data_(in_place_index_t<I>{}, lib::forward<Args>(args)...),
- index_(I) {}
-
- inline constexpr bool valueless_by_exception() const noexcept {
- return index_ == static_cast<index_t>(-1);
- }
-
- inline constexpr std::size_t index() const noexcept {
- return valueless_by_exception() ? variant_npos : index_;
- }
-
- protected:
- using data_t = recursive_union<DestructibleTrait, 0, Ts...>;
-
- friend inline constexpr base &as_base(base &b) { return b; }
- friend inline constexpr const base &as_base(const base &b) { return b; }
- friend inline constexpr base &&as_base(base &&b) { return lib::move(b); }
- friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); }
-
- friend inline constexpr data_t &data(base &b) { return b.data_; }
- friend inline constexpr const data_t &data(const base &b) { return b.data_; }
- friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; }
- friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; }
-
- inline static constexpr std::size_t size() { return sizeof...(Ts); }
-
- data_t data_;
- index_t index_;
-
- friend struct access::base;
- friend struct visitation::base;
- };
-
- struct dtor {
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4100)
-#endif
- template <typename Alt>
- inline void operator()(Alt &alt) const noexcept { alt.~Alt(); }
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- };
-
-#if defined(_MSC_VER) && _MSC_VER < 1910
-#define INHERITING_CTOR(type, base) \
- template <typename... Args> \
- inline explicit constexpr type(Args &&... args) \
- : base(lib::forward<Args>(args)...) {}
-#else
-#define INHERITING_CTOR(type, base) using base::base;
-#endif
-
- template <typename Traits, Trait = Traits::destructible_trait>
- class destructor;
-
-#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
- template <typename... Ts> \
- class destructor<traits<Ts...>, destructible_trait> \
- : public base<destructible_trait, Ts...> { \
- using super = base<destructible_trait, Ts...>; \
- \
- public: \
- INHERITING_CTOR(destructor, super) \
- using super::operator=; \
- \
- destructor(const destructor &) = default; \
- destructor(destructor &&) = default; \
- definition \
- destructor &operator=(const destructor &) = default; \
- destructor &operator=(destructor &&) = default; \
- \
- protected: \
- destroy \
- }
-
- MPARK_VARIANT_DESTRUCTOR(
- Trait::TriviallyAvailable,
- ~destructor() = default;,
- inline void destroy() noexcept {
- this->index_ = static_cast<index_t>(-1);
- });
-
- MPARK_VARIANT_DESTRUCTOR(
- Trait::Available,
- ~destructor() { destroy(); },
- inline void destroy() noexcept {
- if (!this->valueless_by_exception()) {
- visitation::alt::visit_alt(dtor{}, *this);
- }
- this->index_ = static_cast<index_t>(-1);
- });
-
- MPARK_VARIANT_DESTRUCTOR(
- Trait::Unavailable,
- ~destructor() = delete;,
- inline void destroy() noexcept = delete;);
-
-#undef MPARK_VARIANT_DESTRUCTOR
-
- template <typename Traits>
- class constructor : public destructor<Traits> {
- using super = destructor<Traits>;
-
- public:
- INHERITING_CTOR(constructor, super)
- using super::operator=;
-
- protected:
-#ifndef MPARK_GENERIC_LAMBDAS
- struct ctor {
- template <typename LhsAlt, typename RhsAlt>
- inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const {
- constructor::construct_alt(lhs_alt,
- lib::forward<RhsAlt>(rhs_alt).value);
- }
- };
-#endif
-
- template <std::size_t I, typename T, typename... Args>
- inline static T &construct_alt(alt<I, T> &a, Args &&... args) {
- ::new (static_cast<void *>(lib::addressof(a)))
- alt<I, T>(in_place_t{}, lib::forward<Args>(args)...);
- return a.value;
- }
-
- template <typename Rhs>
- inline static void generic_construct(constructor &lhs, Rhs &&rhs) {
- lhs.destroy();
- if (!rhs.valueless_by_exception()) {
- visitation::alt::visit_alt_at(
- rhs.index(),
-#ifdef MPARK_GENERIC_LAMBDAS
- [](auto &lhs_alt, auto &&rhs_alt) {
- constructor::construct_alt(
- lhs_alt, lib::forward<decltype(rhs_alt)>(rhs_alt).value);
- }
-#else
- ctor{}
-#endif
- ,
- lhs,
- lib::forward<Rhs>(rhs));
- lhs.index_ = rhs.index_;
- }
- }
- };
-
- template <typename Traits, Trait = Traits::move_constructible_trait>
- class move_constructor;
-
-#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
- template <typename... Ts> \
- class move_constructor<traits<Ts...>, move_constructible_trait> \
- : public constructor<traits<Ts...>> { \
- using super = constructor<traits<Ts...>>; \
- \
- public: \
- INHERITING_CTOR(move_constructor, super) \
- using super::operator=; \
- \
- move_constructor(const move_constructor &) = default; \
- definition \
- ~move_constructor() = default; \
- move_constructor &operator=(const move_constructor &) = default; \
- move_constructor &operator=(move_constructor &&) = default; \
- }
-
- MPARK_VARIANT_MOVE_CONSTRUCTOR(
- Trait::TriviallyAvailable,
- move_constructor(move_constructor &&that) = default;);
-
- MPARK_VARIANT_MOVE_CONSTRUCTOR(
- Trait::Available,
- move_constructor(move_constructor &&that) noexcept(
- lib::all<std::is_nothrow_move_constructible<Ts>::value...>::value)
- : move_constructor(valueless_t{}) {
- this->generic_construct(*this, lib::move(that));
- });
-
- MPARK_VARIANT_MOVE_CONSTRUCTOR(
- Trait::Unavailable,
- move_constructor(move_constructor &&) = delete;);
-
-#undef MPARK_VARIANT_MOVE_CONSTRUCTOR
-
- template <typename Traits, Trait = Traits::copy_constructible_trait>
- class copy_constructor;
-
-#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
- template <typename... Ts> \
- class copy_constructor<traits<Ts...>, copy_constructible_trait> \
- : public move_constructor<traits<Ts...>> { \
- using super = move_constructor<traits<Ts...>>; \
- \
- public: \
- INHERITING_CTOR(copy_constructor, super) \
- using super::operator=; \
- \
- definition \
- copy_constructor(copy_constructor &&) = default; \
- ~copy_constructor() = default; \
- copy_constructor &operator=(const copy_constructor &) = default; \
- copy_constructor &operator=(copy_constructor &&) = default; \
- }
-
- MPARK_VARIANT_COPY_CONSTRUCTOR(
- Trait::TriviallyAvailable,
- copy_constructor(const copy_constructor &that) = default;);
-
- MPARK_VARIANT_COPY_CONSTRUCTOR(
- Trait::Available,
- copy_constructor(const copy_constructor &that)
- : copy_constructor(valueless_t{}) {
- this->generic_construct(*this, that);
- });
-
- MPARK_VARIANT_COPY_CONSTRUCTOR(
- Trait::Unavailable,
- copy_constructor(const copy_constructor &) = delete;);
-
-#undef MPARK_VARIANT_COPY_CONSTRUCTOR
-
- template <typename Traits>
- class assignment : public copy_constructor<Traits> {
- using super = copy_constructor<Traits>;
-
- public:
- INHERITING_CTOR(assignment, super)
- using super::operator=;
-
- template <std::size_t I, typename... Args>
- inline /* auto & */ auto emplace(Args &&... args)
- -> decltype(this->construct_alt(access::base::get_alt<I>(*this),
- lib::forward<Args>(args)...)) {
- this->destroy();
- auto &result = this->construct_alt(access::base::get_alt<I>(*this),
- lib::forward<Args>(args)...);
- this->index_ = I;
- return result;
- }
-
- protected:
-#ifndef MPARK_GENERIC_LAMBDAS
- template <typename That>
- struct assigner {
- template <typename ThisAlt, typename ThatAlt>
- inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const {
- self->assign_alt(this_alt, lib::forward<ThatAlt>(that_alt).value);
- }
- assignment *self;
- };
-#endif
-
- template <std::size_t I, typename T, typename Arg>
- inline void assign_alt(alt<I, T> &a, Arg &&arg) {
- if (this->index() == I) {
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4244)
-#endif
- a.value = lib::forward<Arg>(arg);
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- } else {
- struct {
- void operator()(std::true_type) const {
- this_->emplace<I>(lib::forward<Arg>(arg_));
- }
- void operator()(std::false_type) const {
- this_->emplace<I>(T(lib::forward<Arg>(arg_)));
- }
- assignment *this_;
- Arg &&arg_;
- } impl{this, lib::forward<Arg>(arg)};
- impl(lib::bool_constant<
- std::is_nothrow_constructible<T, Arg>::value ||
- !std::is_nothrow_move_constructible<T>::value>{});
- }
- }
-
- template <typename That>
- inline void generic_assign(That &&that) {
- if (this->valueless_by_exception() && that.valueless_by_exception()) {
- // do nothing.
- } else if (that.valueless_by_exception()) {
- this->destroy();
- } else {
- visitation::alt::visit_alt_at(
- that.index(),
-#ifdef MPARK_GENERIC_LAMBDAS
- [this](auto &this_alt, auto &&that_alt) {
- this->assign_alt(
- this_alt, lib::forward<decltype(that_alt)>(that_alt).value);
- }
-#else
- assigner<That>{this}
-#endif
- ,
- *this,
- lib::forward<That>(that));
- }
- }
- };
-
- template <typename Traits, Trait = Traits::move_assignable_trait>
- class move_assignment;
-
-#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
- template <typename... Ts> \
- class move_assignment<traits<Ts...>, move_assignable_trait> \
- : public assignment<traits<Ts...>> { \
- using super = assignment<traits<Ts...>>; \
- \
- public: \
- INHERITING_CTOR(move_assignment, super) \
- using super::operator=; \
- \
- move_assignment(const move_assignment &) = default; \
- move_assignment(move_assignment &&) = default; \
- ~move_assignment() = default; \
- move_assignment &operator=(const move_assignment &) = default; \
- definition \
- }
-
- MPARK_VARIANT_MOVE_ASSIGNMENT(
- Trait::TriviallyAvailable,
- move_assignment &operator=(move_assignment &&that) = default;);
-
- MPARK_VARIANT_MOVE_ASSIGNMENT(
- Trait::Available,
- move_assignment &
- operator=(move_assignment &&that) noexcept(
- lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
- std::is_nothrow_move_assignable<Ts>::value)...>::value) {
- this->generic_assign(lib::move(that));
- return *this;
- });
-
- MPARK_VARIANT_MOVE_ASSIGNMENT(
- Trait::Unavailable,
- move_assignment &operator=(move_assignment &&) = delete;);
-
-#undef MPARK_VARIANT_MOVE_ASSIGNMENT
-
- template <typename Traits, Trait = Traits::copy_assignable_trait>
- class copy_assignment;
-
-#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
- template <typename... Ts> \
- class copy_assignment<traits<Ts...>, copy_assignable_trait> \
- : public move_assignment<traits<Ts...>> { \
- using super = move_assignment<traits<Ts...>>; \
- \
- public: \
- INHERITING_CTOR(copy_assignment, super) \
- using super::operator=; \
- \
- copy_assignment(const copy_assignment &) = default; \
- copy_assignment(copy_assignment &&) = default; \
- ~copy_assignment() = default; \
- definition \
- copy_assignment &operator=(copy_assignment &&) = default; \
- }
-
- MPARK_VARIANT_COPY_ASSIGNMENT(
- Trait::TriviallyAvailable,
- copy_assignment &operator=(const copy_assignment &that) = default;);
-
- MPARK_VARIANT_COPY_ASSIGNMENT(
- Trait::Available,
- copy_assignment &operator=(const copy_assignment &that) {
- this->generic_assign(that);
- return *this;
- });
-
- MPARK_VARIANT_COPY_ASSIGNMENT(
- Trait::Unavailable,
- copy_assignment &operator=(const copy_assignment &) = delete;);
-
-#undef MPARK_VARIANT_COPY_ASSIGNMENT
-
- template <typename... Ts>
- class impl : public copy_assignment<traits<Ts...>> {
- using super = copy_assignment<traits<Ts...>>;
-
- public:
- INHERITING_CTOR(impl, super)
- using super::operator=;
-
- template <std::size_t I, typename Arg>
- inline void assign(Arg &&arg) {
- this->assign_alt(access::base::get_alt<I>(*this),
- lib::forward<Arg>(arg));
- }
-
- inline void swap(impl &that) {
- if (this->valueless_by_exception() && that.valueless_by_exception()) {
- // do nothing.
- } else if (this->index() == that.index()) {
- visitation::alt::visit_alt_at(this->index(),
-#ifdef MPARK_GENERIC_LAMBDAS
- [](auto &this_alt, auto &that_alt) {
- using std::swap;
- swap(this_alt.value,
- that_alt.value);
- }
-#else
- swapper{}
-#endif
- ,
- *this,
- that);
- } else {
- impl *lhs = this;
- impl *rhs = lib::addressof(that);
- if (lhs->move_nothrow() && !rhs->move_nothrow()) {
- std::swap(lhs, rhs);
- }
- impl tmp(lib::move(*rhs));
-#ifdef MPARK_EXCEPTIONS
- // EXTENSION: When the move construction of `lhs` into `rhs` throws
- // and `tmp` is nothrow move constructible then we move `tmp` back
- // into `rhs` and provide the strong exception safety guarantee.
- try {
- this->generic_construct(*rhs, lib::move(*lhs));
- } catch (...) {
- if (tmp.move_nothrow()) {
- this->generic_construct(*rhs, lib::move(tmp));
- }
- throw;
- }
-#else
- this->generic_construct(*rhs, lib::move(*lhs));
-#endif
- this->generic_construct(*lhs, lib::move(tmp));
- }
- }
-
- private:
-#ifndef MPARK_GENERIC_LAMBDAS
- struct swapper {
- template <typename ThisAlt, typename ThatAlt>
- inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const {
- using std::swap;
- swap(this_alt.value, that_alt.value);
- }
- };
-#endif
-
- inline constexpr bool move_nothrow() const {
- return this->valueless_by_exception() ||
- lib::array<bool, sizeof...(Ts)>{
- {std::is_nothrow_move_constructible<Ts>::value...}
- }[this->index()];
- }
- };
-
- template <std::size_t I, typename T>
- struct overload_leaf {
- using F = lib::size_constant<I> (*)(T);
- operator F() const { return nullptr; }
- };
-
- template <typename... Ts>
- struct overload_impl {
- private:
- template <typename>
- struct impl;
-
- template <std::size_t... Is>
- struct impl<lib::index_sequence<Is...>> : overload_leaf<Is, Ts>... {};
-
- public:
- using type = impl<lib::index_sequence_for<Ts...>>;
- };
-
- template <typename... Ts>
- using overload = typename overload_impl<Ts...>::type;
-
- template <typename T, typename... Ts>
- using best_match = lib::invoke_result_t<overload<Ts...>, T &&>;
-
- template <typename T>
- struct is_in_place_index : std::false_type {};
-
- template <std::size_t I>
- struct is_in_place_index<in_place_index_t<I>> : std::true_type {};
-
- template <typename T>
- struct is_in_place_type : std::false_type {};
-
- template <typename T>
- struct is_in_place_type<in_place_type_t<T>> : std::true_type {};
-
- } // detail
-
- template <typename... Ts>
- class variant {
- static_assert(0 < sizeof...(Ts),
- "variant must consist of at least one alternative.");
-
- static_assert(lib::all<!std::is_array<Ts>::value...>::value,
- "variant can not have an array type as an alternative.");
-
- static_assert(lib::all<!std::is_reference<Ts>::value...>::value,
- "variant can not have a reference type as an alternative.");
-
- static_assert(lib::all<!std::is_void<Ts>::value...>::value,
- "variant can not have a void type as an alternative.");
-
- public:
- template <
- typename Front = lib::type_pack_element_t<0, Ts...>,
- lib::enable_if_t<std::is_default_constructible<Front>::value, int> = 0>
- inline constexpr variant()
- : impl_(in_place_index_t<0>{}) {}
-
- variant(const variant &) = default;
- variant(variant &&) = default;
-
- template <
- typename Arg,
- typename Decayed = lib::decay_t<Arg>,
- lib::enable_if_t<!std::is_same<Decayed, variant>::value, int> = 0,
- lib::enable_if_t<!detail::is_in_place_index<Decayed>::value, int> = 0,
- lib::enable_if_t<!detail::is_in_place_type<Decayed>::value, int> = 0,
- std::size_t I = detail::best_match<Arg, Ts...>::value,
- typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T, Arg>::value, int> = 0>
- inline constexpr variant(Arg &&arg) noexcept(
- std::is_nothrow_constructible<T, Arg>::value)
- : impl_(in_place_index_t<I>{}, lib::forward<Arg>(arg)) {}
-
- template <
- std::size_t I,
- typename... Args,
- typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
- inline explicit constexpr variant(
- in_place_index_t<I>,
- Args &&... args) noexcept(std::is_nothrow_constructible<T,
- Args...>::value)
- : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}
-
- template <
- std::size_t I,
- typename Up,
- typename... Args,
- typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T,
- std::initializer_list<Up> &,
- Args...>::value,
- int> = 0>
- inline explicit constexpr variant(
- in_place_index_t<I>,
- std::initializer_list<Up> il,
- Args &&... args) noexcept(std::
- is_nothrow_constructible<
- T,
- std::initializer_list<Up> &,
- Args...>::value)
- : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}
-
- template <
- typename T,
- typename... Args,
- std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
- lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
- inline explicit constexpr variant(
- in_place_type_t<T>,
- Args &&... args) noexcept(std::is_nothrow_constructible<T,
- Args...>::value)
- : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}
-
- template <
- typename T,
- typename Up,
- typename... Args,
- std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
- lib::enable_if_t<std::is_constructible<T,
- std::initializer_list<Up> &,
- Args...>::value,
- int> = 0>
- inline explicit constexpr variant(
- in_place_type_t<T>,
- std::initializer_list<Up> il,
- Args &&... args) noexcept(std::
- is_nothrow_constructible<
- T,
- std::initializer_list<Up> &,
- Args...>::value)
- : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}
-
- ~variant() = default;
-
- variant &operator=(const variant &) = default;
- variant &operator=(variant &&) = default;
-
- template <typename Arg,
- lib::enable_if_t<!std::is_same<lib::decay_t<Arg>, variant>::value,
- int> = 0,
- std::size_t I = detail::best_match<Arg, Ts...>::value,
- typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<(std::is_assignable<T &, Arg>::value &&
- std::is_constructible<T, Arg>::value),
- int> = 0>
- inline variant &operator=(Arg &&arg) {
- impl_.template assign<I>(lib::forward<Arg>(arg));
- return *this;
- }
-
- template <
- std::size_t I,
- typename... Args,
- typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
- inline T &emplace(Args &&... args) {
- return impl_.template emplace<I>(lib::forward<Args>(args)...);
- }
-
- template <
- std::size_t I,
- typename Up,
- typename... Args,
- typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T,
- std::initializer_list<Up> &,
- Args...>::value,
- int> = 0>
- inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
- return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
- }
-
- template <
- typename T,
- typename... Args,
- std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
- lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
- inline T &emplace(Args &&... args) {
- return impl_.template emplace<I>(lib::forward<Args>(args)...);
- }
-
- template <
- typename T,
- typename Up,
- typename... Args,
- std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
- lib::enable_if_t<std::is_constructible<T,
- std::initializer_list<Up> &,
- Args...>::value,
- int> = 0>
- inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
- return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
- }
-
- inline constexpr bool valueless_by_exception() const noexcept {
- return impl_.valueless_by_exception();
- }
-
- inline constexpr std::size_t index() const noexcept {
- return impl_.index();
- }
-
- template <bool Dummy = true,
- lib::enable_if_t<
- lib::all<Dummy,
- (lib::dependent_type<std::is_move_constructible<Ts>,
- Dummy>::value &&
- lib::dependent_type<lib::is_swappable<Ts>,
- Dummy>::value)...>::value,
- int> = 0>
- inline void swap(variant &that) noexcept(
- lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
- lib::is_nothrow_swappable<Ts>::value)...>::value) {
- impl_.swap(that.impl_);
- }
-
- private:
- detail::impl<Ts...> impl_;
-
- friend struct detail::access::variant;
- friend struct detail::visitation::variant;
- };
-
- template <std::size_t I, typename... Ts>
- inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {
- return v.index() == I;
- }
-
- template <typename T, typename... Ts>
- inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {
- return holds_alternative<detail::find_index_checked<T, Ts...>::value>(v);
- }
-
- namespace detail {
- template <std::size_t I, typename V>
- struct generic_get_impl {
- constexpr generic_get_impl(int) {}
-
- constexpr AUTO_REFREF operator()(V &&v) const
- AUTO_REFREF_RETURN(
- access::variant::get_alt<I>(lib::forward<V>(v)).value)
- };
-
- template <std::size_t I, typename V>
- inline constexpr AUTO_REFREF generic_get(V &&v)
- AUTO_REFREF_RETURN(generic_get_impl<I, V>(
- holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(
- lib::forward<V>(v)))
- } // namespace detail
-
- template <std::size_t I, typename... Ts>
- inline constexpr variant_alternative_t<I, variant<Ts...>> &get(
- variant<Ts...> &v) {
- return detail::generic_get<I>(v);
- }
-
- template <std::size_t I, typename... Ts>
- inline constexpr variant_alternative_t<I, variant<Ts...>> &&get(
- variant<Ts...> &&v) {
- return detail::generic_get<I>(lib::move(v));
- }
-
- template <std::size_t I, typename... Ts>
- inline constexpr const variant_alternative_t<I, variant<Ts...>> &get(
- const variant<Ts...> &v) {
- return detail::generic_get<I>(v);
- }
-
- template <std::size_t I, typename... Ts>
- inline constexpr const variant_alternative_t<I, variant<Ts...>> &&get(
- const variant<Ts...> &&v) {
- return detail::generic_get<I>(lib::move(v));
- }
-
- template <typename T, typename... Ts>
- inline constexpr T &get(variant<Ts...> &v) {
- return get<detail::find_index_checked<T, Ts...>::value>(v);
- }
-
- template <typename T, typename... Ts>
- inline constexpr T &&get(variant<Ts...> &&v) {
- return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
- }
-
- template <typename T, typename... Ts>
- inline constexpr const T &get(const variant<Ts...> &v) {
- return get<detail::find_index_checked<T, Ts...>::value>(v);
- }
-
- template <typename T, typename... Ts>
- inline constexpr const T &&get(const variant<Ts...> &&v) {
- return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
- }
-
- namespace detail {
-
- template <std::size_t I, typename V>
- inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept
- AUTO_RETURN(v && holds_alternative<I>(*v)
- ? lib::addressof(access::variant::get_alt<I>(*v).value)
- : nullptr)
-
- } // namespace detail
-
- template <std::size_t I, typename... Ts>
- inline constexpr lib::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>
- get_if(variant<Ts...> *v) noexcept {
- return detail::generic_get_if<I>(v);
- }
-
- template <std::size_t I, typename... Ts>
- inline constexpr lib::add_pointer_t<
- const variant_alternative_t<I, variant<Ts...>>>
- get_if(const variant<Ts...> *v) noexcept {
- return detail::generic_get_if<I>(v);
- }
-
- template <typename T, typename... Ts>
- inline constexpr lib::add_pointer_t<T>
- get_if(variant<Ts...> *v) noexcept {
- return get_if<detail::find_index_checked<T, Ts...>::value>(v);
- }
-
- template <typename T, typename... Ts>
- inline constexpr lib::add_pointer_t<const T>
- get_if(const variant<Ts...> *v) noexcept {
- return get_if<detail::find_index_checked<T, Ts...>::value>(v);
- }
-
- template <typename... Ts>
- inline constexpr bool operator==(const variant<Ts...> &lhs,
- const variant<Ts...> &rhs) {
- using detail::visitation::variant;
- using lib::equal_to;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (lhs.index() != rhs.index()) return false;
- if (lhs.valueless_by_exception()) return true;
- return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);
-#else
- return lhs.index() == rhs.index() &&
- (lhs.valueless_by_exception() ||
- variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs));
-#endif
- }
-
- template <typename... Ts>
- inline constexpr bool operator!=(const variant<Ts...> &lhs,
- const variant<Ts...> &rhs) {
- using detail::visitation::variant;
- using lib::not_equal_to;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (lhs.index() != rhs.index()) return true;
- if (lhs.valueless_by_exception()) return false;
- return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);
-#else
- return lhs.index() != rhs.index() ||
- (!lhs.valueless_by_exception() &&
- variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs));
-#endif
- }
-
- template <typename... Ts>
- inline constexpr bool operator<(const variant<Ts...> &lhs,
- const variant<Ts...> &rhs) {
- using detail::visitation::variant;
- using lib::less;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (rhs.valueless_by_exception()) return false;
- if (lhs.valueless_by_exception()) return true;
- if (lhs.index() < rhs.index()) return true;
- if (lhs.index() > rhs.index()) return false;
- return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);
-#else
- return !rhs.valueless_by_exception() &&
- (lhs.valueless_by_exception() || lhs.index() < rhs.index() ||
- (lhs.index() == rhs.index() &&
- variant::visit_value_at(lhs.index(), less{}, lhs, rhs)));
-#endif
- }
-
- template <typename... Ts>
- inline constexpr bool operator>(const variant<Ts...> &lhs,
- const variant<Ts...> &rhs) {
- using detail::visitation::variant;
- using lib::greater;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (lhs.valueless_by_exception()) return false;
- if (rhs.valueless_by_exception()) return true;
- if (lhs.index() > rhs.index()) return true;
- if (lhs.index() < rhs.index()) return false;
- return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);
-#else
- return !lhs.valueless_by_exception() &&
- (rhs.valueless_by_exception() || lhs.index() > rhs.index() ||
- (lhs.index() == rhs.index() &&
- variant::visit_value_at(lhs.index(), greater{}, lhs, rhs)));
-#endif
- }
-
- template <typename... Ts>
- inline constexpr bool operator<=(const variant<Ts...> &lhs,
- const variant<Ts...> &rhs) {
- using detail::visitation::variant;
- using lib::less_equal;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (lhs.valueless_by_exception()) return true;
- if (rhs.valueless_by_exception()) return false;
- if (lhs.index() < rhs.index()) return true;
- if (lhs.index() > rhs.index()) return false;
- return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);
-#else
- return lhs.valueless_by_exception() ||
- (!rhs.valueless_by_exception() &&
- (lhs.index() < rhs.index() ||
- (lhs.index() == rhs.index() &&
- variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs))));
-#endif
- }
-
- template <typename... Ts>
- inline constexpr bool operator>=(const variant<Ts...> &lhs,
- const variant<Ts...> &rhs) {
- using detail::visitation::variant;
- using lib::greater_equal;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (rhs.valueless_by_exception()) return true;
- if (lhs.valueless_by_exception()) return false;
- if (lhs.index() > rhs.index()) return true;
- if (lhs.index() < rhs.index()) return false;
- return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);
-#else
- return rhs.valueless_by_exception() ||
- (!lhs.valueless_by_exception() &&
- (lhs.index() > rhs.index() ||
- (lhs.index() == rhs.index() &&
- variant::visit_value_at(
- lhs.index(), greater_equal{}, lhs, rhs))));
-#endif
- }
-
- struct monostate {};
-
- inline constexpr bool operator<(monostate, monostate) noexcept {
- return false;
- }
-
- inline constexpr bool operator>(monostate, monostate) noexcept {
- return false;
- }
-
- inline constexpr bool operator<=(monostate, monostate) noexcept {
- return true;
- }
-
- inline constexpr bool operator>=(monostate, monostate) noexcept {
- return true;
- }
-
- inline constexpr bool operator==(monostate, monostate) noexcept {
- return true;
- }
-
- inline constexpr bool operator!=(monostate, monostate) noexcept {
- return false;
- }
-
-#ifdef MPARK_CPP14_CONSTEXPR
- namespace detail {
-
- inline constexpr bool all(std::initializer_list<bool> bs) {
- for (bool b : bs) {
- if (!b) {
- return false;
- }
- }
- return true;
- }
-
- } // namespace detail
-
- template <typename Visitor, typename... Vs>
- inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) {
- return (detail::all({!vs.valueless_by_exception()...})
- ? (void)0
- : throw_bad_variant_access()),
- detail::visitation::variant::visit_value(
- lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...);
- }
-#else
- namespace detail {
-
- template <std::size_t N>
- inline constexpr bool all_impl(const lib::array<bool, N> &bs,
- std::size_t idx) {
- return idx >= N || (bs[idx] && all_impl(bs, idx + 1));
- }
-
- template <std::size_t N>
- inline constexpr bool all(const lib::array<bool, N> &bs) {
- return all_impl(bs, 0);
- }
-
- } // namespace detail
-
- template <typename Visitor, typename... Vs>
- inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs)
- DECLTYPE_AUTO_RETURN(
- (detail::all(
- lib::array<bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}})
- ? (void)0
- : throw_bad_variant_access()),
- detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor),
- lib::forward<Vs>(vs)...))
-#endif
-
- template <typename... Ts>
- inline auto swap(variant<Ts...> &lhs,
- variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs)))
- -> decltype(lhs.swap(rhs)) {
- lhs.swap(rhs);
- }
-
- namespace detail {
-
- template <typename T, typename...>
- using enabled_type = T;
-
- namespace hash {
-
- template <typename H, typename K>
- constexpr bool meets_requirements() {
- return std::is_copy_constructible<H>::value &&
- std::is_move_constructible<H>::value &&
- lib::is_invocable_r<std::size_t, H, const K &>::value;
- }
-
- template <typename K>
- constexpr bool is_enabled() {
- using H = std::hash<K>;
- return meets_requirements<H, K>() &&
- std::is_default_constructible<H>::value &&
- std::is_copy_assignable<H>::value &&
- std::is_move_assignable<H>::value;
- }
-
- } // namespace hash
-
- } // namespace detail
-
-#undef AUTO
-#undef AUTO_RETURN
-
-#undef AUTO_REFREF
-#undef AUTO_REFREF_RETURN
-
-#undef DECLTYPE_AUTO
-#undef DECLTYPE_AUTO_RETURN
-
-} // namespace mpark
-
-namespace std {
-
- template <typename... Ts>
- struct hash<mpark::detail::enabled_type<
- mpark::variant<Ts...>,
- mpark::lib::enable_if_t<mpark::lib::all<mpark::detail::hash::is_enabled<
- mpark::lib::remove_const_t<Ts>>()...>::value>>> {
- using argument_type = mpark::variant<Ts...>;
- using result_type = std::size_t;
-
- inline result_type operator()(const argument_type &v) const {
- using mpark::detail::visitation::variant;
- std::size_t result =
- v.valueless_by_exception()
- ? 299792458 // Random value chosen by the universe upon creation
- : variant::visit_alt(
-#ifdef MPARK_GENERIC_LAMBDAS
- [](const auto &alt) {
- using alt_type = mpark::lib::decay_t<decltype(alt)>;
- using value_type = mpark::lib::remove_const_t<
- typename alt_type::value_type>;
- return hash<value_type>{}(alt.value);
- }
-#else
- hasher{}
-#endif
- ,
- v);
- return hash_combine(result, hash<std::size_t>{}(v.index()));
- }
-
- private:
-#ifndef MPARK_GENERIC_LAMBDAS
- struct hasher {
- template <typename Alt>
- inline std::size_t operator()(const Alt &alt) const {
- using alt_type = mpark::lib::decay_t<Alt>;
- using value_type =
- mpark::lib::remove_const_t<typename alt_type::value_type>;
- return hash<value_type>{}(alt.value);
- }
- };
-#endif
-
- static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
- return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
- }
- };
-
- template <>
- struct hash<mpark::monostate> {
- using argument_type = mpark::monostate;
- using result_type = std::size_t;
-
- inline result_type operator()(const argument_type &) const noexcept {
- return 66740831; // return a fundamentally attractive random value.
- }
- };
-
-} // namespace std
-
-#if defined(__GNUC__) && __GNUC__ >= 9
-#pragma GCC diagnostic pop
-#endif
-
-#endif // MPARK_VARIANT_HPP
diff --git a/src/src.qbs b/src/src.qbs
index f5a5ae5a1..7c07e5b61 100644
--- a/src/src.qbs
+++ b/src/src.qbs
@@ -9,6 +9,6 @@ Project {
"shared/json/json.qbs",
"shared/lsp/lsp.qbs",
"shared/quickjs/quickjs.qbs",
- "shared/variant/variant.qbs",
+ "shared/span/span.qbs",
]
}
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index 3816eca2b..45463312b 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -2902,6 +2902,7 @@ void TestApi::targetArtifactStatus()
void TestApi::timeout()
{
QFETCH(QString, projectDirName);
+ QFETCH(QString, cancelOutput);
const auto setupParams = defaultSetupParameters(projectDirName + "/timeout.qbs");
std::unique_ptr<qbs::SetupProjectJob> setupJob{
qbs::Project().setupProject(setupParams, m_logSink, nullptr)};
@@ -2934,13 +2935,15 @@ void TestApi::timeout()
const auto errorString = buildJob->error().toString();
QVERIFY2(errorString.contains("cancel"), qPrintable(errorString));
QVERIFY(errorString.contains("timeout"));
+ QVERIFY(errorString.contains(cancelOutput));
}
void TestApi::timeout_data()
{
QTest::addColumn<QString>("projectDirName");
- QTest::newRow("JS Command") << QString("timeout-js");
- QTest::newRow("Process Command") << QString("timeout-process");
+ QTest::addColumn<QString>("cancelOutput");
+ QTest::newRow("JS Command") << QString("timeout-js") << QString("infinite loop");
+ QTest::newRow("Process Command") << QString("timeout-process") << QString("infinite-loop");
}
void TestApi::toolInModule()
diff --git a/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs
index 7e7427561..7336e3970 100644
--- a/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs
+++ b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs
@@ -2,7 +2,7 @@ import "../BareMetalApplication.qbs" as BareMetalApplication
import "../BareMetalStaticLibrary.qbs" as BareMetalStaticLibrary
Project {
- property string outputLibrariesDirectory: sourceDirectory + "/libs"
+ property string outputLibrariesDirectory: buildDirectory + "/libs"
BareMetalStaticLibrary {
name: "lib-a"
destinationDirectory: project.outputLibrariesDirectory
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs b/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs
new file mode 100644
index 000000000..e8880fc96
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs
@@ -0,0 +1,11 @@
+CppApplication {
+ consoleApplication: true
+ name: "p"
+ files: "main.cpp"
+ qbsModuleProviders: "conan"
+ qbs.buildVariant: "release"
+ qbs.installPrefix: ""
+ install: true
+ Depends { name: "conanmoduleprovider.testlib" }
+ Depends { name: "conanmoduleprovider.testlibheader" }
+}
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt b/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt
new file mode 100644
index 000000000..7c40ff7d6
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt
@@ -0,0 +1,3 @@
+[requires]
+conanmoduleprovider.testlib/1.2.3
+conanmoduleprovider.testlibheader/0.1.0
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp
new file mode 100644
index 000000000..6250927b3
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp
@@ -0,0 +1,8 @@
+#include <testlib.h>
+
+#include <header.h>
+
+int main()
+{
+ HelloWorld h(42 + hello());
+}
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt
new file mode 100644
index 000000000..d186d1906
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 3.15)
+project(conanmoduleprovider.testlib)
+
+find_package(conanmoduleprovider.testlibdep REQUIRED)
+
+add_library(${PROJECT_NAME} STATIC testlib.cpp)
+set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlib.h")
+target_link_libraries(${PROJECT_NAME} conanmoduleprovider.testlibdep::conanmoduleprovider.testlibdep)
+install(TARGETS ${PROJECT_NAME})
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py
new file mode 100644
index 000000000..7cb91f9ef
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py
@@ -0,0 +1,36 @@
+from conan import ConanFile
+from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
+from conan.tools.files import collect_libs
+import os
+
+class ConanModuleProviderTestlib(ConanFile):
+ name = "conanmoduleprovider.testlib"
+ license = "none"
+ version = "1.2.3"
+
+ exports_sources = "*.cpp", "*.h", "CMakeLists.txt"
+ settings = "os", "compiler", "build_type", "arch"
+
+ def requirements(self):
+ self.requires("conanmoduleprovider.testlibdep/1.2.3")
+
+ def layout(self):
+ cmake_layout(self)
+
+ def generate(self):
+ deps = CMakeDeps(self)
+ deps.generate()
+ tc = CMakeToolchain(self, generator="Ninja")
+ tc.generate()
+
+ def build(self):
+ cmake = CMake(self)
+ cmake.configure()
+ cmake.build()
+
+ def package(self):
+ cmake = CMake(self)
+ cmake.install()
+
+ def package_info(self):
+ self.cpp_info.libs = collect_libs(self)
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp
new file mode 100644
index 000000000..7118dfda9
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp
@@ -0,0 +1,7 @@
+#include "testlib.h"
+
+#include <testlibdep.h>
+
+HelloWorld::HelloWorld(int x)
+ : m_x(foo(x))
+{}
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h
new file mode 100644
index 000000000..11a354b70
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h
@@ -0,0 +1,10 @@
+#pragma once
+
+class HelloWorld
+{
+public:
+ explicit HelloWorld(int x);
+
+private:
+ int m_x;
+};
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt
new file mode 100644
index 000000000..5510a9250
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.15)
+project(conanmoduleprovider.testlibdep)
+
+add_library(${PROJECT_NAME} STATIC testlibdep.cpp)
+set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlibdep.h")
+install(TARGETS ${PROJECT_NAME})
+install(FILES lorem_ipsum.txt DESTINATION share) \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py
new file mode 100644
index 000000000..f2c577c5e
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py
@@ -0,0 +1,35 @@
+from conan import ConanFile
+from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
+from conan.tools.files import collect_libs, copy
+import os
+
+class ConanModuleProviderTestlib(ConanFile):
+ name = "conanmoduleprovider.testlibdep"
+ license = "none"
+ version = "1.2.3"
+
+ exports_sources = "*.cpp", "*.h", "*.txt"
+ settings = "os", "compiler", "build_type", "arch"
+
+ def layout(self):
+ cmake_layout(self)
+
+ def generate(self):
+ deps = CMakeDeps(self)
+ deps.generate()
+ tc = CMakeToolchain(self, generator="Ninja")
+ tc.generate()
+
+ def build(self):
+ cmake = CMake(self)
+ cmake.configure()
+ cmake.build()
+
+ def package(self):
+ cmake = CMake(self)
+ cmake.install()
+
+ def package_info(self):
+ self.cpp_info.libs = collect_libs(self)
+ self.cpp_info.resdirs = ['share']
+
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt
new file mode 100644
index 000000000..d8634396c
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp
new file mode 100644
index 000000000..893478c82
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp
@@ -0,0 +1,6 @@
+#include "testlibdep.h"
+
+int foo(int i)
+{
+ return i * i;
+} \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h
new file mode 100644
index 000000000..ca7bd3cbc
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h
@@ -0,0 +1,3 @@
+#pragma once
+
+int foo(int i); \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py
new file mode 100644
index 000000000..6078b9750
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py
@@ -0,0 +1,15 @@
+from conan import ConanFile
+from conan.tools.files import copy
+
+import os
+
+class Recipe(ConanFile):
+ exports_sources = ("header.h")
+ version = '0.1.0'
+ name = 'conanmoduleprovider.testlibheader'
+
+ def package(self):
+ copy(self,
+ "header.h",
+ src=self.source_folder,
+ dst=os.path.join(self.package_folder, "include")) \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h
new file mode 100644
index 000000000..66bd50d57
--- /dev/null
+++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h
@@ -0,0 +1,6 @@
+#pragma once
+
+inline int hello()
+{
+ return 0;
+} \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs
index 00776a62e..7767c2cc5 100644
--- a/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs
+++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs
@@ -1,10 +1,8 @@
Project {
qbsModuleProviders: "provider_a"
- property stringList wantedProviders: qbsModuleProviders
name: "project"
Project {
name: "innerProject"
- qbsModuleProviders: project.wantedProviders
Product {
name: "p1"
Depends { name: "qbsmetatestmodule" }
diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs
index 0d7c8a1bb..4674d6a6a 100644
--- a/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs
+++ b/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs
@@ -17,4 +17,5 @@ CppApplication {
"capnproto_absolute_import.cpp",
"imports/foo.capnp",
]
+ qbs.buildVariant: "release"
}
diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs
index c31824bb0..9f287e906 100644
--- a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs
+++ b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs
@@ -15,4 +15,5 @@ CppApplication {
"capnproto_cpp.cpp",
"foo.capnp"
]
+ qbs.buildVariant: "release"
}
diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp_pkgconfig.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp_pkgconfig.qbs
deleted file mode 100644
index 90201e440..000000000
--- a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp_pkgconfig.qbs
+++ /dev/null
@@ -1,19 +0,0 @@
-import qbs.Host
-
-CppApplication {
- Depends { name: "capnproto.cpp"; required: false }
- condition: {
- var result = qbs.targetPlatform === Host.platform();
- if (!result)
- console.info("targetPlatform differs from hostPlatform");
- if (!capnproto.cpp.present)
- console.info("capnproto is not present");
- return result && capnproto.cpp.present;
- }
- cpp.minimumMacosVersion: "10.8"
- files: [
- "capnproto_cpp.cpp",
- "foo.capnp"
- ]
- qbsModuleProviders: "qbspkgconfig"
-}
diff --git a/tests/auto/blackbox/testdata/capnproto/conanfile.txt b/tests/auto/blackbox/testdata/capnproto/conanfile.txt
new file mode 100644
index 000000000..7313bb82e
--- /dev/null
+++ b/tests/auto/blackbox/testdata/capnproto/conanfile.txt
@@ -0,0 +1,6 @@
+[requires]
+capnproto/1.0.2
+[tool_requires]
+capnproto/1.0.2
+[generators]
+QbsDeps
diff --git a/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs b/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs
index 7266e9e15..5fc5464b1 100644
--- a/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs
+++ b/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs
@@ -14,11 +14,14 @@ Project {
name: "server"
consoleApplication: true
cpp.minimumMacosVersion: "10.8"
+ // workaround for broken capnproto
+ cpp.staticLibraries: qbs.targetOS.contains("windows") ? "Advapi32" : []
capnproto.cpp.useRpc: true
files: [
"greeter.capnp",
"greeter-server.cpp"
]
+ qbs.buildVariant: "release"
}
CppApplication {
Depends { name: "capnproto.cpp"; required: false }
@@ -26,9 +29,11 @@ Project {
consoleApplication: true
capnproto.cpp.useRpc: true
cpp.minimumMacosVersion: "10.8"
+ cpp.staticLibraries: qbs.targetOS.contains("windows") ? "Advapi32" : []
files: [
"greeter.capnp",
"greeter-client.cpp"
]
+ qbs.buildVariant: "release"
}
}
diff --git a/tests/auto/blackbox/testdata/external-libs/external-libs.qbs b/tests/auto/blackbox/testdata/external-libs/external-libs.qbs
index 610df0507..326bf5dae 100644
--- a/tests/auto/blackbox/testdata/external-libs/external-libs.qbs
+++ b/tests/auto/blackbox/testdata/external-libs/external-libs.qbs
@@ -1,7 +1,7 @@
import qbs.TextFile
Project {
- property string libDir: sourceDirectory + "/libs"
+ property string libDir: buildDirectory + "/libs"
StaticLibrary {
name: "lib1"
destinationDirectory: project.libDir
diff --git a/tests/auto/blackbox/testdata/flatbuf/bar.fbs b/tests/auto/blackbox/testdata/flatbuf/bar.fbs
new file mode 100644
index 000000000..47148f800
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/bar.fbs
@@ -0,0 +1,9 @@
+include "foo.fbs";
+
+namespace QbsTest;
+
+table Bar {
+ foo:Foo;
+}
+
+root_type Bar;
diff --git a/tests/auto/blackbox/testdata/flatbuf/baz.fbs b/tests/auto/blackbox/testdata/flatbuf/baz.fbs
new file mode 100644
index 000000000..312183710
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/baz.fbs
@@ -0,0 +1,9 @@
+include "imported_foo/imported_foo.fbs";
+
+namespace QbsTest;
+
+table Baz {
+ foo:Foo;
+}
+
+root_type Baz;
diff --git a/tests/auto/blackbox/testdata/flatbuf/conanfile.txt b/tests/auto/blackbox/testdata/flatbuf/conanfile.txt
new file mode 100644
index 000000000..188da5897
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/conanfile.txt
@@ -0,0 +1,6 @@
+[requires]
+flatbuffers/24.3.25
+[tool_requires]
+flatbuffers/24.3.25
+[generators]
+QbsDeps
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat.c b/tests/auto/blackbox/testdata/flatbuf/flat.c
new file mode 100644
index 000000000..55e25e556
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat.c
@@ -0,0 +1,36 @@
+#include "foo_builder.h"
+
+#include <stdio.h>
+
+#undef ns
+#define ns(x) FLATBUFFERS_WRAP_NAMESPACE(QbsTest, x) // Specified in the schema.
+
+#define test_assert(x) do { if (!(x)) { assert(0); return -1; }} while (0)
+
+int main()
+{
+ void *buffer = NULL;
+ size_t size = 0;
+
+ flatcc_builder_t builder;
+ flatcc_builder_init(&builder);
+
+ flatbuffers_string_ref_t name = flatbuffers_string_create_str(&builder, "John Doe");
+
+ ns(Foo_create_as_root(&builder, name, 42));
+
+ buffer = flatcc_builder_finalize_aligned_buffer(&builder, &size);
+
+ ns(Foo_table_t) foo = ns(Foo_as_root(buffer));
+
+ test_assert(strcmp(ns(Foo_name(foo)), "John Doe") == 0);
+ test_assert(ns(Foo_count(foo)) == 42);
+
+ free(buffer);
+
+ flatcc_builder_clear(&builder);
+
+ printf("The FlatBuffer was successfully created and accessed!\n");
+
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat.cpp b/tests/auto/blackbox/testdata/flatbuf/flat.cpp
new file mode 100644
index 000000000..56332bacd
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat.cpp
@@ -0,0 +1,22 @@
+#include "foo_generated.h"
+
+#include <iostream>
+
+using namespace QbsTest;
+
+int main()
+{
+ flatbuffers::FlatBufferBuilder builder;
+ auto name = builder.CreateString("John Doe");
+ auto newFoo = QbsTest::CreateFoo(builder, name, 42);
+ builder.Finish(newFoo);
+
+ auto foo = GetFoo(builder.GetBufferPointer());
+
+ assert(foo->name()->str() == "John Doe");
+ assert(foo->count() == 42);
+
+ std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl;
+
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp
new file mode 100644
index 000000000..b7c43d8a5
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp
@@ -0,0 +1,25 @@
+#include "baz_generated.h"
+
+#include <iostream>
+
+using namespace QbsTest;
+
+int main()
+{
+ flatbuffers::FlatBufferBuilder builder;
+
+ auto name = builder.CreateString("John Doe");
+ auto newFoo = QbsTest::CreateFoo(builder, name, 42);
+
+ auto newBaz = QbsTest::CreateBaz(builder, newFoo);
+ builder.Finish(newBaz);
+
+ auto baz = GetBaz(builder.GetBufferPointer());
+
+ assert(baz->foo()->name()->str() == "John Doe");
+ assert(baz->foo()->count() == 42);
+
+ std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl;
+
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs
new file mode 100644
index 000000000..888bfd4e3
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs
@@ -0,0 +1,24 @@
+CppApplication {
+ Depends { name: "flatbuf.cpp"; required: false }
+
+ consoleApplication: true
+ condition: {
+ var result = qbs.targetPlatform === qbs.hostPlatform;
+ if (!result)
+ console.info("targetPlatform differs from hostPlatform");
+ return result && hasFlatbuffers;
+ }
+ property bool hasFlatbuffers: {
+ console.info("has flatbuffers: " + flatbuf.cpp.present);
+ return flatbuf.cpp.present;
+ }
+
+ flatbuf.cpp.importPaths: "imports/"
+
+ files: [
+ "flat_absolute_import.cpp",
+ "baz.fbs",
+ "imports/imported_foo/imported_foo.fbs",
+ ]
+ qbsModuleProviders: "conan"
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs
new file mode 100644
index 000000000..6d365252e
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs
@@ -0,0 +1,21 @@
+CppApplication {
+ Depends { name: "flatbuffers.c"; required: false }
+
+ consoleApplication: true
+ condition: {
+ var result = qbs.targetPlatform === qbs.hostPlatform;
+ if (!result)
+ console.info("targetPlatform differs from hostPlatform");
+ return result && hasFlatbuffers;
+ }
+ property bool hasFlatbuffers: {
+ console.info("has flatbuffers: " + flatbuffers.c.present);
+ return flatbuffers.c.present;
+ }
+
+ files: [
+ "flat.c",
+ "foo.fbs",
+ ]
+ qbsModuleProviders: "conan"
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs
new file mode 100644
index 000000000..99e89a5fa
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs
@@ -0,0 +1,21 @@
+CppApplication {
+ Depends { name: "flatbuf.cpp"; required: false }
+
+ consoleApplication: true
+ condition: {
+ var result = qbs.targetPlatform === qbs.hostPlatform;
+ if (!result)
+ console.info("targetPlatform differs from hostPlatform");
+ return result && hasFlatbuffers;
+ }
+ property bool hasFlatbuffers: {
+ console.info("has flatbuffers: " + flatbuf.cpp.present);
+ return flatbuf.cpp.present;
+ }
+
+ files: [
+ "flat.cpp",
+ "foo.fbs",
+ ]
+ qbsModuleProviders: "conan"
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp
new file mode 100644
index 000000000..77ed64acd
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp
@@ -0,0 +1,22 @@
+#include "foo_generated.hpp"
+
+#include <iostream>
+
+using namespace QbsTest;
+
+int main()
+{
+ flatbuffers::FlatBufferBuilder builder;
+ auto name = builder.CreateString("John Doe");
+ auto newFoo = QbsTest::CreateFoo(builder, name, 42);
+ builder.Finish(newFoo);
+
+ auto foo = GetFoo(builder.GetBufferPointer());
+
+ assert(foo->name()->str() == "John Doe");
+ assert(foo->count() == 42);
+
+ std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl;
+
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs
new file mode 100644
index 000000000..31eec7629
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs
@@ -0,0 +1,23 @@
+CppApplication {
+ Depends { name: "flatbuf.cpp"; required: false }
+
+ consoleApplication: true
+ condition: {
+ var result = qbs.targetPlatform === qbs.hostPlatform;
+ if (!result)
+ console.info("targetPlatform differs from hostPlatform");
+ return result && hasFlatbuffers;
+ }
+ property bool hasFlatbuffers: {
+ console.info("has flatbuffers: " + flatbuf.cpp.present);
+ return flatbuf.cpp.present;
+ }
+
+ flatbuf.cpp.filenameExtension: "hpp"
+
+ files: [
+ "flat_filename_extension.cpp",
+ "foo.fbs",
+ ]
+ qbsModuleProviders: "conan"
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp
new file mode 100644
index 000000000..630e4aaef
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp
@@ -0,0 +1,22 @@
+#include "foo.fbs.h"
+
+#include <iostream>
+
+using namespace QbsTest;
+
+int main()
+{
+ flatbuffers::FlatBufferBuilder builder;
+ auto name = builder.CreateString("John Doe");
+ auto newFoo = QbsTest::CreateFoo(builder, name, 42);
+ builder.Finish(newFoo);
+
+ auto foo = GetFoo(builder.GetBufferPointer());
+
+ assert(foo->name()->str() == "John Doe");
+ assert(foo->count() == 42);
+
+ std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl;
+
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs
new file mode 100644
index 000000000..5103b041f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs
@@ -0,0 +1,23 @@
+CppApplication {
+ Depends { name: "flatbuf.cpp"; required: false }
+
+ consoleApplication: true
+ condition: {
+ var result = qbs.targetPlatform === qbs.hostPlatform;
+ if (!result)
+ console.info("targetPlatform differs from hostPlatform");
+ return result && hasFlatbuffers;
+ }
+ property bool hasFlatbuffers: {
+ console.info("has flatbuffers: " + flatbuf.cpp.present);
+ return flatbuf.cpp.present;
+ }
+
+ flatbuf.cpp.filenameSuffix: ".fbs"
+
+ files: [
+ "flat_filename_suffix.cpp",
+ "foo.fbs",
+ ]
+ qbsModuleProviders: "conan"
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp
new file mode 100644
index 000000000..5f4b55e96
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp
@@ -0,0 +1,26 @@
+#include "baz_generated.h"
+#include "imported_foo/imported_foo_generated.h"
+
+#include <iostream>
+
+using namespace QbsTest;
+
+int main()
+{
+ flatbuffers::FlatBufferBuilder builder;
+
+ auto name = builder.CreateString("John Doe");
+ auto newFoo = QbsTest::CreateFoo(builder, name, 42);
+
+ auto newBaz = QbsTest::CreateBaz(builder, newFoo);
+ builder.Finish(newBaz);
+
+ auto baz = GetBaz(builder.GetBufferPointer());
+
+ assert(baz->foo()->name()->str() == "John Doe");
+ assert(baz->foo()->count() == 42);
+
+ std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl;
+
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs
new file mode 100644
index 000000000..0ea0d1dac
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs
@@ -0,0 +1,25 @@
+CppApplication {
+ Depends { name: "flatbuf.cpp"; required: false }
+
+ consoleApplication: true
+ condition: {
+ var result = qbs.targetPlatform === qbs.hostPlatform;
+ if (!result)
+ console.info("targetPlatform differs from hostPlatform");
+ return result && hasFlatbuffers;
+ }
+ property bool hasFlatbuffers: {
+ console.info("has flatbuffers: " + flatbuf.cpp.present);
+ return flatbuf.cpp.present;
+ }
+
+ flatbuf.cpp.importPaths: "imports/"
+ flatbuf.cpp.keepPrefix: true
+
+ files: [
+ "flat_keep_prefix.cpp",
+ "baz.fbs",
+ "imports/imported_foo/imported_foo.fbs",
+ ]
+ qbsModuleProviders: "conan"
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp
new file mode 100644
index 000000000..bec6dadfd
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp
@@ -0,0 +1,25 @@
+#include "bar_generated.h"
+
+#include <iostream>
+
+using namespace QbsTest;
+
+int main()
+{
+ flatbuffers::FlatBufferBuilder builder;
+
+ auto name = builder.CreateString("John Doe");
+ auto newFoo = QbsTest::CreateFoo(builder, name, 42);
+
+ auto newBar = QbsTest::CreateBar(builder, newFoo);
+ builder.Finish(newBar);
+
+ auto bar = GetBar(builder.GetBufferPointer());
+
+ assert(bar->foo()->name()->str() == "John Doe");
+ assert(bar->foo()->count() == 42);
+
+ std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl;
+
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs
new file mode 100644
index 000000000..f5a2c5d0b
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs
@@ -0,0 +1,22 @@
+CppApplication {
+ Depends { name: "flatbuf.cpp"; required: false }
+
+ consoleApplication: true
+ condition: {
+ var result = qbs.targetPlatform === qbs.hostPlatform;
+ if (!result)
+ console.info("targetPlatform differs from hostPlatform");
+ return result && hasFlatbuffers;
+ }
+ property bool hasFlatbuffers: {
+ console.info("has flatbuffers: " + flatbuf.cpp.present);
+ return flatbuf.cpp.present;
+ }
+
+ files: [
+ "flat_relative_import.cpp",
+ "bar.fbs",
+ "foo.fbs",
+ ]
+ qbsModuleProviders: "conan"
+}
diff --git a/tests/auto/blackbox/testdata/flatbuf/foo.fbs b/tests/auto/blackbox/testdata/flatbuf/foo.fbs
new file mode 100644
index 000000000..dff3b488f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/foo.fbs
@@ -0,0 +1,8 @@
+namespace QbsTest;
+
+table Foo {
+ name:string;
+ count:int;
+}
+
+root_type Foo;
diff --git a/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs b/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs
new file mode 100644
index 000000000..dff3b488f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs
@@ -0,0 +1,8 @@
+namespace QbsTest;
+
+table Foo {
+ name:string;
+ count:int;
+}
+
+root_type Foo;
diff --git a/tests/auto/blackbox/testdata/grpc/conanfile.txt b/tests/auto/blackbox/testdata/grpc/conanfile.txt
new file mode 100644
index 000000000..f88e6e8d6
--- /dev/null
+++ b/tests/auto/blackbox/testdata/grpc/conanfile.txt
@@ -0,0 +1,7 @@
+[requires]
+grpc/1.54.3
+[tool_requires]
+protobuf/3.21.12
+grpc/1.54.3
+[generators]
+QbsDeps
diff --git a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs
index e36ae47ca..d1bdd5d60 100644
--- a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs
+++ b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs
@@ -14,6 +14,7 @@ CppApplication {
cpp.cxxLanguageVersion: "c++17"
cpp.minimumMacosVersion: "10.15"
cpp.warningLevel: "none"
+ qbs.buildVariant: "release"
Depends { name: "protobuf.cpp"; required: false }
Depends { name: "grpc++"; id: grpcpp; required: false }
@@ -22,7 +23,7 @@ CppApplication {
property bool hasDependencies: {
console.info("has grpc: " + protobuf.cpp.present);
console.info("has modules: " + grpcpp.present);
- return protobuf.cpp.present;
+ return protobuf.cpp.present && grpcpp.present;
}
files: "grpc.cpp"
diff --git a/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs b/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs
new file mode 100644
index 000000000..650233d86
--- /dev/null
+++ b/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs
@@ -0,0 +1,18 @@
+Project {
+ property string artifactDir
+ Product {
+ type: "t"
+ Rule {
+ multiplex: true
+ Artifact {
+ filePath: project.artifactDir + "/file.out"
+ fileTags: "t"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.sourceCode = function() {};
+ return cmd;
+ }
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/linkerMode/darwin.s b/tests/auto/blackbox/testdata/linkerMode/darwin.s
new file mode 100644
index 000000000..fb165114b
--- /dev/null
+++ b/tests/auto/blackbox/testdata/linkerMode/darwin.s
@@ -0,0 +1,6 @@
+.globl _main
+.globl main
+
+_main:
+main:
+ ret
diff --git a/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs b/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs
index 9934efb04..176730ce0 100644
--- a/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs
+++ b/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs
@@ -2,7 +2,7 @@ Project {
CppApplication {
consoleApplication: true
name: "LinkedProduct-Assembly"
- files: ["main.s"]
+ files: qbs.targetOS.includes("darwin") ? "darwin.s" : "main.s"
cpp.linkerPath: cpp.compilerPathByLanguage["c"]
diff --git a/tests/auto/blackbox/testdata/linkerMode/main.s b/tests/auto/blackbox/testdata/linkerMode/main.s
index fb165114b..ef88f8c52 100644
--- a/tests/auto/blackbox/testdata/linkerMode/main.s
+++ b/tests/auto/blackbox/testdata/linkerMode/main.s
@@ -3,4 +3,3 @@
_main:
main:
- ret
diff --git a/tests/auto/blackbox/testdata/protobuf/conanfile.txt b/tests/auto/blackbox/testdata/protobuf/conanfile.txt
new file mode 100644
index 000000000..e7d849b1a
--- /dev/null
+++ b/tests/auto/blackbox/testdata/protobuf/conanfile.txt
@@ -0,0 +1,6 @@
+[requires]
+protobuf/3.21.12
+[tool_requires]
+protobuf/3.21.12
+[generators]
+QbsDeps
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 917d7436c..dbabfb311 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -144,6 +144,26 @@ QString TestBlackbox::findArchiver(const QString &fileName, int *status)
return binary;
}
+bool TestBlackbox::prepareAndRunConan()
+{
+ QString executable = findExecutable({"conan"});
+ if (executable.isEmpty()) {
+ qInfo() << "conan is not installed or not available in PATH.";
+ return false;
+ }
+ const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test";
+ if (!QFileInfo(profilePath).exists()) {
+ qInfo() << "conan profile is not installed, run './scripts/setup-conan-profiles.sh'";
+ return false;
+ }
+ QProcess conan;
+ QDir::setCurrent(testDataDir + "/conan-provider/testlibdep");
+ rmDirR("build");
+ QStringList arguments{"install", ".", "--profile:all=qbs-test", "--output-folder=build"};
+ conan.start(executable, arguments);
+ return waitForProcessSuccess(conan, 60000);
+}
+
bool TestBlackbox::lexYaccExist()
{
return !findExecutable(QStringList("lex")).isEmpty()
@@ -707,6 +727,45 @@ void TestBlackbox::buildDirectories()
QVERIFY2(outputLines.contains(projectDir), m_qbsStdout.constData());
}
+void TestBlackbox::buildDirPlaceholders_data()
+{
+ QTest::addColumn<QString>("buildDir");
+ QTest::addColumn<bool>("setProjectFile");
+ QTest::addColumn<bool>("successExpected");
+
+ QTest::newRow("normal dir, with project file") << "somedir" << true << true;
+ QTest::newRow("normal dir, without project file") << "somedir" << false << true;
+ QTest::newRow("@project, with project file") << "somedir/@project" << true << true;
+ QTest::newRow("@project, without project file") << "somedir/@project" << false << false;
+ QTest::newRow("@path, with project file") << "somedir/@path" << true << true;
+ QTest::newRow("@path, without project file") << "somedir/@path" << false << false;
+}
+
+void TestBlackbox::buildDirPlaceholders()
+{
+ QFETCH(QString, buildDir);
+ QFETCH(bool, setProjectFile);
+ QFETCH(bool, successExpected);
+
+ const QString projectDir = testDataDir + "/build-dir-placeholders";
+ rmDirR(projectDir);
+ QVERIFY(QDir().mkpath(projectDir));
+ QDir::setCurrent(projectDir);
+ QFile projectFile("build-dir-placeholders.qbs");
+ QVERIFY(projectFile.open(QIODevice::WriteOnly));
+ projectFile.write("Product {\n}\n");
+ projectFile.flush();
+ rmDirR(relativeBuildDir());
+ QbsRunParameters params;
+ params.buildDirectory = buildDir;
+ if (setProjectFile) {
+ params.arguments << "-f"
+ << "build-dir-placeholders.qbs";
+ }
+ params.expectFailure = !successExpected;
+ QCOMPARE(runQbs(params) == 0, successExpected);
+}
+
void TestBlackbox::buildEnvChange()
{
QDir::setCurrent(testDataDir + "/buildenv-change");
@@ -793,28 +852,45 @@ void TestBlackbox::buildVariantDefaults()
void TestBlackbox::capnproto()
{
QFETCH(QString, projectFile);
+ QFETCH(QStringList, arguments);
QDir::setCurrent(testDataDir + "/capnproto");
rmDirR(relativeBuildDir());
+ if (QTest::currentDataTag() == QLatin1String("cpp-conan")
+ || QTest::currentDataTag() == QLatin1String("rpc-conan")) {
+ if (!prepareAndRunConan())
+ QSKIP("conan is not prepared, check messages above");
+ }
+
QbsRunParameters params{QStringLiteral("resolve"), {QStringLiteral("-f"), projectFile}};
+ params.arguments << arguments;
+ QCOMPARE(runQbs(params), 0);
if (m_qbsStdout.contains("targetPlatform differs from hostPlatform"))
QSKIP("Cannot run binaries in cross-compiled build");
if (m_qbsStdout.contains("capnproto is not present"))
QSKIP("capnproto is not present");
- params.command.clear();
+ params.command = QStringLiteral("build");
QCOMPARE(runQbs(params), 0);
}
void TestBlackbox::capnproto_data()
{
QTest::addColumn<QString>("projectFile");
+ QTest::addColumn<QStringList>("arguments");
- QTest::newRow("cpp") << QStringLiteral("capnproto_cpp.qbs");
- QTest::newRow("cpp-pkgconfig") << QStringLiteral("capnproto_cpp_pkgconfig.qbs");
- QTest::newRow("greeter cpp (grpc)") << QStringLiteral("greeter_cpp.qbs");
- QTest::newRow("relative import") << QStringLiteral("capnproto_relative_import.qbs");
- QTest::newRow("absolute import") << QStringLiteral("capnproto_absolute_import.qbs");
+ QStringList pkgConfigArgs({"project.qbsModuleProviders:qbspkgconfig"});
+ QTest::newRow("cpp-pkgconfig") << QStringLiteral("capnproto_cpp.qbs") << pkgConfigArgs;
+ QTest::newRow("rpc-pkgconfig") << QStringLiteral("greeter_cpp.qbs") << pkgConfigArgs;
+ QTest::newRow("relative import")
+ << QStringLiteral("capnproto_relative_import.qbs") << pkgConfigArgs;
+ QTest::newRow("absolute import")
+ << QStringLiteral("capnproto_absolute_import.qbs") << pkgConfigArgs;
+
+ QStringList conanArgs(
+ {"project.qbsModuleProviders:conan", "moduleProviders.conan.installDirectory:build"});
+ QTest::newRow("cpp-conan") << QStringLiteral("capnproto_cpp.qbs") << conanArgs;
+ QTest::newRow("rpc-conan") << QStringLiteral("greeter_cpp.qbs") << conanArgs;
}
void TestBlackbox::changedFiles_data()
@@ -1386,19 +1462,6 @@ void TestBlackbox::variantSuffix_data()
std::make_pair(QString("unix"), QStringList())});
}
-static bool waitForProcessSuccess(QProcess &p, int msecs = 30000)
-{
- if (!p.waitForStarted(msecs) || !p.waitForFinished(msecs)) {
- qDebug() << p.errorString();
- return false;
- }
- if (p.exitCode() != 0) {
- qDebug() << p.readAllStandardError();
- return false;
- }
- return true;
-}
-
void TestBlackbox::vcsGit()
{
const QString gitFilePath = findExecutable(QStringList("git"));
@@ -1925,6 +1988,9 @@ void TestBlackbox::conanfileProbe()
{
QFETCH(bool, forceFailure);
+ if (qEnvironmentVariableIsSet("GITHUB_ACTIONS"))
+ QSKIP("Skip this test when running on GitHub");
+
QString executable = findExecutable({"conan"});
if (executable.isEmpty())
QSKIP("conan is not installed or not available in PATH.");
@@ -4343,6 +4409,43 @@ void TestBlackbox::fileTagsFilterMerging()
QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput));
}
+void TestBlackbox::flatbuf()
+{
+ QFETCH(QString, projectFile);
+
+ QDir::setCurrent(testDataDir + "/flatbuf");
+
+ rmDirR(relativeBuildDir());
+ if (!prepareAndRunConan())
+ QSKIP("conan is not prepared, check messages above");
+
+ QbsRunParameters resolveParams(
+ "resolve", QStringList{"-f", projectFile, "moduleProviders.conan.installDirectory:build"});
+ QCOMPARE(runQbs(resolveParams), 0);
+ if (m_qbsStdout.contains("targetPlatform differs from hostPlatform"))
+ QSKIP("Cannot run binaries in cross-compiled build");
+ const bool withFlatbuffers = m_qbsStdout.contains("has flatbuffers: true");
+ const bool withoutFlatbuffers = m_qbsStdout.contains("has flatbuffers: false");
+ QVERIFY2(withFlatbuffers || withoutFlatbuffers, m_qbsStdout.constData());
+ if (withoutFlatbuffers)
+ QSKIP("flatbuf module not present");
+ QbsRunParameters runParams("run");
+ QCOMPARE(runQbs(runParams), 0);
+}
+
+void TestBlackbox::flatbuf_data()
+{
+ QTest::addColumn<QString>("projectFile");
+
+ // QTest::newRow("c") << QString("flat_c.qbs");
+ QTest::newRow("cpp") << QString("flat_cpp.qbs");
+ QTest::newRow("relative import") << QString("flat_relative_import.qbs");
+ QTest::newRow("absolute import") << QString("flat_absolute_import.qbs");
+ QTest::newRow("filename suffix") << QString("flat_filename_suffix.qbs");
+ QTest::newRow("filename extension") << QString("flat_filename_extension.qbs");
+ QTest::newRow("keep prefix") << QString("flat_keep_prefix.qbs");
+}
+
void TestBlackbox::freedesktop()
{
if (!HostOsInfo::isAnyUnixHost())
@@ -4597,6 +4700,33 @@ void TestBlackbox::installTree()
QVERIFY(QFile::exists(installRoot + "content/subdir2/baz.txt"));
}
+void TestBlackbox::invalidArtifactPath_data()
+{
+ QTest::addColumn<QString>("baseDir");
+ QTest::addColumn<bool>("isValid");
+
+ QTest::newRow("inside, normal case") << "subdir" << true;
+ QTest::newRow("inside, build dir 1") << "project.buildDirectory" << true;
+ QTest::newRow("inside, build dir 2") << "subdir/.." << true;
+ QTest::newRow("outside, absolute") << "/tmp" << false;
+ QTest::newRow("outside, relative 1") << "../../" << false;
+ QTest::newRow("outside, relative 2") << "subdir/../../.." << false;
+}
+
+void TestBlackbox::invalidArtifactPath()
+{
+ QFETCH(QString, baseDir);
+ QFETCH(bool, isValid);
+
+ rmDirR(relativeBuildDir());
+ QDir::setCurrent(testDataDir + "/invalid-artifact-path");
+ QbsRunParameters params(QStringList("project.artifactDir:" + baseDir));
+ params.expectFailure = !isValid;
+ QCOMPARE(runQbs(params) == 0, isValid);
+ if (!isValid)
+ QVERIFY2(m_qbsStderr.contains("outside of build directory"), m_qbsStderr.constData());
+}
+
void TestBlackbox::invalidCommandProperty_data()
{
QTest::addColumn<QString>("errorType");
@@ -6058,12 +6188,15 @@ void TestBlackbox::protobuf_data()
QTest::addColumn<QStringList>("properties");
QTest::addColumn<bool>("hasModules");
QTest::addColumn<bool>("successExpected");
- QTest::newRow("cpp-fallback") << QString("addressbook_cpp.qbs") << QStringList() << true << true;
QTest::newRow("cpp-pkgconfig")
<< QString("addressbook_cpp.qbs")
- << QStringList({"project.qbsModuleProviders:qbspkgconfig", "--no-fallback-module-provider"})
- << true
- << true;
+ << QStringList({"project.qbsModuleProviders:qbspkgconfig"}) << true << true;
+ QTest::newRow("cpp-conan") << QString("addressbook_cpp.qbs")
+ << QStringList(
+ {"project.qbsModuleProviders:conan",
+ "qbs.buildVariant:release",
+ "moduleProviders.conan.installDirectory:build"})
+ << true << true;
QTest::newRow("objc") << QString("addressbook_objc.qbs") << QStringList() << false << true;
QTest::newRow("nanopb") << QString("addressbook_nanopb.qbs") << QStringList() << false << true;
QTest::newRow("import") << QString("import.qbs") << QStringList() << true << true;
@@ -6084,6 +6217,12 @@ void TestBlackbox::protobuf()
QFETCH(bool, hasModules);
QFETCH(bool, successExpected);
rmDirR(relativeBuildDir());
+
+ if (QTest::currentDataTag() == QLatin1String("cpp-conan")) {
+ if (!prepareAndRunConan())
+ QSKIP("conan is not prepared, check messages above");
+ }
+
QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile} << properties);
QCOMPARE(runQbs(resolveParams), 0);
if (m_qbsStdout.contains("targetPlatform differs from hostPlatform"))
@@ -7534,6 +7673,7 @@ void TestBlackbox::autotestTimeout()
{
QFETCH(QStringList, resolveParams);
QFETCH(bool, expectFailure);
+ QFETCH(QString, errorDetails);
QDir::setCurrent(testDataDir + "/autotest-timeout");
QbsRunParameters resolveParameters("resolve", resolveParams);
QCOMPARE(runQbs(resolveParameters), 0);
@@ -7543,7 +7683,9 @@ void TestBlackbox::autotestTimeout()
buildParameters.expectFailure = expectFailure;
if (expectFailure) {
QVERIFY(runQbs(buildParameters) != 0);
- QVERIFY(m_qbsStderr.contains("cancelled") && m_qbsStderr.contains("timeout"));
+ QVERIFY(
+ m_qbsStderr.contains("cancelled") && m_qbsStderr.contains("timeout")
+ && m_qbsStderr.contains(errorDetails.toLocal8Bit()));
}
else
QVERIFY(runQbs(buildParameters) == 0);
@@ -7553,11 +7695,12 @@ void TestBlackbox::autotestTimeout_data()
{
QTest::addColumn<QStringList>("resolveParams");
QTest::addColumn<bool>("expectFailure");
- QTest::newRow("no timeout") << QStringList() << false;
- QTest::newRow("timeout on test") << QStringList({"products.testApp.autotest.timeout:2"})
- << true;
- QTest::newRow("timeout on runner") << QStringList({"products.autotest-runner.timeout:2"})
- << true;
+ QTest::addColumn<QString>("errorDetails");
+ QTest::newRow("no timeout") << QStringList() << false << QString();
+ QTest::newRow("timeout on test")
+ << QStringList({"products.testApp.autotest.timeout:2"}) << true << QString("testApp");
+ QTest::newRow("timeout on runner")
+ << QStringList({"products.autotest-runner.timeout:2"}) << true << QString("testApp");
}
void TestBlackbox::autotests_data()
@@ -8632,16 +8775,16 @@ void TestBlackbox::grpc_data()
QTest::addColumn<QStringList>("arguments");
QTest::addColumn<bool>("hasModules");
- QTest::newRow("cpp-fallback") << QString("grpc_cpp.qbs") << QStringList() << true;
-
- QStringList pkgConfigArgs({
- "project.qbsModuleProviders:qbspkgconfig", "--no-fallback-module-provider"});
+ QStringList pkgConfigArgs({"project.qbsModuleProviders:qbspkgconfig"});
// on macOS, openSSL is hidden from pkg-config by default
if (qbs::Internal::HostOsInfo::isMacosHost()) {
pkgConfigArgs
<< "moduleProviders.qbspkgconfig.extraPaths:/usr/local/opt/openssl@1.1/lib/pkgconfig";
}
QTest::newRow("cpp-pkgconfig") << QString("grpc_cpp.qbs") << pkgConfigArgs << true;
+ QStringList conanArgs(
+ {"project.qbsModuleProviders:conan", "moduleProviders.conan.installDirectory:build"});
+ QTest::newRow("cpp-conan") << QString("grpc_cpp.qbs") << conanArgs << true;
}
void TestBlackbox::grpc()
@@ -8652,14 +8795,12 @@ void TestBlackbox::grpc()
QFETCH(bool, hasModules);
rmDirR(relativeBuildDir());
- QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile});
- if (QTest::currentDataTag() == QLatin1String("cpp")) {
- if (const QString extraLibs = qEnvironmentVariable("QBS_EXTRA_GRPC_LIBS");
- !extraLibs.isEmpty()) {
- resolveParams.arguments << (QLatin1String("modules.protobuf.cpp._extraGrpcLibs:")
- + extraLibs);
- }
+ if (QTest::currentDataTag() == QLatin1String("cpp-conan")) {
+ if (!prepareAndRunConan())
+ QSKIP("conan is not prepared, check messages above");
}
+
+ QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile});
resolveParams.arguments << arguments;
QCOMPARE(runQbs(resolveParams), 0);
const bool withGrpc = m_qbsStdout.contains("has grpc: true");
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index 5ba53ef52..3f817b481 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -60,6 +60,8 @@ private slots:
void bomSources();
void buildDataOfDisabledProduct();
void buildDirectories();
+ void buildDirPlaceholders_data();
+ void buildDirPlaceholders();
void buildEnvChange();
void buildGraphVersions();
void buildVariantDefaults_data();
@@ -133,6 +135,8 @@ private slots:
void externalLibs();
void fileDependencies();
void fileTagsFilterMerging();
+ void flatbuf();
+ void flatbuf_data();
void freedesktop();
void generatedArtifactAsInputToDynamicRule();
void generateLinkerMapFile();
@@ -165,6 +169,8 @@ private slots:
void installPackage();
void installRootFromProjectFile();
void installTree();
+ void invalidArtifactPath_data();
+ void invalidArtifactPath();
void invalidCommandProperty_data();
void invalidCommandProperty();
void invalidExtensionInstantiation();
@@ -359,6 +365,7 @@ private:
QMap<QString, QString> findNodejs(int *status);
QMap<QString, QString> findTypeScript(int *status);
QString findArchiver(const QString &fileName, int *status = nullptr);
+ bool prepareAndRunConan();
static bool lexYaccExist();
static qbs::Version bisonVersion();
};
diff --git a/tests/auto/blackbox/tst_blackboxbase.cpp b/tests/auto/blackbox/tst_blackboxbase.cpp
index 17652e779..317a6b663 100644
--- a/tests/auto/blackbox/tst_blackboxbase.cpp
+++ b/tests/auto/blackbox/tst_blackboxbase.cpp
@@ -274,3 +274,16 @@ qbs::Version TestBlackboxBase::qmakeVersion(const QString &qmakeFilePath)
qDebug() << "qmake '" << qmakeFilePath << "' version is not valid.";
return version;
}
+
+bool waitForProcessSuccess(QProcess &p, int msecs)
+{
+ if (!p.waitForStarted(msecs) || !p.waitForFinished(msecs)) {
+ qDebug() << p.errorString();
+ return false;
+ }
+ if (p.exitCode() != 0) {
+ qDebug() << p.readAllStandardError();
+ return false;
+ }
+ return true;
+}
diff --git a/tests/auto/blackbox/tst_blackboxbase.h b/tests/auto/blackbox/tst_blackboxbase.h
index d020b7cd9..5733cacd7 100644
--- a/tests/auto/blackbox/tst_blackboxbase.h
+++ b/tests/auto/blackbox/tst_blackboxbase.h
@@ -90,6 +90,8 @@ public:
public slots:
virtual void initTestCase();
+ static QString findExecutable(const QStringList &fileNames);
+
protected:
virtual void validateTestProfile();
@@ -99,7 +101,6 @@ protected:
static QByteArray unifiedLineEndings(const QByteArray &ba);
static void sanitizeOutput(QByteArray *ba);
static void ccp(const QString &sourceDirPath, const QString &targetDirPath);
- static QString findExecutable(const QStringList &fileNames);
QMap<QString, QString> findJdkTools(int *status);
static qbs::Version qmakeVersion(const QString &qmakeFilePath);
@@ -113,4 +114,6 @@ protected:
int m_needsQt = false;
};
+bool waitForProcessSuccess(QProcess &p, int msecs = 30000);
+
#endif // TST_BLACKBOXBASE_H
diff --git a/tests/auto/blackbox/tst_blackboxexamples.cpp b/tests/auto/blackbox/tst_blackboxexamples.cpp
index b6a26b7f3..13ccb7796 100644
--- a/tests/auto/blackbox/tst_blackboxexamples.cpp
+++ b/tests/auto/blackbox/tst_blackboxexamples.cpp
@@ -82,6 +82,7 @@ void TestBlackboxExamples::examples_data()
auto examples = collectExamples(testDataDir);
examples.append(collectExamples(testDataDir + "/protobuf"));
+ examples.append(collectExamples(testDataDir + "/flatbuffers"));
std::sort(examples.begin(), examples.end());
for (const auto &example: examples) {
diff --git a/tests/auto/blackbox/tst_blackboxproviders.cpp b/tests/auto/blackbox/tst_blackboxproviders.cpp
index 3642ded03..cf6594229 100644
--- a/tests/auto/blackbox/tst_blackboxproviders.cpp
+++ b/tests/auto/blackbox/tst_blackboxproviders.cpp
@@ -87,60 +87,72 @@ void TestBlackboxProviders::brokenProvider()
QCOMPARE(m_qbsStderr.count("This provider is broken"), 2);
}
-void TestBlackboxProviders::fallbackModuleProvider_data()
+void TestBlackboxProviders::conanProvider()
{
- QTest::addColumn<bool>("fallbacksEnabledGlobally");
- QTest::addColumn<bool>("fallbacksEnabledInProduct");
- QTest::addColumn<QStringList>("pkgConfigLibDirs");
- QTest::addColumn<bool>("successExpected");
- QTest::newRow("without custom lib dir, fallbacks disabled globally and in product")
- << false << false << QStringList() << false;
- QTest::newRow("without custom lib dir, fallbacks disabled globally, enabled in product")
- << false << true << QStringList() << false;
- QTest::newRow("without custom lib dir, fallbacks enabled globally, disabled in product")
- << true << false << QStringList() << false;
- QTest::newRow("without custom lib dir, fallbacks enabled globally and in product")
- << true << true << QStringList() << false;
- QTest::newRow("with custom lib dir, fallbacks disabled globally and in product")
- << false << false << QStringList(testDataDir + "/fallback-module-provider/libdir")
- << false;
- QTest::newRow("with custom lib dir, fallbacks disabled globally, enabled in product")
- << false << true << QStringList(testDataDir + "/fallback-module-provider/libdir")
- << false;
- QTest::newRow("with custom lib dir, fallbacks enabled globally, disabled in product")
- << true << false << QStringList(testDataDir + "/fallback-module-provider/libdir")
- << false;
- QTest::newRow("with custom lib dir, fallbacks enabled globally and in product")
- << true << true << QStringList(testDataDir + "/fallback-module-provider/libdir")
- << true;
-}
-
-void TestBlackboxProviders::fallbackModuleProvider()
-{
- QFETCH(bool, fallbacksEnabledInProduct);
- QFETCH(bool, fallbacksEnabledGlobally);
- QFETCH(QStringList, pkgConfigLibDirs);
+ QFETCH(bool, generateConanFiles);
QFETCH(bool, successExpected);
- QDir::setCurrent(testDataDir + "/fallback-module-provider");
- static const auto b2s = [](bool b) { return QString(b ? "true" : "false"); };
- QbsRunParameters resolveParams("resolve",
- QStringList{"modules.pkgconfig.libDirs:" + pkgConfigLibDirs.join(','),
- "products.p.fallbacksEnabled:" + b2s(fallbacksEnabledInProduct),
- "--force-probe-execution"});
- if (!fallbacksEnabledGlobally)
- resolveParams.arguments << "--no-fallback-module-provider";
- QCOMPARE(runQbs(resolveParams), 0);
- const bool pkgConfigPresent = m_qbsStdout.contains("pkg-config present: true");
- const bool pkgConfigNotPresent = m_qbsStdout.contains("pkg-config present: false");
- QVERIFY(pkgConfigPresent != pkgConfigNotPresent);
- if (pkgConfigNotPresent)
- successExpected = false;
- QbsRunParameters buildParams;
+ const auto executable = findExecutable({"conan"});
+ if (executable.isEmpty())
+ QSKIP("conan is not installed or not available in PATH.");
+
+ const auto generator = QDir::homePath() + "/.conan2/extensions/generators/qbsdeps.py";
+ if (!QFileInfo(generator).exists()) {
+ QSKIP(
+ "qbsdeps.py is not installed, call 'conan config install src/conan/ from qbs source'.");
+ }
+
+ const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test";
+ if (!QFileInfo(profilePath).exists())
+ QSKIP("conan profile is not installed, run './scripts/setup-conan-profiles.sh'.");
+
+ // install testlibdep first
+ QProcess conan;
+ QDir::setCurrent(testDataDir + "/conan-provider/testlibdep");
+ conan.start(executable, {"create", ".", "--profile:all=qbs-test"});
+ QVERIFY(waitForProcessSuccess(conan));
+
+ // install testlib second
+ QDir::setCurrent(testDataDir + "/conan-provider/testlib");
+ conan.start(executable, {"create", ".", "--profile:all=qbs-test"});
+ QVERIFY(waitForProcessSuccess(conan));
+
+ // install header lib third
+ QDir::setCurrent(testDataDir + "/conan-provider/testlibheader");
+ conan.start(executable, {"create", ".", "--profile:all=qbs-test"});
+ QVERIFY(waitForProcessSuccess(conan));
+
+ // now build an app using those libs
+ QDir::setCurrent(testDataDir + "/conan-provider");
+
+ rmDirR(relativeBuildDir());
+ rmDirR("build");
+
+ if (generateConanFiles) {
+ QStringList arguments{
+ "install", ".", "-g=QbsDeps", "--profile:all=qbs-test", "--output-folder=build"};
+ QProcess conan;
+ conan.start(executable, arguments);
+ QVERIFY(waitForProcessSuccess(conan));
+ }
+
+ QbsRunParameters buildParams(
+ "build",
+ {"--force-probe-execution",
+ "moduleProviders.conan.installDirectory:" + QDir::currentPath() + "/build"});
buildParams.expectFailure = !successExpected;
QCOMPARE(runQbs(buildParams) == 0, successExpected);
}
+void TestBlackboxProviders::conanProvider_data()
+{
+ QTest::addColumn<bool>("generateConanFiles");
+ QTest::addColumn<bool>("successExpected");
+
+ QTest::addRow("no conan files generated") << false << false;
+ QTest::addRow("conan files generated") << true << true;
+}
+
void TestBlackboxProviders::moduleProviders()
{
QDir::setCurrent(testDataDir + "/module-providers");
diff --git a/tests/auto/blackbox/tst_blackboxproviders.h b/tests/auto/blackbox/tst_blackboxproviders.h
index e8477de51..088cea6a3 100644
--- a/tests/auto/blackbox/tst_blackboxproviders.h
+++ b/tests/auto/blackbox/tst_blackboxproviders.h
@@ -44,8 +44,8 @@ private slots:
void allowedValues();
void allowedValues_data();
void brokenProvider();
- void fallbackModuleProvider_data();
- void fallbackModuleProvider();
+ void conanProvider();
+ void conanProvider_data();
void moduleProviders();
void moduleProvidersCache();
void nonEagerModuleProvider();
diff --git a/tests/auto/language/testdata/erroneous/module-with-id.qbs b/tests/auto/language/testdata/erroneous/module-with-id.qbs
new file mode 100644
index 000000000..5b980100f
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/module-with-id.qbs
@@ -0,0 +1,4 @@
+Product {
+ name: "p"
+ Depends { name: "module-with-id" }
+}
diff --git a/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs
new file mode 100644
index 000000000..d20b96784
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs
@@ -0,0 +1 @@
+ModuleWithIdParent { id: foo }
diff --git a/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs
new file mode 100644
index 000000000..5e45122de
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs
@@ -0,0 +1 @@
+Module {}
diff --git a/tests/auto/language/testdata/erroneous/modules/recursion_helper/recursion_helper.qbs b/tests/auto/language/testdata/erroneous/modules/recursion_helper/recursion_helper.qbs
new file mode 100644
index 000000000..22436a4aa
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/modules/recursion_helper/recursion_helper.qbs
@@ -0,0 +1,3 @@
+Module {
+ property bool a: product.a
+}
diff --git a/tests/auto/language/testdata/erroneous/recursive-property-direct.qbs b/tests/auto/language/testdata/erroneous/recursive-property-direct.qbs
new file mode 100644
index 000000000..ad14e7618
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/recursive-property-direct.qbs
@@ -0,0 +1,3 @@
+Product {
+ property bool a: a
+}
diff --git a/tests/auto/language/testdata/erroneous/recursive-property-indirect-via-module.qbs b/tests/auto/language/testdata/erroneous/recursive-property-indirect-via-module.qbs
new file mode 100644
index 000000000..fc3ed4f88
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/recursive-property-indirect-via-module.qbs
@@ -0,0 +1,4 @@
+Product {
+ Depends { name: "recursion_helper" }
+ property bool a: recursion_helper.a
+}
diff --git a/tests/auto/language/testdata/erroneous/recursive-property-indirect.qbs b/tests/auto/language/testdata/erroneous/recursive-property-indirect.qbs
new file mode 100644
index 000000000..6fd76e1ae
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/recursive-property-indirect.qbs
@@ -0,0 +1,5 @@
+Product {
+ property bool a: b
+ property bool b: c
+ property bool c: a
+}
diff --git a/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs b/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs
index 746c7e37b..2764af9c2 100644
--- a/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs
+++ b/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs
@@ -1,11 +1,10 @@
Module {
- id: qtcore
property int versionMajor: 5
property int versionMinor: 0
property int versionPatch: 0
property string version: versionMajor.toString() + "." + versionMinor.toString() + "." + versionPatch.toString()
property string coreProperty: "coreProperty"
- property string coreVersion: qtcore.version
+ property string coreVersion: version
property string zort: "zort in dummyqt.core"
Depends { name: "dummy" }
diff --git a/tests/auto/language/tst_language.cpp b/tests/auto/language/tst_language.cpp
index 456e8b9d0..1a3794148 100644
--- a/tests/auto/language/tst_language.cpp
+++ b/tests/auto/language/tst_language.cpp
@@ -1017,6 +1017,10 @@ void TestLanguage::erroneousFiles_data()
QTest::newRow("frozen-object-list") << "object is not extensible";
QTest::newRow("module-property-binding-in-project")
<< "Module properties cannot be set in Project items";
+ QTest::newRow("module-with-id") << "Module items cannot have an id property";
+ QTest::newRow("recursive-property-direct") << "refers to itself";
+ QTest::newRow("recursive-property-indirect") << "refers to itself.*via 'b'.*via 'c'";
+ QTest::newRow("recursive-property-indirect-via-module") << "refers to itself.*via 'a'";
}
void TestLanguage::erroneousFiles()
diff --git a/tests/auto/tools/tst_tools.cpp b/tests/auto/tools/tst_tools.cpp
index a872bdd0d..ab65f4f6b 100644
--- a/tests/auto/tools/tst_tools.cpp
+++ b/tests/auto/tools/tst_tools.cpp
@@ -53,6 +53,7 @@
#include <tools/set.h>
#include <tools/settings.h>
#include <tools/setupprojectparameters.h>
+#include <tools/span.h>
#include <tools/stringutils.h>
#include <tools/version.h>
@@ -1207,87 +1208,6 @@ void TestTools::stringutils_join_char_data()
<< std::string("a b c");
}
-void TestTools::stringutils_startsWith()
-{
- std::string a;
- a = "AB";
- QVERIFY( startsWith(a, "A") );
- QVERIFY( startsWith(a, "AB") );
- QVERIFY( !startsWith(a, "C") );
- QVERIFY( !startsWith(a, "ABCDEF") );
- QVERIFY( startsWith(a, "") );
- QVERIFY( startsWith(a, 'A') );
- QVERIFY( !startsWith(a, 'C') );
- QVERIFY( !startsWith(a, char()) );
-
- QVERIFY( startsWith(a, "A") );
- QVERIFY( startsWith(a, "AB") );
- QVERIFY( !startsWith(a, "C") );
- QVERIFY( !startsWith(a, "ABCDEF") );
- QVERIFY( startsWith(a, "") );
-
- a = "";
- QVERIFY( startsWith(a, "") );
- QVERIFY( !startsWith(a, "ABC") );
-
- QVERIFY( startsWith(a, "") );
- QVERIFY( !startsWith(a, "ABC") );
-
- QVERIFY( !startsWith(a, 'x') );
- QVERIFY( !startsWith(a, char()) );
-
- a = std::string();
- QVERIFY( startsWith(a, "") ); // different from QString::startsWith
- QVERIFY( !startsWith(a, "ABC") );
-
- QVERIFY( !startsWith(a, 'x') );
- QVERIFY( !startsWith(a, char()) );
-
- a = u8"\xc3\xa9";
- QVERIFY( startsWith(a, u8"\xc3\xa9") );
- QVERIFY( !startsWith(a, u8"\xc3\xa1") );
-}
-
-void TestTools::stringutils_endsWith()
-{
- std::string a;
- a = "AB";
- QVERIFY( endsWith(a, "B") );
- QVERIFY( endsWith(a, "AB") );
- QVERIFY( !endsWith(a, "C") );
- QVERIFY( !endsWith(a, "ABCDEF") );
- QVERIFY( endsWith(a, "") );
- QVERIFY( endsWith(a, 'B') );
- QVERIFY( !endsWith(a, 'C') );
- QVERIFY( !endsWith(a, char()) );
-
- QVERIFY( endsWith(a, "B") );
- QVERIFY( endsWith(a, "AB") );
- QVERIFY( !endsWith(a, "C") );
- QVERIFY( !endsWith(a, "ABCDEF") );
- QVERIFY( endsWith(a, "") );
-
- a = "";
- QVERIFY( endsWith(a, "") );
- QVERIFY( !endsWith(a, "ABC") );
- QVERIFY( !endsWith(a, 'x') );
- QVERIFY( !endsWith(a, char()) );
-
- QVERIFY( endsWith(a, "") );
- QVERIFY( !endsWith(a, "ABC") );
-
- a = std::string();
- QVERIFY( endsWith(a, "") ); // different from QString::endsWith
- QVERIFY( !endsWith(a, "ABC") );
-
- QVERIFY( !endsWith(a, 'x') );
- QVERIFY( !endsWith(a, char()) );
-
- a = u8"\xc3\xa9";
- QVERIFY( endsWith(a, u8"\xc3\xa9") );
- QVERIFY( !endsWith(a, u8"\xc3\xa1") );
-}
-
void TestTools::stringutils_trimmed()
{
std::string a;
@@ -1343,6 +1263,12 @@ void TestTools::hash_range()
QCOMPARE(map[key2], 2);
}
+void TestTools::span()
+{
+ std::vector<int> vec;
+ qbs::Internal::span<int> span(vec);
+}
+
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
diff --git a/tests/auto/tools/tst_tools.h b/tests/auto/tools/tst_tools.h
index 619174976..dd27977da 100644
--- a/tests/auto/tools/tst_tools.h
+++ b/tests/auto/tools/tst_tools.h
@@ -96,13 +96,13 @@ private slots:
void stringutils_join_empty();
void stringutils_join_char();
void stringutils_join_char_data();
- void stringutils_startsWith();
- void stringutils_endsWith();
void stringutils_trimmed();
void hash_tuple();
void hash_range();
+ void span();
+
private:
QString setupSettingsDir1();
QString setupSettingsDir2();
diff --git a/tests/benchmarker/benchmarker-main.cpp b/tests/benchmarker/benchmarker-main.cpp
index 2aa379372..4dfe053cc 100644
--- a/tests/benchmarker/benchmarker-main.cpp
+++ b/tests/benchmarker/benchmarker-main.cpp
@@ -41,7 +41,7 @@ static bool hasRegression = false;
static int relativeChange(qint64 oldVal, qint64 newVal)
{
- return newVal == 0 ? 0 : newVal * 100 / oldVal - 100;
+ return newVal == 0 ? 0 : (newVal - oldVal) * 100 / oldVal;
}
static QByteArray relativeChangeString(int change)
diff --git a/tutorial/LICENSE b/tutorial/LICENSE
new file mode 100644
index 000000000..d7cbbf160
--- /dev/null
+++ b/tutorial/LICENSE
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** Files in this directory are part of the Qbs tutorial.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use these files in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this these files under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/ \ No newline at end of file
diff --git a/tutorial/chapter-5/app/app.qbs b/tutorial/chapter-5/app/app.qbs
index 8625592f4..84c2430e4 100644
--- a/tutorial/chapter-5/app/app.qbs
+++ b/tutorial/chapter-5/app/app.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
MyApplication {
Depends { name: "mylib" }
name: "My Application"
diff --git a/tutorial/chapter-5/app/main.c b/tutorial/chapter-5/app/main.c
index b6e6d2fd6..a560d1ba1 100644
--- a/tutorial/chapter-5/app/main.c
+++ b/tutorial/chapter-5/app/main.c
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
#include <stdio.h>
#include "lib.h"
diff --git a/tutorial/chapter-6/app/app.qbs b/tutorial/chapter-6/app/app.qbs
index 8625592f4..84c2430e4 100644
--- a/tutorial/chapter-6/app/app.qbs
+++ b/tutorial/chapter-6/app/app.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
MyApplication {
Depends { name: "mylib" }
name: "My Application"
diff --git a/tutorial/chapter-6/app/main.c b/tutorial/chapter-6/app/main.c
index b6e6d2fd6..a560d1ba1 100644
--- a/tutorial/chapter-6/app/main.c
+++ b/tutorial/chapter-6/app/main.c
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
#include <stdio.h>
#include "lib.h"
diff --git a/tutorial/chapter-6/test/test.qbs b/tutorial/chapter-6/test/test.qbs
index 22cfbcc7d..1e911da47 100644
--- a/tutorial/chapter-6/test/test.qbs
+++ b/tutorial/chapter-6/test/test.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
MyAutoTest {
Depends { name: "mylib" }
name: "mytest"
diff --git a/tutorial/chapter-7/app/main.c b/tutorial/chapter-7/app/main.c
index b6e6d2fd6..a560d1ba1 100644
--- a/tutorial/chapter-7/app/main.c
+++ b/tutorial/chapter-7/app/main.c
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
#include <stdio.h>
#include "lib.h"
diff --git a/tutorial/chapter-7/qbs/imports/MyAutoTest.qbs b/tutorial/chapter-7/qbs/imports/MyAutoTest.qbs
index fe06e4b6a..1faecdc33 100644
--- a/tutorial/chapter-7/qbs/imports/MyAutoTest.qbs
+++ b/tutorial/chapter-7/qbs/imports/MyAutoTest.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
MyApplication {
type: ["application", "autotest"]
}
diff --git a/tutorial/chapter-7/test/test.qbs b/tutorial/chapter-7/test/test.qbs
index 22cfbcc7d..1e911da47 100644
--- a/tutorial/chapter-7/test/test.qbs
+++ b/tutorial/chapter-7/test/test.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
MyAutoTest {
Depends { name: "mylib" }
name: "mytest"
diff --git a/tutorial/chapter-8/app/app.qbs b/tutorial/chapter-8/app/app.qbs
index 8625592f4..84c2430e4 100644
--- a/tutorial/chapter-8/app/app.qbs
+++ b/tutorial/chapter-8/app/app.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
MyApplication {
Depends { name: "mylib" }
name: "My Application"
diff --git a/tutorial/chapter-8/app/main.c b/tutorial/chapter-8/app/main.c
index b6e6d2fd6..a560d1ba1 100644
--- a/tutorial/chapter-8/app/main.c
+++ b/tutorial/chapter-8/app/main.c
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
#include <stdio.h>
#include "lib.h"
diff --git a/tutorial/chapter-8/qbs/imports/MyApplication.qbs b/tutorial/chapter-8/qbs/imports/MyApplication.qbs
index 944a7236d..11b3bfb54 100644
--- a/tutorial/chapter-8/qbs/imports/MyApplication.qbs
+++ b/tutorial/chapter-8/qbs/imports/MyApplication.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
CppApplication {
Depends { name: "mybuildconfig" }
version: "1.0.0"
diff --git a/tutorial/chapter-8/qbs/imports/MyAutoTest.qbs b/tutorial/chapter-8/qbs/imports/MyAutoTest.qbs
index fe06e4b6a..1faecdc33 100644
--- a/tutorial/chapter-8/qbs/imports/MyAutoTest.qbs
+++ b/tutorial/chapter-8/qbs/imports/MyAutoTest.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
MyApplication {
type: ["application", "autotest"]
}
diff --git a/tutorial/chapter-8/test/test.qbs b/tutorial/chapter-8/test/test.qbs
index 22cfbcc7d..1e911da47 100644
--- a/tutorial/chapter-8/test/test.qbs
+++ b/tutorial/chapter-8/test/test.qbs
@@ -1,53 +1,3 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of Qbs.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
MyAutoTest {
Depends { name: "mylib" }
name: "mytest"
diff --git a/tutorial/chapter-9/app/app.qbs b/tutorial/chapter-9/app/app.qbs
new file mode 100644
index 000000000..837b66da3
--- /dev/null
+++ b/tutorial/chapter-9/app/app.qbs
@@ -0,0 +1,9 @@
+//! [0]
+MyApplication {
+ Depends { name: "mylib" }
+ Depends { name: "version_header" }
+ name: "My Application"
+ targetName: "myapp"
+ files: "main.c"
+}
+//! [0]
diff --git a/tutorial/chapter-9/app/main.c b/tutorial/chapter-9/app/main.c
new file mode 100644
index 000000000..d6cefc2ff
--- /dev/null
+++ b/tutorial/chapter-9/app/main.c
@@ -0,0 +1,14 @@
+//![0]
+#include <lib.h>
+#include <version.h>
+
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello, world\n");
+ printf("%s\n", get_string());
+ printf("ProductVersion = %s\n", kProductVersion);
+ return 0;
+}
+//![0]
diff --git a/tutorial/chapter-9/lib/lib.c b/tutorial/chapter-9/lib/lib.c
new file mode 100644
index 000000000..5dcae0de3
--- /dev/null
+++ b/tutorial/chapter-9/lib/lib.c
@@ -0,0 +1,10 @@
+#include "lib.h"
+
+#ifndef CRUCIAL_DEFINE
+# error CRUCIAL_DEFINE not defined
+#endif
+
+const char *get_string()
+{
+ return "Hello from library";
+}
diff --git a/tutorial/chapter-9/lib/lib.h b/tutorial/chapter-9/lib/lib.h
new file mode 100644
index 000000000..ef39ca4a1
--- /dev/null
+++ b/tutorial/chapter-9/lib/lib.h
@@ -0,0 +1,8 @@
+#ifndef LIB_H
+#define LIB_H
+
+#include "lib_global.h"
+
+MYLIB_EXPORT const char *get_string();
+
+#endif // LIB_H
diff --git a/tutorial/chapter-9/lib/lib.qbs b/tutorial/chapter-9/lib/lib.qbs
new file mode 100644
index 000000000..e8cf9bdb9
--- /dev/null
+++ b/tutorial/chapter-9/lib/lib.qbs
@@ -0,0 +1,10 @@
+MyLibrary {
+ name: "mylib"
+ files: [
+ "lib.c",
+ "lib.h",
+ ]
+ Depends { name: 'cpp' }
+ cpp.defines: ['CRUCIAL_DEFINE']
+}
+
diff --git a/tutorial/chapter-9/lib/lib_global.h b/tutorial/chapter-9/lib/lib_global.h
new file mode 100644
index 000000000..329b62fd3
--- /dev/null
+++ b/tutorial/chapter-9/lib/lib_global.h
@@ -0,0 +1,25 @@
+#ifndef LIB_GLOBAL_H
+#define LIB_GLOBAL_H
+
+#if defined(_WIN32) || defined(WIN32)
+#define MY_LIB_DECL_EXPORT __declspec(dllexport)
+#define MY_LIB_DECL_IMPORT __declspec(dllimport)
+#else
+#define MY_LIB_DECL_EXPORT __attribute__((visibility("default")))
+#define MY_LIB_DECL_IMPORT __attribute__((visibility("default")))
+#endif
+
+// ![0]
+// lib/lib_global.h
+#if defined(MYLIB_STATIC_LIBRARY)
+#define MYLIB_EXPORT
+#else
+#if defined(MYLIB_LIBRARY)
+#define MYLIB_EXPORT MY_LIB_DECL_EXPORT
+#else
+#define MYLIB_EXPORT MY_LIB_DECL_IMPORT
+#endif
+#endif
+// ![0]
+
+#endif // LIB_GLOBAL_H
diff --git a/tutorial/chapter-9/myproject.qbs b/tutorial/chapter-9/myproject.qbs
new file mode 100644
index 000000000..fac217b71
--- /dev/null
+++ b/tutorial/chapter-9/myproject.qbs
@@ -0,0 +1,32 @@
+Project {
+ property string version: "1.0.0"
+ property bool withTests: true
+ property bool installDebugInformation: true
+ property stringList autotestArguments: []
+ property stringList autotestWrapper: []
+
+ name: "My Project"
+ minimumQbsVersion: "2.0"
+ //! [0]
+ // myproject.qbs
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs",
+ "version-header/version-header.qbs",
+ ]
+ //! [0]
+ qbsSearchPaths: "qbs"
+
+ SubProject {
+ filePath: "test/test.qbs"
+ Properties {
+ condition: parent.withTests
+ }
+ }
+
+ AutotestRunner {
+ condition: parent.withTests
+ arguments: parent.autotestArguments
+ wrapper: parent.autotestWrapper
+ }
+}
diff --git a/tutorial/chapter-9/qbs/imports/MyApplication.qbs b/tutorial/chapter-9/qbs/imports/MyApplication.qbs
new file mode 100644
index 000000000..451065190
--- /dev/null
+++ b/tutorial/chapter-9/qbs/imports/MyApplication.qbs
@@ -0,0 +1,10 @@
+CppApplication {
+ Depends { name: "mybuildconfig" }
+ version: mybuildconfig.productVersion
+
+ cpp.rpaths: mybuildconfig.libRPaths
+ consoleApplication: true
+ installDir: mybuildconfig.appInstallDir
+ install: true
+ installDebugInformation: project.installDebugInformation
+}
diff --git a/tutorial/chapter-9/qbs/imports/MyAutoTest.qbs b/tutorial/chapter-9/qbs/imports/MyAutoTest.qbs
new file mode 100644
index 000000000..1faecdc33
--- /dev/null
+++ b/tutorial/chapter-9/qbs/imports/MyAutoTest.qbs
@@ -0,0 +1,3 @@
+MyApplication {
+ type: ["application", "autotest"]
+}
diff --git a/tutorial/chapter-9/qbs/imports/MyLibrary.qbs b/tutorial/chapter-9/qbs/imports/MyLibrary.qbs
new file mode 100644
index 000000000..9f2590f50
--- /dev/null
+++ b/tutorial/chapter-9/qbs/imports/MyLibrary.qbs
@@ -0,0 +1,26 @@
+// ![0]
+Library {
+ Depends { name: "cpp" }
+ Depends { name: "mybuildconfig" }
+ type: mybuildconfig.staticBuild ? "staticlibrary" : "dynamiclibrary"
+ version: mybuildconfig.productVersion
+ install: !mybuildconfig.staticBuild || mybuildconfig.installStaticLib
+ installDir: mybuildconfig.libInstallDir
+
+ readonly property string _nameUpper : name.replace(" ", "_").toUpperCase()
+ property string libraryMacro: _nameUpper + "_LIBRARY"
+ property string staticLibraryMacro: _nameUpper + "_STATIC_LIBRARY"
+ cpp.defines: mybuildconfig.staticBuild ? [staticLibraryMacro] : [libraryMacro]
+ cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined
+
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: [exportingProduct.sourceDirectory]
+ cpp.defines: exportingProduct.mybuildconfig.staticBuild
+ ? [exportingProduct.staticLibraryMacro] : []
+ }
+
+ Depends { name: "bundle" }
+ bundle.isBundle: false
+}
+// ![0]
diff --git a/tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs b/tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs
new file mode 100644
index 000000000..7aed8f7eb
--- /dev/null
+++ b/tutorial/chapter-9/qbs/modules/mybuildconfig/mybuildconfig.qbs
@@ -0,0 +1,30 @@
+import qbs.FileInfo
+
+//! [0]
+// qbs/modules/mybuildconfig/mybuildconfig.qbs
+Module {
+ Depends { name: "cpp" }
+
+ property string productVersion: "1.0.0"
+ // ...
+ //! [0]
+ property string appInstallDir: "bin"
+ property string libDirName: "lib"
+ property string libInstallDir: qbs.targetOS.contains("windows") ? "bin" : libDirName
+ property bool staticBuild: false
+ property bool installStaticLib: true
+ property bool enableRPath: true
+
+ property stringList libRPaths: {
+ if (enableRPath && cpp.rpathOrigin && product.installDir) {
+ return [
+ FileInfo.joinPaths(
+ cpp.rpathOrigin,
+ FileInfo.relativePath(
+ FileInfo.joinPaths('/', product.installDir),
+ FileInfo.joinPaths('/', libDirName)))
+ ];
+ }
+ return [];
+ }
+}
diff --git a/tutorial/chapter-9/test/test.c b/tutorial/chapter-9/test/test.c
new file mode 100644
index 000000000..1fef24685
--- /dev/null
+++ b/tutorial/chapter-9/test/test.c
@@ -0,0 +1,18 @@
+#include "lib.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ if (argc > 2) {
+ printf("usage: test [value]\n");
+ return 1;
+ }
+ const char *expected = argc == 2 ? argv[1] : "Hello from library";
+ if (strcmp(get_string(), expected) != 0) {
+ printf("text differs\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/tutorial/chapter-9/test/test.qbs b/tutorial/chapter-9/test/test.qbs
new file mode 100644
index 000000000..1e911da47
--- /dev/null
+++ b/tutorial/chapter-9/test/test.qbs
@@ -0,0 +1,5 @@
+MyAutoTest {
+ Depends { name: "mylib" }
+ name: "mytest"
+ files: "test.c"
+}
diff --git a/tutorial/chapter-9/version-header/version-header.qbs b/tutorial/chapter-9/version-header/version-header.qbs
new file mode 100644
index 000000000..0a416d572
--- /dev/null
+++ b/tutorial/chapter-9/version-header/version-header.qbs
@@ -0,0 +1,57 @@
+//! [5]
+// version-header/version-header.qbs
+//! [0]
+import qbs.TextFile
+
+Product {
+ name: "version_header"
+ type: "hpp"
+
+ Depends { name: "mybuildconfig" }
+//! [0]
+
+//! [1]
+ Group {
+ files: ["version.h.in"]
+ fileTags: ["version_h_in"]
+ }
+//! [1]
+
+//! [2]
+ Rule {
+ inputs: ["version_h_in"]
+ Artifact {
+ filePath: "version.h"
+ fileTags: "hpp"
+ }
+//! [2]
+//! [3]
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating " + output.fileName;
+ cmd.highlight = "codegen";
+ cmd.sourceCode = function() {
+ var file = new TextFile(input.filePath, TextFile.ReadOnly);
+ var content = file.readAll();
+
+ content = content.replace(
+ "${PRODUCT_VERSION}",
+ product.mybuildconfig.productVersion);
+
+ file = new TextFile(output.filePath, TextFile.WriteOnly);
+ file.write(content);
+ file.close();
+ }
+ return cmd;
+ }
+//! [3]
+ }
+
+//! [4]
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: exportingProduct.buildDirectory
+ }
+//! [4]
+}
+//! [5]
diff --git a/tutorial/chapter-9/version-header/version.h.in b/tutorial/chapter-9/version-header/version.h.in
new file mode 100644
index 000000000..2e6604967
--- /dev/null
+++ b/tutorial/chapter-9/version-header/version.h.in
@@ -0,0 +1,9 @@
+//! [0]
+// version-header/version.h.in
+#ifndef VERSION_H
+#define VERSION_H
+
+const char kProductVersion[] = "${PRODUCT_VERSION}";
+
+#endif // VERSION_H
+//! [0]